misc: fix tracedump API to match CLI behavior
[vpp.git] / src / plugins / tracedump / tracedump.c
index 0f1612c..0c0f3b4 100644 (file)
@@ -335,6 +335,143 @@ doublebreak:;
   vec_free (s);
 }
 
+/* API message handler */
+static void
+vl_api_trace_v2_dump_t_handler (vl_api_trace_v2_dump_t *mp)
+{
+  vl_api_registration_t *rp;
+  vl_api_trace_v2_details_t *dmp;
+  tracedump_main_t *tdmp = &tracedump_main;
+  vlib_trace_header_t ***client_trace_cache, **th;
+  int i, j;
+  u32 client_index;
+  u32 first_position, max, first_thread_id, last_thread_id;
+  u32 n_threads = vlib_get_n_threads ();
+  u8 *s = 0;
+
+  rp = vl_api_client_index_to_registration (mp->client_index);
+  if (rp == 0)
+    return;
+
+  client_index = rp->vl_api_registration_pool_index;
+
+  vec_validate_init_empty (tdmp->traces, client_index, 0);
+
+  client_trace_cache = tdmp->traces[client_index];
+
+  if (mp->clear_cache)
+    {
+      toss_client_cache (tdmp, client_index, client_trace_cache);
+      client_trace_cache = 0;
+    }
+
+  /* Now, where were we? */
+  first_thread_id = last_thread_id = clib_net_to_host_u32 (mp->thread_id);
+  first_position = clib_net_to_host_u32 (mp->position);
+  max = clib_net_to_host_u32 (mp->max);
+
+  if (first_thread_id == ~0)
+    {
+      first_thread_id = 0;
+      last_thread_id = n_threads - 1;
+    }
+
+  /* Don't overflow the existing queue space for shared memory API clients. */
+  if (rp->vl_input_queue)
+    {
+      svm_queue_t *q = rp->vl_input_queue;
+      u32 queue_slots_available = q->maxsize - q->cursize;
+      int chunk = (queue_slots_available > 0) ? queue_slots_available - 1 : 0;
+      /* split available slots among requested threads */
+      if (chunk < max * (last_thread_id - first_thread_id + 1))
+       max = chunk / (last_thread_id - first_thread_id + 1);
+    }
+
+  /* Need a fresh cache for this client? */
+  if (vec_len (client_trace_cache) == 0 && first_position != ~0)
+    {
+      vlib_worker_thread_barrier_sync (vlib_get_first_main ());
+
+      /* Make a slot for each worker thread */
+      vec_validate (client_trace_cache, n_threads - 1);
+      i = 0;
+
+      foreach_vlib_main ()
+       {
+         vlib_trace_main_t *tm = &this_vlib_main->trace_main;
+
+         /* Filter as directed */
+         trace_apply_filter (this_vlib_main);
+
+         pool_foreach (th, tm->trace_buffer_pool)
+           {
+             vec_add1 (client_trace_cache[i], th[0]);
+           }
+
+         /* Sort them by increasing time. */
+         if (vec_len (client_trace_cache[i]))
+           vec_sort_with_function (client_trace_cache[i], trace_cmp);
+
+         i++;
+       }
+      vlib_worker_thread_barrier_release (vlib_get_first_main ());
+    }
+
+  /* Save the cache, one way or the other */
+  tdmp->traces[client_index] = client_trace_cache;
+
+  for (i = first_thread_id; i <= last_thread_id; i++)
+    {
+      // dump a number of 'max' packets per thead
+      for (j = first_position;
+          j < vec_len (client_trace_cache[i]) && j < first_position + max;
+          j++)
+       {
+         th = &client_trace_cache[i][j];
+
+         vec_reset_length (s);
+
+         s =
+           format (s, "%U", format_vlib_trace, vlib_get_first_main (), th[0]);
+
+         dmp = vl_msg_api_alloc (sizeof (*dmp) + vec_len (s));
+         dmp->_vl_msg_id =
+           htons (VL_API_TRACE_V2_DETAILS + (tdmp->msg_id_base));
+         dmp->context = mp->context;
+         dmp->thread_id = ntohl (i);
+         dmp->position = ntohl (j);
+         dmp->more = j < vec_len (client_trace_cache[i]) - 1;
+         vl_api_vec_to_api_string (s, &dmp->trace_data);
+
+         vl_api_send_msg (rp, (u8 *) dmp);
+       }
+    }
+
+  vec_free (s);
+}
+
+static void
+vl_api_trace_clear_cache_t_handler (vl_api_trace_clear_cache_t *mp)
+{
+  vl_api_registration_t *rp;
+  tracedump_main_t *tdmp = &tracedump_main;
+  vlib_trace_header_t ***client_trace_cache;
+  vl_api_trace_clear_cache_reply_t *rmp;
+  u32 client_index;
+
+  rp = vl_api_client_index_to_registration (mp->client_index);
+  if (rp == 0)
+    return;
+
+  client_index = rp->vl_api_registration_pool_index;
+  vec_validate_init_empty (tdmp->traces, client_index, 0);
+  client_trace_cache = tdmp->traces[client_index];
+  toss_client_cache (tdmp, client_index, client_trace_cache);
+
+  int rv = 0;
+  REPLY_MACRO (VL_API_TRACE_CLEAR_CACHE_REPLY);
+}
+
 /* API definitions */
 #include <tracedump/tracedump.api.c>
 
@@ -353,6 +490,7 @@ tracedump_init (vlib_main_t * vm)
   tdmp->msg_id_base = setup_message_id_table ();
 
   vl_api_set_msg_thread_safe (am, tdmp->msg_id_base + VL_API_TRACE_DUMP, 1);
+  vl_api_set_msg_thread_safe (am, tdmp->msg_id_base + VL_API_TRACE_V2_DUMP, 1);
 
   return error;
 }