api: refactor api data storage

single struct to hold all api handler, flags, etc.
Provide functions to toggle flags instead of writing directly to
internal data.

Type: refactor
Change-Id: I4730d7290e57489de8eda34a72211527e015b721
Signed-off-by: Damjan Marion <damarion@cisco.com>
diff --git a/src/plugins/arping/arping_api.c b/src/plugins/arping/arping_api.c
index e0c47c7..50fbb04 100644
--- a/src/plugins/arping/arping_api.c
+++ b/src/plugins/arping/arping_api.c
@@ -74,7 +74,7 @@
   am->msg_id_base = setup_message_id_table ();
 
   /* Mark API as mp safe */
-  vam->is_mp_safe[am->msg_id_base + VL_API_ARPING] = 1;
+  vl_api_set_msg_thread_safe (vam, am->msg_id_base + VL_API_ARPING, 1);
 
   return 0;
 }
diff --git a/src/plugins/avf/avf_api.c b/src/plugins/avf/avf_api.c
index 366a983..05b4ead 100644
--- a/src/plugins/avf/avf_api.c
+++ b/src/plugins/avf/avf_api.c
@@ -95,7 +95,7 @@
   /* ask for a correctly-sized block of API message decode slots */
   avm->msg_id_base = setup_message_id_table ();
 
-  am->is_mp_safe[avm->msg_id_base + VL_API_AVF_DELETE] = 1;
+  vl_api_set_msg_thread_safe (am, avm->msg_id_base + VL_API_AVF_DELETE, 1);
 
   return 0;
 }
diff --git a/src/plugins/geneve/geneve_api.c b/src/plugins/geneve/geneve_api.c
index d35a1bf..5a98394 100644
--- a/src/plugins/geneve/geneve_api.c
+++ b/src/plugins/geneve/geneve_api.c
@@ -238,8 +238,8 @@
    */
   geneve_base_msg_id = setup_message_id_table ();
 
-  am->api_trace_cfg[VL_API_GENEVE_ADD_DEL_TUNNEL + REPLY_MSG_ID_BASE].size +=
-    16 * sizeof (u32);
+  vl_api_increase_msg_trace_size (
+    am, VL_API_GENEVE_ADD_DEL_TUNNEL + REPLY_MSG_ID_BASE, 16 * sizeof (u32));
 
   return 0;
 }
diff --git a/src/plugins/lacp/lacp_api.c b/src/plugins/lacp/lacp_api.c
index fce2492..fab28cb 100644
--- a/src/plugins/lacp/lacp_api.c
+++ b/src/plugins/lacp/lacp_api.c
@@ -125,7 +125,8 @@
   lm->msg_id_base = setup_message_id_table ();
 
   /* Mark these APIs as mp safe */
-  am->is_mp_safe[lm->msg_id_base + VL_API_SW_INTERFACE_LACP_DUMP] = 1;
+  vl_api_set_msg_thread_safe (
+    am, lm->msg_id_base + VL_API_SW_INTERFACE_LACP_DUMP, 1);
 
   return 0;
 }
diff --git a/src/plugins/tracedump/graph_api.c b/src/plugins/tracedump/graph_api.c
index 0626f7d..20eb1b9 100644
--- a/src/plugins/tracedump/graph_api.c
+++ b/src/plugins/tracedump/graph_api.c
@@ -252,7 +252,7 @@
 
   gmp->msg_id_base = setup_message_id_table ();
 
-  am->is_mp_safe[gmp->msg_id_base + VL_API_GRAPH_NODE_GET] = 1;
+  vl_api_set_msg_thread_safe (am, gmp->msg_id_base + VL_API_GRAPH_NODE_GET, 1);
 
   return 0;
 }
diff --git a/src/plugins/tracedump/tracedump.c b/src/plugins/tracedump/tracedump.c
index f1073fe..17b9a42 100644
--- a/src/plugins/tracedump/tracedump.c
+++ b/src/plugins/tracedump/tracedump.c
@@ -349,7 +349,7 @@
   /* Add our API messages to the global name_crc hash table */
   tdmp->msg_id_base = setup_message_id_table ();
 
-  am->is_mp_safe[tdmp->msg_id_base + VL_API_TRACE_DUMP] = 1;
+  vl_api_set_msg_thread_safe (am, tdmp->msg_id_base + VL_API_TRACE_DUMP, 1);
 
   return error;
 }
diff --git a/src/vlibapi/api.h b/src/vlibapi/api.h
index d290301..f838a80 100644
--- a/src/vlibapi/api.h
+++ b/src/vlibapi/api.h
@@ -124,6 +124,30 @@
 int vl_msg_traverse_trace (vl_api_trace_t *tp, vl_msg_traverse_trace_fn fn,
 			   void *ctx);
 
