CLI control of graph dispatch elogs

Change-Id: I195c8eabc0ee67880f1e85fc7594b00be6b563e3
Signed-off-by: Dave Barach <dave@barachs.net>
diff --git a/src/vlib/main.c b/src/vlib/main.c
index c5153ab..eed627c 100644
--- a/src/vlib/main.c
+++ b/src/vlib/main.c
@@ -912,18 +912,35 @@
 {
   vlib_main_t *evm = &vlib_global_main;
   elog_main_t *em = &evm->elog_main;
+  int enabled = evm->elog_trace_graph_dispatch |
+    evm->elog_trace_graph_circuit;
 
-  if (VLIB_ELOG_MAIN_LOOP && n_vectors)
-    elog_track (em,
-		/* event type */
-		vec_elt_at_index (is_return
-				  ? evm->node_return_elog_event_types
-				  : evm->node_call_elog_event_types,
-				  node_index),
-		/* track */
-		(vm->thread_index ? &vlib_worker_threads[vm->thread_index].
-		 elog_track : &em->default_track),
-		/* data to log */ n_vectors);
+  if (PREDICT_FALSE (enabled && n_vectors))
+    {
+      if (PREDICT_FALSE (!elog_is_enabled (em)))
+	{
+	  evm->elog_trace_graph_dispatch = 0;
+	  evm->elog_trace_graph_circuit = 0;
+	  return;
+	}
+      if (PREDICT_TRUE
+	  (evm->elog_trace_graph_dispatch ||
+	   (evm->elog_trace_graph_circuit &&
+	    node_index == evm->elog_trace_graph_circuit_node_index)))
+	{
+	  elog_track (em,
+		      /* event type */
+		      vec_elt_at_index (is_return
+					? evm->node_return_elog_event_types
+					: evm->node_call_elog_event_types,
+					node_index),
+		      /* track */
+		      (vm->thread_index ?
+		       &vlib_worker_threads[vm->thread_index].elog_track
+		       : &em->default_track),
+		      /* data to log */ n_vectors);
+	}
+    }
 }
 
 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0
@@ -1116,6 +1133,7 @@
   u64 t;
   vlib_node_main_t *nm = &vm->node_main;
   vlib_next_frame_t *nf;
