vlib: add format_vnet_buffer_no_chain
[vpp.git] / src / vnet / unix / gdb_funcs.c
index d78773e..91dabe3 100644 (file)
@@ -37,6 +37,21 @@ vl (void *p)
   return vec_len (p);
 }
 
+/**
+ * @brief GDB callable function: pvh - Return vector header of vector
+ *
+ * @param *p - void - address of vector
+ *
+ * @return vh - vec_header_t, the vector header
+ *
+ */
+vec_header_t *
+pvh (void *p)
+{
+  return _vec_find (p);
+}
+
+
 /**
  * @brief GDB callable function: pe - call pool_elts - number of elements in a pool
  *
@@ -51,6 +66,20 @@ pe (void *v)
   return (pool_elts (v));
 }
 
+/**
+ * @brief GDB callable function: ph - call pool_header - get pool header.
+ *
+ * @param *p - void - address of pool
+ *
+ * @return pool_header_t
+ *
+ */
+pool_header_t *
+ph (void *p)
+{
+  return pool_header (p);
+}
+
 /**
  * @brief GDB callable function: pifi - call pool_is_free_index - is passed index free?
  *
@@ -111,8 +140,8 @@ vlib_dump_frame_ownership (void)
                     nm->nodes[this_node_runtime->node_index]->name,
                     index - first_nf_index,
                     nm->nodes[owned_runtime->node_index]->name);
-           fformat (stderr, "  nf index %d nf->frame_index %d\n",
-                    nf - vm->node_main.next_frames, nf->frame_index);
+           fformat (stderr, "  nf index %d nf->frame %p\n",
+                    nf - vm->node_main.next_frames, nf->frame);
          }
       }
   }
@@ -185,6 +214,79 @@ gdb_show_session (int verbose)
   unformat_free (&input);
 }
 
+static int
+trace_cmp (void *a1, void *a2)
+{
+  vlib_trace_header_t **t1 = a1;
+  vlib_trace_header_t **t2 = a2;
+  i64 dt = t1[0]->time - t2[0]->time;
+  return dt < 0 ? -1 : (dt > 0 ? +1 : 0);
+}
+
+void
+gdb_show_traces ()
+{
+  vlib_trace_main_t *tm;
+  vlib_trace_header_t **h, **traces;
+  u32 i, index = 0;
+  char *fmt;
+  u8 *s = 0;
+  u32 max;
+
+  /* By default display only this many traces. */
+  max = 50;
+
+  /* Get active traces from pool. */
+
+  foreach_vlib_main ()
+    {
+      fmt = "------------------- Start of thread %d %s -------------------\n";
+      s = format (s, fmt, index, vlib_worker_threads[index].name);
+
+      tm = &this_vlib_main->trace_main;
+
+      trace_apply_filter (this_vlib_main);
+
+      traces = 0;
+      pool_foreach (h, tm->trace_buffer_pool)
+       {
+         vec_add1 (traces, h[0]);
+       }
+
+      if (vec_len (traces) == 0)
+       {
+         s = format (s, "No packets in trace buffer\n");
+         goto done;
+       }
+
+      /* Sort them by increasing time. */
+      vec_sort_with_function (traces, trace_cmp);
+
+      for (i = 0; i < vec_len (traces); i++)
+       {
+         if (i == max)
+           {
+             fformat (stderr,
+                      "Limiting display to %d packets."
+                      " To display more specify max.",
+                      max);
+             goto done;
+           }
+
+         s = format (s, "Packet %d\n%U\n\n", i + 1, format_vlib_trace,
+                     vlib_get_first_main (), traces[i]);
+       }
+
+    done:
+      vec_free (traces);
+
+      index++;
+    }
+
+  fformat (stderr, "%v", s);
+  vec_free (s);
+}
+
 /**
  * @brief GDB callable function: show_gdb_command_fn - show gdb
  *
@@ -199,10 +301,16 @@ show_gdb_command_fn (vlib_main_t * vm,
   vlib_cli_output (vm, "vl(p) returns vec_len(p)");
   vlib_cli_output (vm, "vb(b) returns vnet_buffer(b) [opaque]");
   vlib_cli_output (vm, "vb2(b) returns vnet_buffer2(b) [opaque2]");
+  vlib_cli_output (vm, "vbi(b) returns b index");
+  vlib_cli_output (vm,
+                  "vgb(bi) returns vlib_get_buffer(vlib_get_main(), bi)");
   vlib_cli_output (vm, "pe(p) returns pool_elts(p)");
+  vlib_cli_output (vm, "ph(p) returns pool_header(p)");
   vlib_cli_output (vm, "pifi(p, i) returns pool_is_free_index(p, i)");
   vlib_cli_output (vm, "gdb_show_errors(0|1) dumps error counters");
   vlib_cli_output (vm, "gdb_show_session dumps session counters");
+  vlib_cli_output (vm, "gdb_show_traces() dumps buffer traces");
+  vlib_cli_output (vm, "gdb_validate_buffer(b) check vlib_buffer b sanity");
   vlib_cli_output (vm, "debug_hex_bytes (ptr, n_bytes) dumps n_bytes in hex");
   vlib_cli_output (vm, "vlib_dump_frame_ownership() does what it says");
   vlib_cli_output (vm, "vlib_runtime_index_to_node_name (index) prints NN");
@@ -218,6 +326,12 @@ VLIB_CLI_COMMAND (show_gdb_funcs_command, static) = {
 };
 /* *INDENT-ON* */
 