+always_inline void
+vl_api_increase_msg_trace_size (api_main_t *am, u32 msg_id, u32 inc)
+{
+  am->msg_data[msg_id].trace_size += inc;
+}
+
+always_inline void
+vl_api_set_msg_thread_safe (api_main_t *am, u32 msg_id, int v)
+{
+  am->msg_data[msg_id].is_mp_safe = v != 0;
+}
+
+always_inline void
+vl_api_set_msg_autoendian (api_main_t *am, u32 msg_id, int v)
+{
+  am->msg_data[msg_id].is_autoendian = v != 0;
+}
+
+always_inline void
+vl_api_allow_msg_replay (api_main_t *am, u32 msg_id, int v)
+{
+  am->msg_data[msg_id].replay_allowed = v != 0;
+}
+
 #endif /* included_api_h */
 /*
  * fd.io coding-style-patch-verification: ON
diff --git a/src/vlibapi/api_common.h b/src/vlibapi/api_common.h
index 491ecb8..66a547f 100644
--- a/src/vlibapi/api_common.h
+++ b/src/vlibapi/api_common.h
@@ -81,14 +81,6 @@
 
 #define VL_API_INVALID_FI ((u32)~0)
 
-/** Trace configuration for a single message */
-typedef struct
-{
-  int size;			/**< for sanity checking */
-  int trace_enable;		/**< trace this message  */
-  int replay_enable;		/**< This message can be replayed  */
-} trace_cfg_t;
-
 /**
  * API trace state
  */
@@ -136,11 +128,11 @@
   void *fromjson;		/**< JSON to binary convert function */
   void *calc_size;		/**< message size calculation */
   int size;			/**< message size  */
-  int traced;			/**< is this message to be traced?  */
-  int replay;			/**< is this message to be replayed?  */
-  int message_bounce;		/**< do not free message after processing */
-  int is_mp_safe;		/**< worker thread barrier required?  */
-  int is_autoendian;		/**< endian conversion required?  */
+  int traced : 1;		/**< is this message to be traced?  */
+  int replay : 1;		/**< is this message to be replayed?  */
+  int message_bounce : 1;	/**< do not free message after processing */
+  int is_mp_safe : 1;		/**< worker thread barrier required?  */
+  int is_autoendian : 1;	/**< endian conversion required?  */
 } vl_msg_api_msg_config_t;
 
 /** Message header structure */
@@ -231,48 +223,55 @@
   char name[64];
 } api_version_t;
 
+typedef struct
+{
+  /** Message handler vector  */
+  void (*handler) (void *);
+
+  /** non-default message cleanup handler vector */
+  void (*cleanup_handler) (void *);
+
+  /** Message name vector */
+  const char *name;
+
+  /** Message convert function vector */
+  cJSON *(*tojson_handler) (void *);
+
+  /** Message convert function vector */
+  void *(*fromjson_handler) (cJSON *, int *);
+
+  /** Message endian handler vector */
+  void (*endian_handler) (void *);
+
+  /** Message print function vector */
+  void (*print_handler) (void *, void *);
+
+  /** Message print function vector in JSON */
+  void (*print_json_handler) (void *, void *);
+
+  /** Message calc size function vector */
+  uword (*calc_size_func) (void *);
+
+  /** trace size for sanity checking */
+  int trace_size;
+
+  /** Flags */
+  u8 bounce : 1;	 /**> Don't automatically free message buffer vetor */
+  u8 is_mp_safe : 1;	 /**< Message is mp safe vector */
+  u8 is_autoendian : 1;	 /**< Message requires us to do endian conversion */
+  u8 trace_enable : 1;	 /**< trace this message  */
+  u8 replay_allowed : 1; /**< This message can be replayed  */
+
+} vl_api_msg_data_t;
+
 /** API main structure, used by both vpp and binary API clients */
 typedef struct api_main_t
 {
-  /** Message handler vector  */
-  void (**msg_handlers) (void *);
-
-  /** non-default message cleanup handler vector */
-  void (**msg_cleanup_handlers) (void *);
-
-  /** Message endian handler vector */
-  void (**msg_endian_handlers) (void *);
-
-  /** Message print function vector */
-  void (**msg_print_handlers) (void *, void *);
-
-  /** Message print function vector in JSON */
-  void (**msg_print_json_handlers) (void *, void *);
-
-  /** Message convert function vector */
-  cJSON *(**msg_tojson_handlers) (void *);
-
-  /** Message convert function vector */
-  void *(**msg_fromjson_handlers) (cJSON *, int *);
-
-  /** Message calc size function vector */
-  uword (**msg_calc_size_funcs) (void *);
-
-  /** Message name vector */
-  const char **msg_names;
+  vl_api_msg_data_t *msg_data;
 
   /** API message ID by name hash table */
   uword *msg_id_by_name;
 
-  /** Don't automatically free message buffer vetor */
-  u8 *message_bounce;
-
-  /** Message is mp safe vector */
-  u8 *is_mp_safe;
-
-  /** Message requires us to do endian conversion */
-  u8 *is_autoendian;
-
   /** Allocator ring vectors (in shared memory) */
   struct ring_alloc_ *arings;
 
@@ -294,9 +293,6 @@
   /** Print every received message */
   int msg_print_flag;
 
-  /** Current trace configuration */
-  trace_cfg_t *api_trace_cfg;
-
   /** Current process PID */
   int our_pid;
 
@@ -411,6 +407,14 @@
   return my_api_main;
 }
 