+  u64 pmc_before[2], pmc_after[2], pmc_delta[2];
 
   if (CLIB_DEBUG > 0)
     {
@@ -1151,142 +1169,142 @@
 
   vm->cpu_time_last_node_dispatch = last_time_stamp;
 
-  if (1 /* || vm->thread_index == node->thread_index */ )
+  vlib_elog_main_loop_event (vm, node->node_index,
+			     last_time_stamp, frame ? frame->n_vectors : 0,
+			     /* is_after */ 0);
+
+  vlib_node_runtime_perf_counter (vm, &pmc_before[0], &pmc_before[1]);
+
+  /*
+   * Turn this on if you run into
+   * "bad monkey" contexts, and you want to know exactly
+   * which nodes they've visited... See ixge.c...
+   */
+  if (VLIB_BUFFER_TRACE_TRAJECTORY && frame)
     {
-      u64 pmc_before[2], pmc_after[2], pmc_delta[2];
-
-      vlib_elog_main_loop_event (vm, node->node_index,
-				 last_time_stamp,
-				 frame ? frame->n_vectors : 0,
-				 /* is_after */ 0);
-
-      vlib_node_runtime_perf_counter (vm, &pmc_before[0], &pmc_before[1]);
-
-      /*
-       * Turn this on if you run into
-       * "bad monkey" contexts, and you want to know exactly
-       * which nodes they've visited... See ixge.c...
-       */
-      if (VLIB_BUFFER_TRACE_TRAJECTORY && frame)
+      int i;
+      u32 *from;
+      from = vlib_frame_vector_args (frame);
+      for (i = 0; i < frame->n_vectors; i++)
 	{
-	  int i;
-	  u32 *from;
-	  from = vlib_frame_vector_args (frame);
-	  for (i = 0; i < frame->n_vectors; i++)
-	    {
-	      vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
-	      add_trajectory_trace (b, node->node_index);
-	    }
-	  if (PREDICT_FALSE (vm->dispatch_pcap_enable))
-	    dispatch_pcap_trace (vm, node, frame);
-	  n = node->function (vm, node, frame);
+	  vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
+	  add_trajectory_trace (b, node->node_index);
 	}
-      else
+      if (PREDICT_FALSE (vm->dispatch_pcap_enable))
+	dispatch_pcap_trace (vm, node, frame);
+      n = node->function (vm, node, frame);
+    }
+  else
+    {
+      if (PREDICT_FALSE (vm->dispatch_pcap_enable))
+	dispatch_pcap_trace (vm, node, frame);
+      n = node->function (vm, node, frame);
+    }
+
+  t = clib_cpu_time_now ();
+
+  /*
+   * To validate accounting: pmc_delta = t - pmc_before;
+   * perf ticks should equal clocks/pkt...
+   */
+  vlib_node_runtime_perf_counter (vm, &pmc_after[0], &pmc_after[1]);
+
+  pmc_delta[0] = pmc_after[0] - pmc_before[0];
+  pmc_delta[1] = pmc_after[1] - pmc_before[1];
+
+  vlib_elog_main_loop_event (vm, node->node_index, t, n, 1 /* is_after */ );
+
+  vm->main_loop_vectors_processed += n;
+  vm->main_loop_nodes_processed += n > 0;
+
+  v = vlib_node_runtime_update_stats (vm, node,
+				      /* n_calls */ 1,
+				      /* n_vectors */ n,
+				      /* n_clocks */ t - last_time_stamp,
+				      pmc_delta[0] /* PMC0 */ ,
+				      pmc_delta[1] /* PMC1 */ );
+
+  /* When in interrupt mode and vector rate crosses threshold switch to
+     polling mode. */
+  if (PREDICT_FALSE ((dispatch_state == VLIB_NODE_STATE_INTERRUPT)
+		     || (dispatch_state == VLIB_NODE_STATE_POLLING
+			 && (node->flags
+			     &
+			     VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE))))
+    {
+      /* *INDENT-OFF* */
+      ELOG_TYPE_DECLARE (e) =
+        {
+          .function = (char *) __FUNCTION__,
+          .format = "%s vector length %d, switching to %s",
+          .format_args = "T4i4t4",
+          .n_enum_strings = 2,
+          .enum_strings = {
+            "interrupt", "polling",
+          },
+        };
+      /* *INDENT-ON* */
+      struct
+      {
+	u32 node_name, vector_length, is_polling;
+      } *ed;
+
+      if ((dispatch_state == VLIB_NODE_STATE_INTERRUPT
+	   && v >= nm->polling_threshold_vector_length) &&
+	  !(node->flags &
+	    VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE))
 	{
-	  if (PREDICT_FALSE (vm->dispatch_pcap_enable))
-	    dispatch_pcap_trace (vm, node, frame);
-	  n = node->function (vm, node, frame);
-	}
+	  vlib_node_t *n = vlib_get_node (vm, node->node_index);
+	  n->state = VLIB_NODE_STATE_POLLING;
+	  node->state = VLIB_NODE_STATE_POLLING;
+	  node->flags &=
+	    ~VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE;
+	  node->flags |= VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE;
+	  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] -= 1;
+	  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] += 1;
 
-      t = clib_cpu_time_now ();
-
-      /*
-       * To validate accounting: pmc_delta = t - pmc_before;
-       * perf ticks should equal clocks/pkt...
-       */
-      vlib_node_runtime_perf_counter (vm, &pmc_after[0], &pmc_after[1]);
-
-      pmc_delta[0] = pmc_after[0] - pmc_before[0];
-      pmc_delta[1] = pmc_after[1] - pmc_before[1];
-
-      vlib_elog_main_loop_event (vm, node->node_index, t, n,	/* is_after */
-				 1);
-
-      vm->main_loop_vectors_processed += n;
-      vm->main_loop_nodes_processed += n > 0;
-
-      v = vlib_node_runtime_update_stats (vm, node,
-					  /* n_calls */ 1,
-					  /* n_vectors */ n,
-					  /* n_clocks */ t - last_time_stamp,
-					  pmc_delta[0] /* PMC0 */ ,
-					  pmc_delta[1] /* PMC1 */ );
-
-      /* When in interrupt mode and vector rate crosses threshold switch to
-         polling mode. */
-      if ((dispatch_state == VLIB_NODE_STATE_INTERRUPT)
-	  || (dispatch_state == VLIB_NODE_STATE_POLLING
-	      && (node->flags
-		  & VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE)))
-	{
-#ifdef DISPATCH_NODE_ELOG_REQUIRED
-	  ELOG_TYPE_DECLARE (e) =
-	  {
-	    .function = (char *) __FUNCTION__,.format =
-	      "%s vector length %d, switching to %s",.format_args =
-	      "T4i4t4",.n_enum_strings = 2,.enum_strings =
+	  if (PREDICT_FALSE (vlib_global_main.elog_trace_graph_dispatch))
 	    {
-	  "interrupt", "polling",},};
-	  struct
-	  {
-	    u32 node_name, vector_length, is_polling;
-	  } *ed;
-	  vlib_worker_thread_t *w = vlib_worker_threads + vm->thread_index;
-#endif
+	      vlib_worker_thread_t *w = vlib_worker_threads
+		+ vm->thread_index;
 
-	  if ((dispatch_state == VLIB_NODE_STATE_INTERRUPT
-	       && v >= nm->polling_threshold_vector_length) &&
-	      !(node->flags &
-		VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE))
-	    {
-	      vlib_node_t *n = vlib_get_node (vm, node->node_index);
-	      n->state = VLIB_NODE_STATE_POLLING;
-	      node->state = VLIB_NODE_STATE_POLLING;
-	      node->flags &=
-		~VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE;
-	      node->flags |=
-		VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE;
-	      nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] -= 1;
-	      nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] += 1;
-
-#ifdef DISPATCH_NODE_ELOG_REQUIRED
 	      ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
 				    w->elog_track);
 	      ed->node_name = n->name_elog_string;
 	      ed->vector_length = v;
 	      ed->is_polling = 1;
