vlib: introduce vlib_get_main_by_index(), vlib_get_n_threads()
[vpp.git] / src / plugins / tracedump / tracedump.c
index 87e6cf6..7c83ba2 100644 (file)
 
 tracedump_main_t tracedump_main;
 
+
+static void
+vl_api_trace_set_filters_t_handler (vl_api_trace_set_filters_t * mp)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  tracedump_main_t *tdmp = &tracedump_main;
+  u32 node_index = clib_net_to_host_u32 (mp->node_index);
+  u32 flag = clib_net_to_host_u32 (mp->flag);
+  u32 count = clib_net_to_host_u32 (mp->count);
+  vl_api_trace_set_filters_reply_t *rmp;
+  int rv = 0;
+
+  if (flag == TRACE_FF_NONE)
+    {
+      count = node_index = 0;
+    }
+  else if (flag != TRACE_FF_INCLUDE_NODE && flag != TRACE_FF_EXCLUDE_NODE)
+    {
+      rv = VNET_API_ERROR_INVALID_VALUE;
+      goto done;
+    }
+
+  vlib_node_t *node;
+  node = vlib_get_node (vm, node_index);
+  if (!node)
+    {
+      rv = VNET_API_ERROR_NO_SUCH_NODE;
+      goto done;
+    }
+
+  trace_filter_set (node_index, flag, count);
+
+done:
+  REPLY_MACRO (VL_API_TRACE_SET_FILTERS_REPLY);
+}
+
+
+static void
+vl_api_trace_capture_packets_t_handler (vl_api_trace_capture_packets_t * mp)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  tracedump_main_t *tdmp = &tracedump_main;
+  u32 add = clib_net_to_host_u32 (mp->max_packets);
+  u32 node_index = clib_net_to_host_u32 (mp->node_index);
+  u8 filter = mp->use_filter;
+  u8 verbose = mp->verbose;
+  u8 pre_clear = mp->pre_capture_clear;
+  vl_api_trace_capture_packets_reply_t *rmp;
+  int rv = 0;
+
+  if (!vnet_trace_placeholder)
+    vec_validate_aligned (vnet_trace_placeholder, 2048,
+                         CLIB_CACHE_LINE_BYTES);
+
+  vlib_node_t *node;
+  node = vlib_get_node (vm, node_index);
+  if (!node)
+    {
+      rv = VNET_API_ERROR_NO_SUCH_NODE;
+      goto done;
+    }
+
+  if ((node->flags & VLIB_NODE_FLAG_TRACE_SUPPORTED) == 0)
+    {
+      /* FIXME: Make a new, better error like "UNSUPPORTED_NODE_OPERATION"? */
+      rv = VNET_API_ERROR_NO_SUCH_NODE;
+      goto done;
+    }
+
+  if (pre_clear)
+    vlib_trace_stop_and_clear ();
+
+  trace_update_capture_options (add, node_index, filter, verbose);
+
+done:
+  REPLY_MACRO (VL_API_TRACE_CAPTURE_PACKETS_REPLY);
+}
+
+
+static void
+vl_api_trace_clear_capture_t_handler (vl_api_trace_clear_capture_t * mp)
+{
+  vl_api_trace_clear_capture_reply_t *rmp;
+  tracedump_main_t *tdmp = &tracedump_main;
+
+  vlib_trace_stop_and_clear ();
+
+  int rv = 0;
+  REPLY_MACRO (VL_API_TRACE_CLEAR_CAPTURE_REPLY);
+}
+
+
+
 static int
 trace_cmp (void *a1, void *a2)
 {
@@ -61,6 +154,23 @@ toss_client_cache (tracedump_main_t * tdmp, u32 client_index,
   tdmp->traces[client_index] = client_trace_cache;
 }
 
+static clib_error_t *
+tracedump_cache_reaper (u32 client_index)
+{
+  tracedump_main_t *tdmp = &tracedump_main;
+  vlib_trace_header_t ***client_trace_cache;
+
+  /* Its likely that we won't have a cache entry */
+  if (client_index >= vec_len (tdmp->traces))
+    return 0;
+
+  client_trace_cache = tdmp->traces[client_index];
+  toss_client_cache (tdmp, client_index, client_trace_cache);
+  return 0;
+}
+
+VL_MSG_API_REAPER_FUNCTION (tracedump_cache_reaper);
+
 /* API message handler */
 static void
 vl_api_trace_dump_t_handler (vl_api_trace_dump_t * mp)
@@ -103,14 +213,21 @@ vl_api_trace_dump_t_handler (vl_api_trace_dump_t * mp)
   iterator_position = clib_net_to_host_u32 (mp->position);
   max_records = clib_net_to_host_u32 (mp->max_records);
 
+  /* Don't overflow the existing queue space. */
+  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;
+  if (chunk < max_records)
+    max_records = chunk;
+
   /* Need a fresh cache for this client? */
   if (vec_len (client_trace_cache) == 0
       && (iterator_thread_id != ~0 || iterator_position != ~0))
     {
-      vlib_worker_thread_barrier_sync (&vlib_global_main);
+      vlib_worker_thread_barrier_sync (vlib_get_first_main ());
 
       /* Make a slot for each worker thread */
-      vec_validate (client_trace_cache, vec_len (vlib_mains) - 1);
+      vec_validate (client_trace_cache, vlib_get_n_threads () - 1);
       i = 0;
 
       /* *INDENT-OFF* */
@@ -121,10 +238,10 @@ vl_api_trace_dump_t_handler (vl_api_trace_dump_t * mp)
         /* Filter as directed */
         trace_apply_filter(this_vlib_main);
 
-        pool_foreach (th, tm->trace_buffer_pool,
-        ({
+        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]))
@@ -133,7 +250,7 @@ vl_api_trace_dump_t_handler (vl_api_trace_dump_t * mp)
         i++;
       }));
       /* *INDENT-ON* */
-      vlib_worker_thread_barrier_release (&vlib_global_main);
+      vlib_worker_thread_barrier_release (vlib_get_first_main ());
     }
 
   /* Save the cache, one way or the other */
@@ -151,8 +268,8 @@ vl_api_trace_dump_t_handler (vl_api_trace_dump_t * mp)
 
          vec_reset_length (s);
 
-         s = format (s, "Packet %d\n%U\n\n", j + 1, format_vlib_trace,
-                     &vlib_global_main, th[0]);
+         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 =
@@ -161,6 +278,7 @@ vl_api_trace_dump_t_handler (vl_api_trace_dump_t * mp)
          last_thread_id = dmp->thread_id = ntohl (i);
          last_position = dmp->position = ntohl (j);
          vl_api_vec_to_api_string (s, &dmp->trace_data);
+         dmp->packet_number = htonl (j);
          dmp->more_threads = 0;
          dmp->more_this_thread = 0;