+always_inline vl_api_msg_data_t *
+vl_api_get_msg_data (api_main_t *am, u32 msg_id)
+{
+  if (msg_id >= vec_len (am->msg_data))
+    return 0;
+  return am->msg_data + msg_id;
+}
+
 always_inline void
 vlibapi_set_main (api_main_t * am)
 {
diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h
index 6b5b37a..9c93d33 100644
--- a/src/vlibapi/api_helper_macros.h
+++ b/src/vlibapi/api_helper_macros.h
@@ -30,7 +30,7 @@
 #define _NATIVE_TO_NETWORK(t, rmp)                                            \
   api_main_t *am = vlibapi_get_main ();                                       \
   void (*endian_fp) (void *);                                                 \
-  endian_fp = am->msg_endian_handlers[t + (REPLY_MSG_ID_BASE)];               \
+  endian_fp = am->msg_data[t + (REPLY_MSG_ID_BASE)].endian_handler;           \
   (*endian_fp) (rmp);
 
 #define REPLY_MACRO(msg)                                                      \
diff --git a/src/vlibapi/api_shared.c b/src/vlibapi/api_shared.c
index 17560e5..98da604 100644
--- a/src/vlibapi/api_shared.c
+++ b/src/vlibapi/api_shared.c
@@ -79,13 +79,11 @@
   u8 **old_trace;
   u8 *msg_copy;
   u32 length;
-  trace_cfg_t *cfgp;
   u16 msg_id = clib_net_to_host_u16 (*((u16 *) msg));
+  vl_api_msg_data_t *m = vl_api_get_msg_data (am, msg_id);
   msgbuf_t *header = (msgbuf_t *) (((u8 *) msg) - offsetof (msgbuf_t, data));
 
-  cfgp = am->api_trace_cfg + msg_id;
-
-  if (!cfgp || !cfgp->trace_enable)
+  if (!m || !m->trace_enable)
     return;
 
   msg_copy = 0;
@@ -227,21 +225,18 @@
 {
   u8 *tmpmem = 0;
   int tlen, slen;
-  cJSON *(*tojson_fn) (void *);
 
   u32 msg_length = vec_len (msg);
   vec_validate (tmpmem, msg_length - 1);
   clib_memcpy_fast (tmpmem, msg, msg_length);
   u16 id = clib_net_to_host_u16 (*((u16 *) msg));
+  vl_api_msg_data_t *m = vl_api_get_msg_data (am, id);
 
-  void (*endian_fp) (void *);
-  endian_fp = am->msg_endian_handlers[id];
-  (*endian_fp) (tmpmem);
+  m->endian_handler (tmpmem);
 
-  if (id < vec_len (am->msg_tojson_handlers) && am->msg_tojson_handlers[id])
+  if (m && m->tojson_handler)
     {
-      tojson_fn = am->msg_tojson_handlers[id];
-      cJSON *o = tojson_fn (tmpmem);
+      cJSON *o = m->tojson_handler (tmpmem);
       char *s = cJSON_Print (o);
       slen = strlen (s);
       tlen = fwrite (s, 1, slen, fp);
@@ -503,7 +498,7 @@
 		      int trace_it, int do_it, int free_it)
 {
   u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
-  u8 *(*print_fp) (void *, void *);
+  vl_api_msg_data_t *m = vl_api_get_msg_data (am, id);
 
   if (PREDICT_FALSE (am->elog_trace_api_messages))
     {
@@ -519,51 +514,44 @@
 	u32 c;
       } *ed;
       ed = ELOG_DATA (am->elog_main, e);
-      if (id < vec_len (am->msg_names) && am->msg_names[id])
-	ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
+      if (m && m->name)
+	ed->c = elog_string (am->elog_main, (char *) m->name);
       else
 	ed->c = elog_string (am->elog_main, "BOGUS");
     }
 
-  if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
+  if (m && m->handler)
     {
       if (trace_it)
 	vl_msg_api_trace (am, am->rx_trace, the_msg);
 
       if (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]\n");
-	    }
+	  fformat (stdout, "[%d]: %s\n", id, m->name);
+	  if (m->print_handler)
+	    m->print_handler (the_msg, stdout);
 	  else
-	    {
-	      (*print_fp) (the_msg, stdout);
-	    }
+	    fformat (stdout, "  [no registered print fn]\n");
 	}
 
       uword calc_size = 0;
-      uword (*calc_size_fp) (void *);
-      calc_size_fp = am->msg_calc_size_funcs[id];
-      ASSERT (NULL != calc_size_fp);
-      if (calc_size_fp)
+      ASSERT (NULL != m->calc_size_func);
+      if (m->calc_size_func)
 	{
-	  calc_size = (*calc_size_fp) (the_msg);
+	  calc_size = m->calc_size_func (the_msg);
 	  if (calc_size > msg_len)
 	    {
 	      clib_warning (
 		"Truncated message '%s' (id %u) received, calculated size "
 		"%lu is bigger than actual size %llu, message dropped.",
-		am->msg_names[id], id, calc_size, msg_len);
+		m->name, id, calc_size, msg_len);
 	    }
 	}
       else
 	{
 	  clib_warning ("Message '%s' (id %u) has NULL calc_size_func, cannot "
 			"verify message size is correct",
-			am->msg_names[id], id);
+			m->name, id);
 	}
 
       /* don't process message if it's truncated, otherwise byte swaps
@@ -572,30 +560,26 @@
       if (do_it && calc_size <= msg_len)
 	{
 
-	  if (!am->is_mp_safe[id])
+	  if (!m->is_mp_safe)
 	    {
 	      vl_msg_api_barrier_trace_context (am->msg_names[id]);
 	      vl_msg_api_barrier_sync ();
 	    }
 
-	  if (am->is_autoendian[id])
-	    {
-	      void (*endian_fp) (void *);
-	      endian_fp = am->msg_endian_handlers[id];
-	      (*endian_fp) (the_msg);
-	    }
+	  if (m->is_autoendian)
+	    m->endian_handler (the_msg);
 
 	  if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
 	    clib_call_callbacks (am->perf_counter_cbs, am, id,
 				 0 /* before */ );
 