+vlib_buffer_t *
+vgb (u32 bi)
+{
+  return vlib_get_buffer (vlib_get_main (), bi);
+}
+
 vnet_buffer_opaque_t *
 vb (void *vb_arg)
 {
@@ -240,6 +354,78 @@ vb2 (void *vb_arg)
   return rv;
 }
 
+u32
+vbi (vlib_buffer_t * b)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  vlib_buffer_main_t *bm = vm->buffer_main;
+  u32 bi = pointer_to_uword (b) - bm->buffer_mem_start;
+  bi >>= CLIB_LOG2_CACHE_LINE_BYTES;
+  return bi;
+}
+
+int
+gdb_validate_buffer (vlib_buffer_t * b)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  u32 bi = vbi (b);
+  u8 *s =
+    vlib_validate_buffers (vm, &bi, 0, 1, VLIB_BUFFER_KNOWN_ALLOCATED, 1);
+  if (s)
+    {
+      fformat (stderr, "gdb_validate_buffer(): %v", s);
+      return -1;
+    }
+  fformat (stderr, "gdb_validate_buffer(): no error found\n");
+  return 0;
+}
+
+/**
+ * Dump a trajectory trace, reasonably easy to call from gdb
+ */
+void
+gdb_dump_trajectory_trace (u32 bi)
+{
+#if VLIB_BUFFER_TRACE_TRAJECTORY > 0
+  vlib_main_t *vm = vlib_get_main ();
+  vlib_node_main_t *vnm = &vm->node_main;
+  vlib_buffer_t *b;
+  u16 *trace;
+  u8 i;
+
+  b = vlib_get_buffer (vm, bi);
+
+  trace = b->trajectory_trace;
+
+  fformat (stderr, "Context trace for bi %d b 0x%llx, visited %d\n", bi, b,
+          b->trajectory_nb);
+
+  for (i = 0; i < b->trajectory_nb; i++)
+    {
+      u32 node_index;
+
+      node_index = trace[i];
+
+      if (node_index >= vec_len (vnm->nodes))
+       {
+         fformat (stderr, "Skip bogus node index %d\n", node_index);
+         continue;
+       }
+
+      fformat (stderr, "%v (%d)\n", vnm->nodes[node_index]->name, node_index);
+    }
+#else
+  fformat (stderr, "in vlib/buffers.h, "
+                  "#define VLIB_BUFFER_TRACE_TRAJECTORY 1\n");
+
+#endif
+}
+
+void
+gdb_dump_buffer (vlib_buffer_t *b)
+{
+  fformat (stderr, "%U\n", format_vnet_buffer, b);
+}
 
 /* Cafeteria plan, maybe you don't want these functions */
 clib_error_t *