FD.io VPP  v21.01.1
Vector Packet Processing
trace.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * trace.c: VLIB trace buffer.
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vlib/vlib.h>
41 #include <vlib/threads.h>
43 
45 
46 /* Helper function for nodes which only trace buffer data. */
47 void
50  u32 * buffers,
51  uword n_buffers,
52  uword next_buffer_stride,
53  uword n_buffer_data_bytes_in_trace)
54 {
55  u32 n_left, *from;
56 
57  n_left = n_buffers;
58  from = buffers;
59 
60  while (n_left >= 4)
61  {
62  u32 bi0, bi1;
63  vlib_buffer_t *b0, *b1;
64  u8 *t0, *t1;
65 
66  /* Prefetch next iteration. */
67  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
68  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
69 
70  bi0 = from[0];
71  bi1 = from[1];
72 
73  b0 = vlib_get_buffer (vm, bi0);
74  b1 = vlib_get_buffer (vm, bi1);
75 
76  if (b0->flags & VLIB_BUFFER_IS_TRACED)
77  {
78  t0 = vlib_add_trace (vm, node, b0, n_buffer_data_bytes_in_trace);
79  clib_memcpy_fast (t0, b0->data + b0->current_data,
80  n_buffer_data_bytes_in_trace);
81  }
82  if (b1->flags & VLIB_BUFFER_IS_TRACED)
83  {
84  t1 = vlib_add_trace (vm, node, b1, n_buffer_data_bytes_in_trace);
85  clib_memcpy_fast (t1, b1->data + b1->current_data,
86  n_buffer_data_bytes_in_trace);
87  }
88  from += 2;
89  n_left -= 2;
90  }
91 
92  while (n_left >= 1)
93  {
94  u32 bi0;
95  vlib_buffer_t *b0;
96  u8 *t0;
97 
98  bi0 = from[0];
99 
100  b0 = vlib_get_buffer (vm, bi0);
101 
102  if (b0->flags & VLIB_BUFFER_IS_TRACED)
103  {
104  t0 = vlib_add_trace (vm, node, b0, n_buffer_data_bytes_in_trace);
105  clib_memcpy_fast (t0, b0->data + b0->current_data,
106  n_buffer_data_bytes_in_trace);
107  }
108  from += 1;
109  n_left -= 1;
110  }
111 }
112 
113 /* Free up all trace buffer memory. */
114 void
116 {
117  int i;
118  vlib_trace_main_t *tm;
119 
120  /* *INDENT-OFF* */
122  ({
123  tm = &this_vlib_main->trace_main;
124 
125  tm->trace_enable = 0;
126  vec_free (tm->nodes);
127  }));
128 
130  ({
131  tm = &this_vlib_main->trace_main;
132 
133  for (i = 0; i < vec_len (tm->trace_buffer_pool); i++)
134  if (! pool_is_free_index (tm->trace_buffer_pool, i))
135  vec_free (tm->trace_buffer_pool[i]);
137  }));
138  /* *INDENT-ON* */
139 }
140 
141 u8 *
142 format_vlib_trace (u8 * s, va_list * va)
143 {
144  vlib_main_t *vm = va_arg (*va, vlib_main_t *);
145  vlib_trace_header_t *h = va_arg (*va, vlib_trace_header_t *);
146  vlib_trace_header_t *e = vec_end (h);
147  vlib_node_t *node, *prev_node;
148  clib_time_t *ct = &vm->clib_time;
149  f64 t;
150 
151  prev_node = 0;
152  while (h < e)
153  {
154  node = vlib_get_node (vm, h->node_index);
155 
156  if (node != prev_node)
157  {
158  t =
160  s =
161  format (s, "\n%U: %v", format_time_interval, "h:m:s:u", t,
162  node->name);
163  }
164  prev_node = node;
165 
166  if (node->format_trace)
167  s = format (s, "\n %U", node->format_trace, vm, node, h->data);
168  else
169  s = format (s, "\n %U", node->format_buffer, h->data);
170 
171  h = vlib_trace_header_next (h);
172  }
173 
174  return s;
175 }
176 
177 /* Root of all trace cli commands. */
178 /* *INDENT-OFF* */
179 VLIB_CLI_COMMAND (trace_cli_command,static) = {
180  .path = "trace",
181  .short_help = "Packet tracer commands",
182 };
183 /* *INDENT-ON* */
184 
185 int
186 trace_time_cmp (void *a1, void *a2)
187 {
188  vlib_trace_header_t **t1 = a1;
189  vlib_trace_header_t **t2 = a2;
190  i64 dt = t1[0]->time - t2[0]->time;
191  return dt < 0 ? -1 : (dt > 0 ? +1 : 0);
192 }
193 
194 /*
195  * Return 1 if this packet passes the trace filter, or 0 otherwise
196  */
197 u32
199 {
200  vlib_trace_header_t *e = vec_end (h);
201 
202  if (tm->filter_flag == 0)
203  return 1;
204 
205  /*
206  * When capturing a post-mortem dispatch trace,
207  * toss all existing traces once per dispatch cycle.
208  * So we can trace 4 billion pkts without running out of
209  * memory...
210  */
212  return 0;
213 
214  if (tm->filter_flag == FILTER_FLAG_INCLUDE)
215  {
216  while (h < e)
217  {
218  if (h->node_index == tm->filter_node_index)
219  return 1;
220  h = vlib_trace_header_next (h);
221  }
222  return 0;
223  }
224  else /* FILTER_FLAG_EXCLUDE */
225  {
226  while (h < e)
227  {
228  if (h->node_index == tm->filter_node_index)
229  return 0;
230  h = vlib_trace_header_next (h);
231  }
232  return 1;
233  }
234 
235  return 0;
236 }
237 
238 /*
239  * Remove traces from the trace buffer pool that don't pass the filter
240  */
241 void
243 {
244  vlib_trace_main_t *tm = &vm->trace_main;
246  vlib_trace_header_t ***traces_to_remove = 0;
247  u32 index;
248  u32 trace_index;
249  u32 n_accepted;
250 
251  u32 accept;
252 
253  if (tm->filter_flag == FILTER_FLAG_NONE)
254  return;
255 
256  /*
257  * Ideally we would retain the first N traces that pass the filter instead
258  * of any N traces.
259  */
260  n_accepted = 0;
261  /* *INDENT-OFF* */
263  {
264  accept = filter_accept(tm, h[0]);
265 
266  if ((n_accepted == tm->filter_count) || !accept)
267  vec_add1 (traces_to_remove, h);
268  else
269  n_accepted++;
270  }
271  /* *INDENT-ON* */
272 
273  /* remove all traces that we don't want to keep */
274  for (index = 0; index < vec_len (traces_to_remove); index++)
275  {
276  trace_index = traces_to_remove[index] - tm->trace_buffer_pool;
277  _vec_len (tm->trace_buffer_pool[trace_index]) = 0;
278  pool_put_index (tm->trace_buffer_pool, trace_index);
279  }
280 
281  vec_free (traces_to_remove);
282 }
283 
284 static clib_error_t *
286  unformat_input_t * input, vlib_cli_command_t * cmd)
287 {
288  vlib_trace_main_t *tm;
289  vlib_trace_header_t **h, **traces;
290  u32 i, index = 0;
291  char *fmt;
292  u8 *s = 0;
293  u32 max;
294 
295  /*
296  * By default display only this many traces. To display more, explicitly
297  * specify a max. This prevents unexpectedly huge outputs.
298  */
299  max = 50;
301  {
302  if (unformat (input, "max %d", &max))
303  ;
304  else
305  return clib_error_create ("expected 'max COUNT', got `%U'",
306  format_unformat_error, input);
307  }
308 
309 
310  /* Get active traces from pool. */
311 
312  /* *INDENT-OFF* */
314  ({
315  fmt = "------------------- Start of thread %d %s -------------------\n";
316  s = format (s, fmt, index, vlib_worker_threads[index].name);
317 
318  tm = &this_vlib_main->trace_main;
319 
320  trace_apply_filter(this_vlib_main);
321 
322  traces = 0;
324  {
325  vec_add1 (traces, h[0]);
326  }
327 
328  if (vec_len (traces) == 0)
329  {
330  s = format (s, "No packets in trace buffer\n");
331  goto done;
332  }
333 
334  /* Sort them by increasing time. */
336 
337  for (i = 0; i < vec_len (traces); i++)
338  {
339  if (i == max)
340  {
341  vlib_cli_output (vm, "Limiting display to %d packets."
342  " To display more specify max.", max);
343  goto done;
344  }
345 
346  s = format (s, "Packet %d\n%U\n\n", i + 1,
347  format_vlib_trace, vm, traces[i]);
348  }
349 
350  done:
351  vec_free (traces);
352 
353  index++;
354  }));
355  /* *INDENT-ON* */
356 
357  vlib_cli_output (vm, "%v", s);
358  vec_free (s);
359  return 0;
360 }
361 
362 /* *INDENT-OFF* */
363 VLIB_CLI_COMMAND (show_trace_cli,static) = {
364  .path = "show trace",
365  .short_help = "Show trace buffer [max COUNT]",
366  .function = cli_show_trace_buffer,
367 };
368 /* *INDENT-ON* */
369 
370 int vlib_enable_disable_pkt_trace_filter (int enable) __attribute__ ((weak));
371 
372 int
374 {
375  return 0;
376 }
377 
378 void
380 {
381  vlib_enable_disable_pkt_trace_filter (0); /* disble tracing */
383 }
384 
385 
386 void
387 trace_update_capture_options (u32 add, u32 node_index, u32 filter, u8 verbose)
388 {
389  vlib_trace_main_t *tm;
390  vlib_trace_node_t *tn;
391 
392  if (add == ~0)
393  add = 50;
394 
395  /* *INDENT-OFF* */
397  {
398  tm = &this_vlib_main->trace_main;
399  tm->verbose = verbose;
400  vec_validate (tm->nodes, node_index);
401  tn = tm->nodes + node_index;
402 
403  /*
404  * Adding 0 makes no real sense, and there wa no other way
405  * to explicilty zero-out the limits and count, so make
406  * an "add 0" request really be "set to 0".
407  */
408  if (add == 0)
409  tn->limit = tn->count = 0;
410  else
411  tn->limit += add;
412  }));
413 
415  {
416  tm = &this_vlib_main->trace_main;
417  tm->trace_enable = 1;
418  }));
419  /* *INDENT-ON* */
420 
422 }
423 
424 static clib_error_t *
426  unformat_input_t * input, vlib_cli_command_t * cmd)
427 {
428  unformat_input_t _line_input, *line_input = &_line_input;
429  vlib_node_t *node;
430  u32 node_index, add;
431  u8 verbose = 0;
432  int filter = 0;
433  clib_error_t *error = 0;
434 
435  if (!unformat_user (input, unformat_line_input, line_input))
436  return 0;
437 
438  if (vnet_trace_placeholder == 0)
441 
442  while (unformat_check_input (line_input) != (uword) UNFORMAT_END_OF_INPUT)
443  {
444  if (unformat (line_input, "%U %d",
445  unformat_vlib_node, vm, &node_index, &add))
446  ;
447  else if (unformat (line_input, "verbose"))
448  verbose = 1;
449  else if (unformat (line_input, "filter"))
450  filter = 1;
451  else
452  {
453  error = clib_error_create ("expected NODE COUNT, got `%U'",
454  format_unformat_error, line_input);
455  goto done;
456  }
457  }
458 
459  node = vlib_get_node (vm, node_index);
460 
461  if ((node->flags & VLIB_NODE_FLAG_TRACE_SUPPORTED) == 0)
462  {
463  error = clib_error_create ("node '%U' doesn't support per-node "
464  "tracing. There may be another way to "
465  "initiate trace on this node.",
466  format_vlib_node_name, vm, node_index);
467  goto done;
468  }
469 
470  u32 filter_table = classify_get_trace_chain ();
471  if (filter && filter_table == ~0)
472  {
473  error = clib_error_create ("No packet trace filter configured...");
474  goto done;
475  }
476 
477  trace_update_capture_options (add, node_index, filter, verbose);
478 
479 done:
480  unformat_free (line_input);
481 
482  return error;
483 }
484 
485 /* *INDENT-OFF* */
486 VLIB_CLI_COMMAND (add_trace_cli,static) = {
487  .path = "trace add",
488  .short_help = "trace add <input-graph-node> <add'l-pkts-for-node-> [filter] [verbose]",
489  .function = cli_add_trace_buffer,
490 };
491 /* *INDENT-ON* */
492 
493 /*
494  * Configure a filter for packet traces.
495  *
496  * This supplements the packet trace feature so that only packets matching
497  * the filter are included in the trace. Currently the only filter is to
498  * keep packets that include a certain node in the trace or exclude a certain
499  * node in the trace.
500  *
501  * The count of traced packets in the "trace add" command is still used to
502  * create a certain number of traces. The "trace filter" command specifies
503  * how many of those packets should be retained in the trace.
504  *
505  * For example, 1Mpps of traffic is arriving and one of those packets is being
506  * dropped. To capture the trace for only that dropped packet, you can do:
507  * trace filter include error-drop 1
508  * trace add dpdk-input 1000000
509  * <wait one second>
510  * show trace
511  *
512  * Note that the filter could be implemented by capturing all traces and just
513  * reducing traces displayed by the "show trace" function. But that would
514  * require a lot of memory for storing the traces, making that infeasible.
515  *
516  * To remove traces from the trace pool that do not include a certain node
517  * requires that the trace be "complete" before applying the filter. To
518  * accomplish this, the trace pool is filtered upon each iteraction of the
519  * main vlib loop. Doing so keeps the number of allocated traces down to a
520  * reasonably low number. This requires that tracing for a buffer is not
521  * performed after the vlib main loop interation completes. i.e. you can't
522  * save away a buffer temporarily then inject it back into the graph and
523  * expect that the trace_index is still valid (such as a traffic manager might
524  * do). A new trace buffer should be allocated for those types of packets.
525  *
526  * The filter can be extended to support multiple nodes and other match
527  * criteria (e.g. input sw_if_index, mac address) but for now just checks if
528  * a specified node is in the trace or not in the trace.
529  */
530 
531 void
532 trace_filter_set (u32 node_index, u32 flag, u32 count)
533 {
534  /* *INDENT-OFF* */
536  ({
537  vlib_trace_main_t *tm;
538 
539  tm = &this_vlib_main->trace_main;
540  tm->filter_node_index = node_index;
541  tm->filter_flag = flag;
542  tm->filter_count = count;
543 
544  /*
545  * Clear the trace limits to stop any in-progress tracing
546  * Prevents runaway trace allocations when the filter changes
547  * (or is removed)
548  */
549  vec_free (tm->nodes);
550  }));
551  /* *INDENT-ON* */
552 }
553 
554 
555 static clib_error_t *
557  unformat_input_t * input, vlib_cli_command_t * cmd)
558 {
559  u32 filter_node_index;
560  u32 filter_flag;
561  u32 filter_count;
562 
563  if (unformat (input, "include %U %d",
564  unformat_vlib_node, vm, &filter_node_index, &filter_count))
565  {
566  filter_flag = FILTER_FLAG_INCLUDE;
567  }
568  else if (unformat (input, "exclude %U %d",
569  unformat_vlib_node, vm, &filter_node_index,
570  &filter_count))
571  {
572  filter_flag = FILTER_FLAG_EXCLUDE;
573  }
574  else if (unformat (input, "none"))
575  {
576  filter_flag = FILTER_FLAG_NONE;
577  filter_node_index = 0;
578  filter_count = 0;
579  }
580  else
581  return
583  ("expected 'include NODE COUNT' or 'exclude NODE COUNT' or 'none', got `%U'",
584  format_unformat_error, input);
585 
586  trace_filter_set (filter_node_index, filter_flag, filter_count);
587 
588  return 0;
589 }
590 
591 /* *INDENT-OFF* */
592 VLIB_CLI_COMMAND (filter_trace_cli,static) = {
593  .path = "trace filter",
594  .short_help = "trace filter none | [include|exclude] NODE COUNT",
595  .function = cli_filter_trace,
596 };
597 /* *INDENT-ON* */
598 
599 static clib_error_t *
601  unformat_input_t * input, vlib_cli_command_t * cmd)
602 {
604  return 0;
605 }
606 
607 /* *INDENT-OFF* */
608 VLIB_CLI_COMMAND (clear_trace_cli,static) = {
609  .path = "clear trace",
610  .short_help = "Clear trace buffer and free memory",
611  .function = cli_clear_trace_buffer,
612 };
613 /* *INDENT-ON* */
614 
615 /* Placeholder function to get us linked in. */
616 void
618 {
619 }
620 
621 int
623  u32 classify_table_index, int func)
624 __attribute__ ((weak));
625 
626 int
628 {
629  clib_warning ("BUG: STUB called");
630  return 1;
631 }
632 
633 void *
635  vlib_node_runtime_t * r, vlib_buffer_t * b, u32 n_data_bytes)
636 {
637  return vlib_add_trace_inline (vm, r, b, n_data_bytes);
638 }
639 
640 
641 
642 /*
643  * fd.io coding-style-patch-verification: ON
644  *
645  * Local Variables:
646  * eval: (c-set-style "gnu")
647  * End:
648  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
u32 filter_flag
Definition: trace.h:90
void vlib_trace_cli_reference(void)
Definition: trace.c:617
format_function_t format_vlib_node_name
Definition: node_funcs.h:1222
vlib_trace_node_t * nodes
Definition: trace.h:101
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
static clib_error_t * cli_clear_trace_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: trace.c:600
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
static vlib_trace_header_t * vlib_trace_header_next(vlib_trace_header_t *h)
Definition: trace_funcs.h:106
#define VLIB_NODE_FLAG_TRACE_SUPPORTED
Definition: node.h:306
static void * vlib_add_trace_inline(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
format_function_t * format_trace
Definition: node.h:362
u16 flags
Definition: node.h:289
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
void trace_filter_set(u32 node_index, u32 flag, u32 count)
Definition: trace.c:532
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
vlib_main_t * vm
Definition: in2out_ed.c:1580
clib_time_t clib_time
Definition: main.h:123
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:520
void trace_update_capture_options(u32 add, u32 node_index, u32 filter, u8 verbose)
Definition: trace.c:387
unsigned char u8
Definition: types.h:56
u32 filter_node_index
Definition: trace.h:89
double f64
Definition: types.h:142
static clib_error_t * cli_show_trace_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: trace.c:285
vlib_trace_header_t ** trace_buffer_pool
Definition: trace.h:86
u32 trace_enable
Definition: trace.h:98
#define vlib_prefetch_buffer_with_index(vm, bi, type)
Prefetch buffer metadata by buffer index The first 64 bytes of buffer contains most header informatio...
Definition: buffer_funcs.h:476
description fragment has unexpected format
Definition: map.api:433
unsigned int u32
Definition: types.h:88
#define vec_end(v)
End (last data address) of vector.
#define clib_error_create(args...)
Definition: error.h:96
u64 cpu_time_main_loop_start
Definition: main.h:132
u32 filter_accept(vlib_trace_main_t *tm, vlib_trace_header_t *h)
Definition: trace.c:198
u8 * vnet_trace_placeholder
Definition: trace.c:44
unformat_function_t unformat_line_input
Definition: format.h:282
Definition: cJSON.c:84
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:34
#define FILTER_FLAG_EXCLUDE
Definition: trace.h:93
u8 * format_vlib_trace(u8 *s, va_list *va)
Definition: trace.c:142
struct _unformat_input_t unformat_input_t
signed long i64
Definition: types.h:78
#define FILTER_FLAG_NONE
Definition: trace.h:91
vec_header_t h
Definition: buffer.c:322
f64 seconds_per_clock
Definition: time.h:58
format_function_t * format_buffer
Definition: node.h:358
void vlib_trace_stop_and_clear(void)
Definition: trace.c:379
#define foreach_vlib_main(body)
Definition: threads.h:242
int cJSON_bool fmt
Definition: cJSON.h:160
u8 * name
Definition: node.h:264
u32 filter_count
Definition: trace.h:95
#define pool_free(p)
Free a pool.
Definition: pool.h:440
u32 classify_table_index
Definition: fib_types.api:68
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
static clib_error_t * cli_filter_trace(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: trace.c:556
static clib_error_t * cli_add_trace_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: trace.c:425
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
#define clib_warning(format, args...)
Definition: error.h:59
#define FILTER_FLAG_POST_MORTEM
Definition: trace.h:94
u8 data[]
Packet data.
Definition: buffer.h:181
int trace_time_cmp(void *a1, void *a2)
Definition: trace.c:186
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:298
string name[64]
Definition: ip.api:44
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:330
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
vlib_trace_main_t trace_main
Definition: main.h:194
void vlib_trace_frame_buffers_only(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, uword n_buffers, uword next_buffer_stride, uword n_buffer_data_bytes_in_trace)
Definition: trace.c:48
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
int vlib_enable_disable_pkt_trace_filter(int enable)
Enable / disable packet trace filter.
Definition: trace.c:373
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1055
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
u32 index
Definition: flow_types.api:221
int vnet_is_packet_traced(vlib_buffer_t *b, u32 classify_table_index, int func)
Definition: trace.c:627
u8 * format_time_interval(u8 *s, va_list *args)
Definition: std-formats.c:138
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:1228
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u32 classify_get_trace_chain(void)
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:85
u8 count
Definition: dhcp.api:208
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
void clear_trace_buffer(void)
Definition: trace.c:115
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
void trace_apply_filter(vlib_main_t *vm)
Definition: trace.c:242
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
#define FILTER_FLAG_INCLUDE
Definition: trace.h:92