-	  (*am->msg_handlers[id]) (the_msg);
+	  m->handler (the_msg);
 
 	  if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
 	    clib_call_callbacks (am->perf_counter_cbs, am, id,
 				 1 /* after */ );
 
-	  if (!am->is_mp_safe[id])
+	  if (!m->is_mp_safe)
 	    vl_msg_api_barrier_release ();
 	}
     }
@@ -629,10 +613,10 @@
 	u32 c;
       } *ed;
       ed = ELOG_DATA (am->elog_main, e);
-      if (id < vec_len (am->msg_names) && am->msg_names[id])
+      if (m && m->name)
 	{
-	  ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
-	  ed->barrier = !am->is_mp_safe[id];
+	  ed->c = elog_string (am->elog_main, (char *) m->name);
+	  ed->barrier = !m->is_mp_safe;
 	}
       else
 	{
@@ -693,14 +677,16 @@
 {
   api_main_t *am = vlibapi_get_main ();
   u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
+  vl_api_msg_data_t *m = vl_api_get_msg_data (am, id);
 
-  if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers)))
+  if (PREDICT_FALSE (!m))
     {
       clib_warning ("_vl_msg_id too large: %d\n", id);
       return;
     }
-  if (am->msg_cleanup_handlers[id])
-    (*am->msg_cleanup_handlers[id]) (the_msg);
+
+  if (m->cleanup_handler)
+    m->cleanup_handler (the_msg);
 
   vl_msg_api_free (the_msg);
 }
@@ -712,17 +698,17 @@
 vl_msg_api_replay_handler (void *the_msg)
 {
   api_main_t *am = vlibapi_get_main ();
-
   u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
+  vl_api_msg_data_t *m = vl_api_get_msg_data (am, id);
 
-  if (PREDICT_FALSE (id >= vec_len (am->msg_handlers)))
+  if (PREDICT_FALSE (!m))
     {
       clib_warning ("_vl_msg_id too large: %d\n", id);
       return;
     }
   /* do NOT trace the message... */
-  if (am->msg_handlers[id])
-    (*am->msg_handlers[id]) (the_msg);
+  if (m->handler)
+    m->handler (the_msg);
   /* do NOT free the message buffer... */
 }
 
@@ -745,25 +731,11 @@
 			1 /* do_it */, 0 /* free_it */);
 }
 
