ipsec: Reference count the SAs
[vpp.git] / src / vlibapi / api_shared.c
index 6774e3d..9579fe1 100644 (file)
@@ -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;
 }
 
@@ -360,7 +362,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,7 +395,7 @@ 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 (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
@@ -418,7 +420,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 ();
@@ -433,12 +438,8 @@ msg_handler_internal (api_main_t * am,
     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)
+elog_id_for_msg_name (vlib_main_t * vm, const char *msg_name)
 {
   uword *p, r;
   static uword *h;
@@ -458,7 +459,6 @@ elog_id_for_msg_name (vlib_main_t * vm, char *msg_name)
 
   return r;
 }
-#endif
 
 /* This is only to be called from a vlib/vnet app */
 void
@@ -466,41 +466,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 (vm->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 (&vm->elog_main, e);
+      if (id < vec_len (am->msg_names))
+       ed->c = elog_id_for_msg_name (vm, (const char *) am->msg_names[id]);
+      else
+       ed->c = elog_id_for_msg_name (vm, "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 +534,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 (vm->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 (&vm->elog_main, e);
+      if (id < vec_len (am->msg_names))
+       ed->c = elog_id_for_msg_name (vm, (const char *) am->msg_names[id]);
+      else
+       ed->c = elog_id_for_msg_name (vm, "BOGUS");
+      ed->barrier = is_mp_safe;
+    }
 }
 
 void
@@ -590,7 +617,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 +638,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)))
     {
@@ -624,6 +651,12 @@ vl_msg_api_replay_handler (void *the_msg)
   /* do NOT free the message buffer... */
 }
 
+u32
+vl_msg_api_get_msg_length (void *msg_arg)
+{
+  return vl_msg_api_get_msg_length_inline (msg_arg);
+}
+
 /*
  * vl_msg_api_socket_handler
  */
@@ -653,15 +686,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;
@@ -687,7 +737,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;
@@ -702,6 +752,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)
 {
@@ -713,11 +775,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);
 }
 
@@ -828,7 +890,7 @@ vl_msg_api_set_first_available_msg_id (u16 first_avail)
 }
 
 u16
-vl_msg_api_get_msg_ids (char *name, int n)
+vl_msg_api_get_msg_ids (const char *name, int n)
 {
   api_main_t *am = &api_main;
   u8 *name_copy;
@@ -872,7 +934,7 @@ vl_msg_api_get_msg_ids (char *name, int n)
 }
 
 void
-vl_msg_api_add_msg_name_crc (api_main_t * am, char *string, u32 id)
+vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
 {
   uword *p;
 
@@ -889,6 +951,87 @@ vl_msg_api_add_msg_name_crc (api_main_t * am, 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)
+{
+  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);
+}
+
+/*
+ * 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;
+}
 
 /*
  * fd.io coding-style-patch-verification: ON