-#endif
 	    }
-	  else if (dispatch_state == VLIB_NODE_STATE_POLLING
-		   && v <= nm->interrupt_threshold_vector_length)
+	}
+      else if (dispatch_state == VLIB_NODE_STATE_POLLING
+	       && v <= nm->interrupt_threshold_vector_length)
+	{
+	  vlib_node_t *n = vlib_get_node (vm, node->node_index);
+	  if (node->flags &
+	      VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE)
 	    {
-	      vlib_node_t *n = vlib_get_node (vm, node->node_index);
-	      if (node->flags &
-		  VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE)
-		{
-		  /* Switch to interrupt mode after dispatch in polling one more time.
-		     This allows driver to re-enable interrupts. */
-		  n->state = VLIB_NODE_STATE_INTERRUPT;
-		  node->state = VLIB_NODE_STATE_INTERRUPT;
-		  node->flags &=
-		    ~VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE;
-		  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] -=
-		    1;
-		  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] +=
-		    1;
+	      /* Switch to interrupt mode after dispatch in polling one more time.
+	         This allows driver to re-enable interrupts. */
+	      n->state = VLIB_NODE_STATE_INTERRUPT;
+	      node->state = VLIB_NODE_STATE_INTERRUPT;
+	      node->flags &=
+		~VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE;
+	      nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] -= 1;
+	      nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] += 1;
 
-		}
-	      else
+	    }
+	  else
+	    {
+	      vlib_worker_thread_t *w = vlib_worker_threads
+		+ vm->thread_index;
+	      node->flags |=
+		VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE;
+	      if (PREDICT_FALSE (vlib_global_main.elog_trace_graph_dispatch))
 		{
-		  node->flags |=
-		    VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE;
-#ifdef DISPATCH_NODE_ELOG_REQUIRED
 		  ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
 					w->elog_track);
 		  ed->node_name = n->name_elog_string;
 		  ed->vector_length = v;
 		  ed->is_polling = 0;
-#endif
 		}
 	    }
 	}
@@ -1778,9 +1796,30 @@
 
       if (is_main)
 	{
+          /* *INDENT-OFF* */
+          ELOG_TYPE_DECLARE (es) =
+            {
+              .format = "process tw start",
+              .format_args = "",
+            };
+          ELOG_TYPE_DECLARE (ee) =
+            {
+              .format = "process tw end: %d",
+              .format_args = "i4",
+            };
+          /* *INDENT-ON* */
+
+	  struct
+	  {
+	    int nready_procs;
+	  } *ed;
+
 	  /* Check if process nodes have expired from timing wheel. */
 	  ASSERT (nm->data_from_advancing_timing_wheel != 0);
 
+	  if (PREDICT_FALSE (vm->elog_trace_graph_dispatch))
+	    ed = ELOG_DATA (&vlib_global_main.elog_main, es);
+
 	  nm->data_from_advancing_timing_wheel =
 	    TW (tw_timer_expire_timers_vec)
 	    ((TWT (tw_timer_wheel) *) nm->timing_wheel, vlib_time_now (vm),
@@ -1788,6 +1827,13 @@
 
 	  ASSERT (nm->data_from_advancing_timing_wheel != 0);
 
+	  if (PREDICT_FALSE (vm->elog_trace_graph_dispatch))
+	    {
+	      ed = ELOG_DATA (&vlib_global_main.elog_main, ee);
+	      ed->nready_procs =
+		_vec_len (nm->data_from_advancing_timing_wheel);
+	    }
+
 	  if (PREDICT_FALSE
 	      (_vec_len (nm->data_from_advancing_timing_wheel) > 0))
 	    {