-#define foreach_msg_api_vector                                                \
-  _ (msg_names)                                                               \
-  _ (msg_handlers)                                                            \
-  _ (msg_cleanup_handlers)                                                    \
-  _ (msg_endian_handlers)                                                     \
-  _ (msg_print_handlers)                                                      \
-  _ (msg_print_json_handlers)                                                 \
-  _ (msg_tojson_handlers)                                                     \
-  _ (msg_fromjson_handlers)                                                   \
-  _ (msg_calc_size_funcs)                                                     \
-  _ (api_trace_cfg)                                                           \
-  _ (message_bounce)                                                          \
-  _ (is_mp_safe)                                                              \
-  _ (is_autoendian)
-
 void
 vl_msg_api_config (vl_msg_api_msg_config_t * c)
 {
   api_main_t *am = vlibapi_get_main ();
+  vl_api_msg_data_t *m;
 
   /*
    * This happens during the java core tests if the message
@@ -782,32 +754,30 @@
       return;
     }
 
-#define _(a) vec_validate (am->a, c->id);
-  foreach_msg_api_vector;
-#undef _
+  vec_validate (am->msg_data, c->id);
+  m = vl_api_get_msg_data (am, c->id);
 
-  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);
+  if (m->handler && m->handler != c->handler)
+    clib_warning ("BUG: re-registering 'vl_api_%s_t_handler'."
+		  "Handler was %llx, replaced by %llx",
+		  c->name, m->handler, c->handler);
 
-  am->msg_names[c->id] = c->name;
-  am->msg_handlers[c->id] = c->handler;
-  am->msg_cleanup_handlers[c->id] = c->cleanup;
-  am->msg_endian_handlers[c->id] = c->endian;
-  am->msg_print_handlers[c->id] = c->print;
-  am->msg_print_json_handlers[c->id] = c->print_json;
-  am->msg_tojson_handlers[c->id] = c->tojson;
-  am->msg_fromjson_handlers[c->id] = c->fromjson;
-  am->msg_calc_size_funcs[c->id] = c->calc_size;
-  am->message_bounce[c->id] = c->message_bounce;
-  am->is_mp_safe[c->id] = c->is_mp_safe;
-  am->is_autoendian[c->id] = c->is_autoendian;
+  m->name = c->name;
+  m->handler = c->handler;
+  m->cleanup_handler = c->cleanup;
+  m->endian_handler = c->endian;
+  m->print_handler = c->print;
+  m->print_json_handler = c->print_json;
+  m->tojson_handler = c->tojson;
+  m->fromjson_handler = c->fromjson;
+  m->calc_size_func = c->calc_size;
+  m->bounce = c->message_bounce;
+  m->is_mp_safe = c->is_mp_safe;
+  m->is_autoendian = c->is_autoendian;
 
-  am->api_trace_cfg[c->id].size = c->size;
-  am->api_trace_cfg[c->id].trace_enable = c->traced;
-  am->api_trace_cfg[c->id].replay_enable = c->replay;
+  m->trace_size = c->size;
+  m->trace_enable = c->traced;
+  m->replay_allowed = c->replay;
 
   if (!am->msg_id_by_name)
     am->msg_id_by_name = hash_create_string (0, sizeof (uword));
@@ -864,10 +834,10 @@
 vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
 {
   api_main_t *am = vlibapi_get_main ();
+  vl_api_msg_data_t *m = vl_api_get_msg_data (am, msg_id);
   ASSERT (msg_id > 0);
 
-  vec_validate (am->msg_cleanup_handlers, msg_id);
-  am->msg_cleanup_handlers[msg_id] = fp;
+  m->cleanup_handler = fp;
 }
 
 void
diff --git a/src/vlibmemory/memclnt_api.c b/src/vlibmemory/memclnt_api.c
index 289a4c5..9e2971a 100644
--- a/src/vlibmemory/memclnt_api.c
+++ b/src/vlibmemory/memclnt_api.c
@@ -193,8 +193,8 @@
   foreach_vlib_api_msg;
 #undef _
 
-  am->is_mp_safe[VL_API_CONTROL_PING] = 1;
-  am->is_mp_safe[VL_API_CONTROL_PING_REPLY] = 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;
 }
@@ -727,10 +727,10 @@
   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 ecdcc72..80d8628 100644
--- a/src/vlibmemory/memory_api.c
+++ b/src/vlibmemory/memory_api.c
@@ -532,9 +532,9 @@
    * 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);
 
@@ -768,6 +768,7 @@
 				 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 *);
   u8 *(*print_fp) (void *, void *);
   svm_region_t *old_vlib_rp;
@@ -785,23 +786,23 @@
 	u32 c;
       } * ed;
       ed = ELOG_DATA (am->elog_main, e);
-      if (id < vec_len (am->msg_names) && am->msg_names[id])
-	ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
+      if (m && m->name)
+	ed->c = elog_string (am->elog_main, (char *) m->name);
       else
 	ed->c = elog_string (am->elog_main, "BOGUS");
     }
 
-  if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
+  if (m && m->handler)
     {
-      handler = (void *) am->msg_handlers[id];
+      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, am->msg_names[id]);
-	  print_fp = (void *) am->msg_print_handlers[id];
+	  fformat (stdout, "[%d]: %s\n", id, m->name);
+	  print_fp = (void *) am->msg_data[id].print_handler;
 	  if (print_fp == 0)
 	    {
 	      fformat (stdout, "  [no registered print fn for msg %d]\n", id);
@@ -811,11 +812,11 @@
 	      (*print_fp) (the_msg, vm);
 	    }
 	}
-      is_mp_safe = am->is_mp_safe[id];
+      is_mp_safe = am->msg_data[id].is_mp_safe;
 
       if (!is_mp_safe)
 	{
-	  vl_msg_api_barrier_trace_context (am->msg_names[id]);
+	  vl_msg_api_barrier_trace_context (am->msg_data[id].name);
 	  vl_msg_api_barrier_sync ();
 	}
       if (is_private)
@@ -829,10 +830,10 @@
       if (PREDICT_FALSE (vl_mem_api_fuzz_hook != 0))
 	(*vl_mem_api_fuzz_hook) (id, the_msg);
 
-      if (am->is_autoendian[id])
+      if (m->is_autoendian)
 	{
 	  void (*endian_fp) (void *);
-	  endian_fp = am->msg_endian_handlers[id];
+	  endian_fp = am->msg_data[id].endian_handler;
 	  (*endian_fp) (the_msg);
 	}
       if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
@@ -859,7 +860,7 @@
    * Special-case, so we can e.g. bounce messages off the vnet
    * main thread without copying them...
    */
-  if (id >= vec_len (am->message_bounce) || !(am->message_bounce[id]))
+  if (!m || !m->bounce)
     {
       if (is_private)
 	{
@@ -892,8 +893,8 @@
 	u32 c;
       } * ed;
       ed = ELOG_DATA (am->elog_main, e);
-      if (id < vec_len (am->msg_names) && am->msg_names[id])
-	ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
+      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;
diff --git a/src/vlibmemory/memory_client.c b/src/vlibmemory/memory_client.c
index 585fca6..330390e 100644
--- a/src/vlibmemory/memory_client.c
+++ b/src/vlibmemory/memory_client.c
@@ -377,7 +377,7 @@
     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_api_##n##_t_calc_size);                       \
-  am->api_trace_cfg[VL_API_##N].replay_enable = 0;
+  am->msg_data[VL_API_##N].replay_allowed = 0;
   foreach_api_msg;
 #undef _
 }
@@ -562,6 +562,8 @@
   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;
@@ -574,12 +576,11 @@
   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;
-  if (!am->msg_calc_size_funcs[VL_API_GET_FIRST_MSG_ID_REPLY])
+  old_handler = m->handler;
+  m->handler = (void *) vl_api_get_first_msg_id_reply_t_handler;
+  if (!m->calc_size_func)
     {
-      am->msg_calc_size_funcs[VL_API_GET_FIRST_MSG_ID_REPLY] =
+      m->calc_size_func =
 	(uword (*) (void *)) vl_api_get_first_msg_id_reply_t_calc_size;
     }
 
@@ -608,7 +609,7 @@
 
     sock_err:
       /* Restore old handler */
-      am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler;
+      m->handler = old_handler;
 
       return -1;
     }
@@ -633,7 +634,7 @@
 	    }
 	}
       /* Restore old handler */
-      am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler;
+      m->handler = old_handler;
 
       return rv;
     }
@@ -641,7 +642,7 @@
 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_shared.c b/src/vlibmemory/memory_shared.c
index b70f45f..77a610b 100644
--- a/src/vlibmemory/memory_shared.c
+++ b/src/vlibmemory/memory_shared.c
@@ -117,14 +117,16 @@
 		  if (CLIB_DEBUG > 0)
 		    {
 		      u16 *msg_idp, msg_id;
+		      vl_api_msg_data_t *m;
 		      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))
+		      m = vl_api_get_msg_data (am, msg_id);
+		      if (m)
 			clib_warning ("msg id %d name %s", (u32) msg_id,
-				      vlibapi_get_main ()->msg_names[msg_id]);
+				      m->name);
 		    }
 		  shmem_hdr->garbage_collects++;
 		  goto collected;
@@ -731,10 +733,7 @@
 
   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);
+  vec_free (am->msg_data);
 }
 
 void
diff --git a/src/vlibmemory/socket_api.c b/src/vlibmemory/socket_api.c
index 3df182b..e451d62 100644
--- a/src/vlibmemory/socket_api.c
+++ b/src/vlibmemory/socket_api.c
@@ -132,7 +132,7 @@
   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);
@@ -802,7 +802,7 @@
     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, vl_api_##n##_t_calc_size);                       \
-  am->api_trace_cfg[VL_API_##N].replay_enable = 0;
+  am->msg_data[VL_API_##N].replay_allowed = 0;
   foreach_vlib_api_msg;
 #undef _
 
diff --git a/src/vlibmemory/vlib_api.c b/src/vlibmemory/vlib_api.c
index b598f0b..3d4f882 100644
--- a/src/vlibmemory/vlib_api.c
+++ b/src/vlibmemory/vlib_api.c
@@ -340,7 +340,7 @@
    */
   msg_id_base = setup_message_id_table ();
 
-  am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
+  vl_api_set_msg_thread_safe (am, VL_API_GET_NODE_GRAPH, 1);
   return 0;
 }
 
diff --git a/src/vlibmemory/vlib_api_cli.c b/src/vlibmemory/vlib_api_cli.c
index 39e2250..084080f 100644
--- a/src/vlibmemory/vlib_api_cli.c
+++ b/src/vlibmemory/vlib_api_cli.c
@@ -242,20 +242,19 @@
     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);
 	}
     }
 
@@ -510,7 +509,7 @@
       assert_size (file_size_left, clib_max (size, sizeof (u16)));
       msg_id = ntohs (*((u16 *) msg));
       if (msg_id >= vec_len (msgid_vec) ||
-	  msgid_vec[msg_id] >= vec_len (am->api_trace_cfg))
+	  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);
 
@@ -522,7 +521,7 @@
 
   for (; i <= last_index; i++)
     {
-      trace_cfg_t *cfgp;
+      vl_api_msg_data_t *m;
       u16 msg_id;
       int size;
 
@@ -537,7 +536,7 @@
       msg_id = ntohs (*((u16 *) msg));
 
       if (msg_id >= vec_len (msgid_vec) ||
-	  msgid_vec[msg_id] >= vec_len (am->api_trace_cfg))
+	  msgid_vec[msg_id] >= vec_len (am->msg_data))
 	{
 	  vlib_cli_output (
 	    vm, "warning: unknown msg id %d for msg number %d, skipping\n",
@@ -547,7 +546,7 @@
 	}
 
       msg_id = msgid_vec[msg_id];
-      cfgp = am->api_trace_cfg + 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));
@@ -561,9 +560,7 @@
       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);
@@ -571,8 +568,7 @@
 	      am->replay_in_progress = 0;
 	      return;
 	    }
-	  endian_fp = am->msg_endian_handlers[msg_id];
-	  (*endian_fp) (tmpbuf + sizeof (uword));
+	  m->endian_handler (tmpbuf + sizeof (uword));
 	}
 
       /* msg_id always in network byte order */
@@ -585,13 +581,9 @@
       switch (which)
 	{
 	case DUMP_JSON:
-	  if (msg_id < vec_len (am->msg_print_json_handlers) &&
-	      am->msg_print_json_handlers[msg_id])
+	  if (m && m->print_json_handler)
 	    {
-	      u8 *(*print_fp) (void *, void *);
-
-	      print_fp = (void *) am->msg_print_json_handlers[msg_id];
-	      (*print_fp) (tmpbuf + sizeof (uword), vm);
+	      m->print_json_handler (tmpbuf + sizeof (uword), vm);
 	    }
 	  else
 	    {
@@ -602,13 +594,9 @@
 	  break;
 
 	case DUMP:
-	  if (msg_id < vec_len (am->msg_print_handlers) &&
-	      am->msg_print_handlers[msg_id])
+	  if (m && m->print_handler)
 	    {
-	      u8 *(*print_fp) (void *, void *);
-
-	      print_fp = (void *) am->msg_print_handlers[msg_id];
-	      (*print_fp) (tmpbuf + sizeof (uword), vm);
+	      m->print_handler (tmpbuf + sizeof (uword), vm);
 	    }
 	  else
 	    {
@@ -619,25 +607,20 @@
 	  break;
 
 	case INITIALIZERS:
-	  if (msg_id < vec_len (am->msg_print_handlers) &&
-	      am->msg_print_handlers[msg_id])
+	  if (m && m->print_handler)
 	    {
 	      u8 *s;
 	      int j;
-	      u8 *(*print_fp) (void *, void *);
-
-	      print_fp = (void *) am->msg_print_handlers[msg_id];
 
 	      vlib_cli_output (vm, "/*");
 
-	      (*print_fp) (tmpbuf + sizeof (uword), vm);
+	      m->print_handler (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    ");
@@ -650,22 +633,17 @@
 	  break;
 
 	case REPLAY:
-	  if (msg_id < vec_len (am->msg_print_handlers) &&
-	      am->msg_print_handlers[msg_id] && cfgp->replay_enable)
+	  if (m && m->print_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->replay_allowed)
 		vlib_cli_output (vm, "Skipping msg id %d: no handler\n",
 				 msg_id);
 	      break;
@@ -708,11 +686,17 @@
   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);
+  void (*handler) (void *, void *) = 0;
   u8 is_json = a->is_json;
   u8 *tmpbuf = 0;
 
+  if (!m)
+    {
+      vlib_cli_output (a->vm, "Unknown msg id %d\n", msg_id);
+      return 0;
+    }
+
   if (clib_arch_is_little_endian)
     {
       u32 msg_length = vec_len (msg);
@@ -720,25 +704,15 @@
       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);
     }
 
-  if (is_json)
-    handlers = am->msg_print_json_handlers;
-  else
-    handlers = am->msg_print_handlers;
+  handler = is_json ? m->print_json_handler : m->print_handler;
 
-  if (msg_id < vec_len (handlers) && handlers[msg_id])
-    {
-      print_fp = (void *) handlers[msg_id];
-      (*print_fp) (msg, a->vm);
-    }
+  if (handler)
+    handler (msg, a->vm);
   else
-    {
-      vlib_cli_output (a->vm, "Skipping msg id %d: no print fcn\n", msg_id);
-    }
+    vlib_cli_output (a->vm, "Skipping msg id %d: no print fcn\n", msg_id);
 
   vec_free (tmpbuf);
   return 0;
@@ -825,9 +799,8 @@
 {
   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");
@@ -849,6 +822,7 @@
 
   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);
@@ -862,28 +836,19 @@
     }
   vec_free (name_crc);
 
-  cfgp = am->api_trace_cfg + msg_id;
-  if (!am->api_trace_cfg)
+  if (m->replay_allowed)
     {
-      vlib_cli_output (vm, "msg id %d no trace config\n", msg_id);
-      return rv;
-    }
-
-  if (cfgp->replay_enable)
-    {
-
       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",
@@ -892,24 +857,18 @@
 	}
 
       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);
 
-      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])
+      if (!m->is_mp_safe)
 	vl_msg_api_barrier_sync ();
-      (*handler) (msg, vm);
-      if (!am->is_mp_safe[msg_id])
+      m->handler (msg);
+      if (!m->is_mp_safe)
 	vl_msg_api_barrier_release ();
     }
 
diff --git a/src/vnet/classify/classify_api.c b/src/vnet/classify/classify_api.c
index 0f9243c..53e3cb6 100644
--- a/src/vnet/classify/classify_api.c
+++ b/src/vnet/classify/classify_api.c
@@ -966,9 +966,10 @@
   /*
    * Trace space for classifier mask+match
    */
-  am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
-  am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size +=
-    5 * sizeof (u32x4);
+  vl_api_increase_msg_trace_size (am, VL_API_CLASSIFY_ADD_DEL_TABLE,
+				  5 * sizeof (u32x4));
+  vl_api_increase_msg_trace_size (am, VL_API_CLASSIFY_ADD_DEL_SESSION,
+				  5 * sizeof (u32x4));
 
   /*
    * Set up the (msg_name, crc, message-id) table
diff --git a/src/vnet/devices/virtio/vhost_user_api.c b/src/vnet/devices/virtio/vhost_user_api.c
index 6dd9da0..cc1896b 100644
--- a/src/vnet/devices/virtio/vhost_user_api.c
+++ b/src/vnet/devices/virtio/vhost_user_api.c
@@ -330,8 +330,8 @@
 {
   api_main_t *am = vlibapi_get_main ();
   /* Mark CREATE_VHOST_USER_IF as mp safe */
-  am->is_mp_safe[VL_API_CREATE_VHOST_USER_IF] = 1;
-  am->is_mp_safe[VL_API_CREATE_VHOST_USER_IF_V2] = 1;
+  vl_api_set_msg_thread_safe (am, VL_API_CREATE_VHOST_USER_IF, 1);
+  vl_api_set_msg_thread_safe (am, VL_API_CREATE_VHOST_USER_IF_V2, 1);
 
   /*
    * Set up the (msg_name, crc, message-id) table
diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c
index 29f98f7..5766f2c 100644
--- a/src/vnet/interface_api.c
+++ b/src/vnet/interface_api.c
@@ -1630,21 +1630,24 @@
   REPLY_MSG_ID_BASE = setup_message_id_table ();
 
   /* Mark these APIs as mp safe */
-  am->is_mp_safe[REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP] = 1;
-  am->is_mp_safe[REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DETAILS] = 1;
-  am->is_mp_safe[REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TAG_ADD_DEL] = 1;
-  am->is_mp_safe[REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_INTERFACE_NAME] =
-    1;
+  vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP,
+			      1);
+  vl_api_set_msg_thread_safe (
+    am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DETAILS, 1);
+  vl_api_set_msg_thread_safe (
+    am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TAG_ADD_DEL, 1);
+  vl_api_set_msg_thread_safe (
+    am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_INTERFACE_NAME, 1);
 
   /* Do not replay VL_API_SW_INTERFACE_DUMP messages */
-  am->api_trace_cfg[REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP]
-    .replay_enable = 0;
+  vl_api_allow_msg_replay (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP,
+			   0);
 
   /* Mark these APIs as autoendian */
-  am->is_autoendian[REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_TX_PLACEMENT] =
-    1;
-  am->is_autoendian[REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TX_PLACEMENT_GET] =
-    1;
+  vl_api_set_msg_autoendian (
+    am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_TX_PLACEMENT, 1);
+  vl_api_set_msg_autoendian (
+    am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TX_PLACEMENT_GET, 1);
 
   return 0;
 }
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index ae4ee0c..e03b010 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -2119,10 +2119,10 @@
   /*
    * Mark the route add/del API as MP safe
    */
-  am->is_mp_safe[VL_API_IP_ROUTE_ADD_DEL] = 1;
-  am->is_mp_safe[VL_API_IP_ROUTE_ADD_DEL_REPLY] = 1;
-  am->is_mp_safe[VL_API_IP_ROUTE_ADD_DEL_V2] = 1;
-  am->is_mp_safe[VL_API_IP_ROUTE_ADD_DEL_V2_REPLY] = 1;
+  vl_api_set_msg_thread_safe (am, VL_API_IP_ROUTE_ADD_DEL, 1);
+  vl_api_set_msg_thread_safe (am, VL_API_IP_ROUTE_ADD_DEL_REPLY, 1);
+  vl_api_set_msg_thread_safe (am, VL_API_IP_ROUTE_ADD_DEL_V2, 1);
+  vl_api_set_msg_thread_safe (am, VL_API_IP_ROUTE_ADD_DEL_V2_REPLY, 1);
 
   /*
    * Set up the (msg_name, crc, message-id) table
diff --git a/src/vnet/l2/l2_api.c b/src/vnet/l2/l2_api.c
index 5a0432d..c555a17 100644
--- a/src/vnet/l2/l2_api.c
+++ b/src/vnet/l2/l2_api.c
@@ -1281,7 +1281,7 @@
   api_main_t *am = vlibapi_get_main ();
 
   /* Mark VL_API_BRIDGE_DOMAIN_DUMP as mp safe */
-  am->is_mp_safe[VL_API_BRIDGE_DOMAIN_DUMP] = 1;
+  vl_api_set_msg_thread_safe (am, VL_API_BRIDGE_DOMAIN_DUMP, 1);
 
   /*
    * Set up the (msg_name, crc, message-id) table
diff --git a/src/vnet/mpls/mpls_api.c b/src/vnet/mpls/mpls_api.c
index 4efb617..fac5282 100644
--- a/src/vnet/mpls/mpls_api.c
+++ b/src/vnet/mpls/mpls_api.c
@@ -508,7 +508,8 @@
   /*
    * Trace space for 8 MPLS encap labels
    */
-  am->api_trace_cfg[VL_API_MPLS_TUNNEL_ADD_DEL].size += 8 * sizeof (u32);
+  vl_api_increase_msg_trace_size (am, VL_API_MPLS_TUNNEL_ADD_DEL,
+				  8 * sizeof (u32));
 
   /*
    * Set up the (msg_name, crc, message-id) table
diff --git a/src/vnet/vxlan-gpe/vxlan_gpe_api.c b/src/vnet/vxlan-gpe/vxlan_gpe_api.c
index 9423b27..e9cf17f 100644
--- a/src/vnet/vxlan-gpe/vxlan_gpe_api.c
+++ b/src/vnet/vxlan-gpe/vxlan_gpe_api.c
@@ -342,8 +342,8 @@
 {
   api_main_t *am = vlibapi_get_main ();
 
-  am->api_trace_cfg[VL_API_VXLAN_GPE_ADD_DEL_TUNNEL].size +=
-    17 * sizeof (u32);
+  vl_api_increase_msg_trace_size (am, VL_API_VXLAN_GPE_ADD_DEL_TUNNEL,
+				  17 * sizeof (u32));
 
   /*
    * Set up the (msg_name, crc, message-id) table
diff --git a/src/vnet/vxlan/vxlan_api.c b/src/vnet/vxlan/vxlan_api.c
index c97597a..56fd654 100644
--- a/src/vnet/vxlan/vxlan_api.c
+++ b/src/vnet/vxlan/vxlan_api.c
@@ -354,7 +354,8 @@
 {
   api_main_t *am = vlibapi_get_main ();
 
-  am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
+  vl_api_increase_msg_trace_size (am, VL_API_VXLAN_ADD_DEL_TUNNEL,
+				  16 * sizeof (u32));
 
   /*
    * Set up the (msg_name, crc, message-id) table