FD.io VPP  v21.06
Vector Packet Processing
main.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  */
4 
5 #include <vnet/plugin/plugin.h>
6 #include <vpp/app/version.h>
7 
8 typedef struct
9 {
12 
13 typedef struct
14 {
15  u32 enable : 1;
21 
23 
24 #define VLIB_PCAP_MAJOR_VERSION 1
25 #define VLIB_PCAP_MINOR_VERSION 0
26 
27 typedef struct
28 {
30  int enable;
31  int status;
37 
38 static u8 *
39 format_buffer_metadata (u8 *s, va_list *args)
40 {
41  vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
42 
43  s = format (s, "flags: %U\n", format_vnet_buffer_flags, b);
44  s = format (s, "current_data: %d, current_length: %d\n",
45  (i32) (b->current_data), (i32) (b->current_length));
46  s = format (
47  s, "current_config_index/punt_reason: %d, flow_id: %x, next_buffer: %x\n",
49  s = format (s, "error: %d, ref_count: %d, buffer_pool_index: %d\n",
50  (u32) (b->error), (u32) (b->ref_count),
51  (u32) (b->buffer_pool_index));
52  s = format (s, "trace_handle: 0x%x, len_not_first_buf: %d\n",
54  return s;
55 }
56 
57 #define A(x) vec_add1 (dtt->pcap_buffer, (x))
58 
59 uword
62 {
63  int i;
64  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **bufp, *b;
66  pcap_main_t *pm = &dtm->dispatch_pcap_main;
69  vlib_trace_main_t *tm = &vm->trace_main;
70  u32 capture_size;
71  vlib_node_t *n;
72  i32 n_left;
73  f64 time_now = vlib_time_now (vm);
74  u32 *from;
75  u8 *d;
76  u8 string_count;
77 
78  /* Input nodes don't have frames yet */
79  if (frame == 0 || frame->n_vectors == 0)
80  goto done;
81 
82  from = vlib_frame_vector_args (frame);
83  vlib_get_buffers (vm, from, bufs, frame->n_vectors);
84  bufp = bufs;
85 
86  n = vlib_get_node (vm, node->node_index);
87 
88  for (i = 0; i < frame->n_vectors; i++)
89  {
91  {
92  b = bufp[i];
93 
95  string_count = 0;
96 
97  /* Version, flags */
100  A (0 /* string_count */);
101  A (n->protocol_hint);
102 
103  /* Buffer index (big endian) */
104  A ((from[i] >> 24) & 0xff);
105  A ((from[i] >> 16) & 0xff);
106  A ((from[i] >> 8) & 0xff);
107  A ((from[i] >> 0) & 0xff);
108 
109  /* Node name, NULL-terminated ASCII */
110  dtt->pcap_buffer = format (dtt->pcap_buffer, "%v%c", n->name, 0);
111  string_count++;
112 
113  dtt->pcap_buffer =
114  format (dtt->pcap_buffer, "%U%c", format_buffer_metadata, b, 0);
115  string_count++;
116  dtt->pcap_buffer =
117  format (dtt->pcap_buffer, "%U%c", format_vnet_buffer_opaque, b, 0);
118  string_count++;
119  dtt->pcap_buffer = format (dtt->pcap_buffer, "%U%c",
121  string_count++;
122 
123  /* Is this packet traced? */
124  if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
125  {
128 
129  dtt->pcap_buffer = format (dtt->pcap_buffer, "%U%c",
130  format_vlib_trace, vm, h[0], 0);
131  string_count++;
132  }
133 
134  /* Save the string count */
135  dtt->pcap_buffer[2] = string_count;
136 
137  /* Figure out how many bytes in the pcap trace */
138  capture_size =
140 
142  n_left = clib_min (capture_size, 16384);
143  d = pcap_add_packet (pm, time_now, n_left, capture_size);
144 
145  /* Copy the header */
147  d += vec_len (dtt->pcap_buffer);
148 
149  n_left = clib_min (vlib_buffer_length_in_chain (vm, b),
150  (16384 - vec_len (dtt->pcap_buffer)));
151  /* Copy the packet data */
152  while (1)
153  {
154  u32 copy_length = clib_min ((u32) n_left, b->current_length);
155  clib_memcpy_fast (d, b->data + b->current_data, copy_length);
156  n_left -= b->current_length;
157  if (n_left <= 0)
158  break;
159  d += b->current_length;
160  ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
161  b = vlib_get_buffer (vm, b->next_buffer);
162  }
164  }
165  }
166 done:
167  return node->function (vm, node, frame);
168 }
169 
170 static void
172 {
174  pcap_main_t *pm = &dtm->dispatch_pcap_main;
175 
176  /* Reset the trace buffer and capture count */
179  pm->n_packets_captured = 0;
181  {
182  vlib_node_runtime_t *epoll_input_rt =
184  epoll_input_rt->input_main_loops_per_call = 0;
185  }
187 }
188 
189 static void
191 {
193  pcap_main_t *pm = &dtm->dispatch_pcap_main;
195 
197  pm->file_name =
198  (char *) format (0, "/tmp/dispatch_post_mortem.%d%c", getpid (), 0);
199  error = pcap_write (pm);
200  pcap_close (pm);
201  if (error)
202  clib_error_report (error);
203  /*
204  * We're in the middle of crashing. Don't try to free the filename.
205  */
206 }
207 static int
209 {
213  pcap_main_t *pm = &dtm->dispatch_pcap_main;
214  vlib_trace_main_t *tm;
215  vlib_trace_node_t *tn;
216 
217  vec_validate (dtm->threads, vtm->n_vlib_mains);
218 
219  if (a->status)
220  {
221  if (dtm->enable)
222  {
223  int i;
224  vlib_cli_output (vm,
225  "pcap dispatch capture enabled: %d of %d pkts...",
227  vlib_cli_output (vm, "capture to file %s", pm->file_name);
228 
229  for (i = 0; i < vec_len (dtm->dispatch_buffer_trace_nodes); i++)
230  {
232  vm, "Buffer trace of %d pkts from %U enabled...",
235  }
236  }
237  else
238  vlib_cli_output (vm, "pcap dispatch capture disabled");
239  return 0;
240  }
241 
242  /* Consistency checks */
243 
244  /* Enable w/ capture already enabled not allowed */
245  if (dtm->enable && a->enable)
246  return VNET_API_ERROR_INVALID_VALUE;
247 
248  /* Disable capture with capture already disabled, not interesting */
249  if (dtm->enable == 0 && a->enable == 0)
250  return VNET_API_ERROR_VALUE_EXIST;
251 
252  /* Change number of packets to capture while capturing */
253  if (dtm->enable && a->enable &&
255  return VNET_API_ERROR_INVALID_VALUE_2;
256 
257  /* Independent of enable/disable, to allow buffer trace multi nodes */
258  if (a->buffer_trace_node_index != ~0)
259  {
261  {
262  tm = &this_vlib_main->trace_main;
263  tm->verbose = 0; /* not sure this ever did anything... */
265  tn = tm->nodes + a->buffer_trace_node_index;
267  if (a->post_mortem)
268  {
270  tm->filter_count = ~0;
271  }
272  tm->trace_enable = 1;
273  if (vlib_node_set_dispatch_wrapper (this_vlib_main,
275  clib_warning (0, "Dispatch wrapper already in use on thread %u",
276  this_vlib_main->thread_index);
277  }
279  }
280 
281  if (a->enable)
282  {
283  /* Clean up from previous run, if any */
284  vec_free (pm->file_name);
285  vec_free (pm->pcap_data);
286  memset (pm, 0, sizeof (*pm));
287 
290  if (pm->lock == 0)
291  clib_spinlock_init (&(pm->lock));
292 
293  if (a->filename == 0)
294  a->filename = format (0, "/tmp/dispatch.pcap%c", 0);
295 
296  pm->file_name = (char *) a->filename;
297  pm->n_packets_captured = 0;
298  pm->packet_type = PCAP_PACKET_TYPE_vpp;
300  dtm->enable = 1;
301  }
302  else
303  {
304  dtm->enable = 0;
306  {
307  tm = &this_vlib_main->trace_main;
308  tm->filter_flag = 0;
309  tm->filter_count = 0;
310  vlib_node_set_dispatch_wrapper (this_vlib_main, 0);
311  }
313  if (pm->n_packets_captured)
314  {
317  vlib_cli_output (vm, "Write %d packets to %s, and stop capture...",
318  pm->n_packets_captured, pm->file_name);
319  error = pcap_write (pm);
320  if (pm->flags & PCAP_MAIN_INIT_DONE)
321  pcap_close (pm);
322  /* Report I/O errors... */
323  if (error)
324  {
325  clib_error_report (error);
326  return VNET_API_ERROR_SYSCALL_ERROR_1;
327  }
328  return 0;
329  }
330  else
331  return VNET_API_ERROR_NO_SUCH_ENTRY;
332  }
333 
334  vlib_node_t *epoll_input_node =
335  vlib_get_node_by_name (vm, (u8 *) "unix-epoll-input");
336 
337  /* Save the input node index, see the post-mortem callback */
338  if (epoll_input_node)
339  dtm->epoll_input_node_index = epoll_input_node->index;
340 
341  /* main thread only */
347 
348  return 0;
349 }
350 
351 static clib_error_t *
353  vlib_cli_command_t *cmd)
354 {
355  unformat_input_t _line_input, *line_input = &_line_input;
357  u8 *filename = 0;
358  u32 max = 1000;
359  int rv;
360  int enable = 0;
361  int status = 0;
362  int post_mortem = 0;
363  u32 node_index = ~0, buffer_traces_to_capture = 100;
364 
365  /* Get a line of input. */
366  if (!unformat_user (input, unformat_line_input, line_input))
367  return 0;
368 
369  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
370  {
371  if (unformat (line_input, "on %=", &enable, 1))
372  ;
373  else if (unformat (line_input, "enable %=", &enable, 1))
374  ;
375  else if (unformat (line_input, "off %=", &enable, 0))
376  ;
377  else if (unformat (line_input, "disable %=", &enable, 0))
378  ;
379  else if (unformat (line_input, "max %d", &max))
380  ;
381  else if (unformat (line_input, "packets-to-capture %d", &max))
382  ;
383  else if (unformat (line_input, "file %U", unformat_vlib_tmpfile,
384  &filename))
385  ;
386  else if (unformat (line_input, "status %=", &status, 1))
387  ;
388  else if (unformat (line_input, "buffer-trace %U %d", unformat_vlib_node,
389  vm, &node_index, &buffer_traces_to_capture))
390  ;
391  else if (unformat (line_input, "post-mortem %=", &post_mortem, 1))
392  ;
393  else
394  {
395  return clib_error_return (0, "unknown input `%U'",
396  format_unformat_error, line_input);
397  }
398  }
399 
400  unformat_free (line_input);
401 
402  /* no need for memset (a, 0, sizeof (*a)), set all fields here. */
403  a->filename = filename;
404  a->enable = enable;
405  a->status = status;
406  a->packets_to_capture = max;
408  a->buffer_traces_to_capture = buffer_traces_to_capture;
409  a->post_mortem = post_mortem;
410 
412 
413  switch (rv)
414  {
415  case 0:
416  break;
417 
418  case -7:
419  return clib_error_return (0, "dispatch trace already enabled...");
420 
421  case -81:
422  return clib_error_return (0, "dispatch trace already disabled...");
423 
424  case -8:
425  return clib_error_return (
426  0, "can't change number of records to capture while tracing...");
427 
428  case -11:
429  return clib_error_return (0, "I/O writing trace capture...");
430 
431  case -6:
432  return clib_error_return (0, "No packets captured...");
433 
434  default:
435  vlib_cli_output (vm, "WARNING: trace configure returned %d", rv);
436  break;
437  }
438  return 0;
439 }
440 
441 /*?
442  * This command is used to start or stop pcap dispatch trace capture, or show
443  * the capture status.
444  *
445  * This command has the following optional parameters:
446  *
447  * - <b>on|off</b> - Used to start or stop capture.
448  *
449  * - <b>max <nn></b> - Depth of local buffer. Once '<em>nn</em>' number
450  * of packets have been received, buffer is flushed to file. Once another
451  * '<em>nn</em>' number of packets have been received, buffer is flushed
452  * to file, overwriting previous write. If not entered, value defaults
453  * to 100. Can only be updated if packet capture is off.
454  *
455  * - <b>file <name></b> - Used to specify the output filename. The file will
456  * be placed in the '<em>/tmp</em>' directory, so only the filename is
457  * supported. Directory should not be entered. If file already exists, file
458  * will be overwritten. If no filename is provided, '<em>/tmp/vpe.pcap</em>'
459  * will be used. Can only be updated if packet capture is off.
460  *
461  * - <b>status</b> - Displays the current status and configured attributes
462  * associated with a packet capture. If packet capture is in progress,
463  * '<em>status</em>' also will return the number of packets currently in
464  * the local buffer. All additional attributes entered on command line
465  * with '<em>status</em>' will be ignored and not applied.
466  *
467  * @cliexpar
468  * Example of how to display the status of capture when off:
469  * @cliexstart{pcap dispatch trace status}
470  * max is 100, for any interface to file /tmp/vpe.pcap
471  * pcap dispatch capture is off...
472  * @cliexend
473  * Example of how to start a dispatch trace capture:
474  * @cliexstart{pcap dispatch trace on max 35 file dispatchTrace.pcap}
475  * pcap dispatch capture on...
476  * @cliexend
477  * Example of how to start a dispatch trace capture with buffer tracing
478  * @cliexstart{pcap dispatch trace on max 10000 file dispatchTrace.pcap
479  * buffer-trace dpdk-input 1000}
480  * pcap dispatch capture on...
481  * @cliexend
482  * Example of how to display the status of a tx packet capture in progress:
483  * @cliexstart{pcap tx trace status}
484  * max is 35, dispatch trace to file /tmp/vppTest.pcap
485  * pcap tx capture is on: 20 of 35 pkts...
486  * @cliexend
487  * Example of how to stop a tx packet capture:
488  * @cliexstart{vppctl pcap dispatch trace off}
489  * captured 21 pkts...
490  * saved to /tmp/dispatchTrace.pcap...
491  * Example of how to start a post-mortem dispatch trace:
492  * pcap dispatch trace on max 20000 buffer-trace
493  * dpdk-input 3000000000 post-mortem
494  * @cliexend
495 ?*/
496 
497 VLIB_CLI_COMMAND (pcap_dispatch_trace_command, static) = {
498  .path = "pcap dispatch trace",
499  .short_help =
500  "pcap dispatch trace [on|off] [max <nn>] [file <name>] [status]\n"
501  " [buffer-trace <input-node-name> <nn>][post-mortem]",
502  .function = dispatch_trace_command_fn,
503 };
504 
506  .version = VPP_BUILD_VER,
507  .description = "Dispatch Trace",
508 };
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:524
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:133
u32 filter_flag
Definition: trace.h:90
char * file_name
File name of pcap output.
Definition: pcap.h:162
#define clib_min(x, y)
Definition: clib.h:342
__clib_export clib_error_t * pcap_write(pcap_main_t *pm)
Write PCAP file.
Definition: pcap.c:89
u32 flags
flags
Definition: pcap.h:174
format_function_t format_vlib_node_name
Definition: node_funcs.h:1235
a
Definition: bitmap.h:544
u32 n_packets_to_capture
Number of packets to capture.
Definition: pcap.h:165
static u32 vlib_buffer_get_trace_index(vlib_buffer_t *b)
Extract the trace (pool) index from a trace handle.
Definition: buffer.h:416
VLIB_PLUGIN_REGISTER()
vlib_trace_node_t * nodes
Definition: trace.h:101
#define PREDICT_TRUE(x)
Definition: clib.h:125
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:119
clib_spinlock_t worker_thread_main_loop_callback_lock
Definition: main.h:228
u32 index
Definition: node.h:270
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:325
#define VLIB_PCAP_MINOR_VERSION
Definition: main.c:25
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:129
u32 thread_index
Definition: main.h:213
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:607
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
dispatch_trace_thread_t * threads
Definition: main.c:18
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:535
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
u8 buffer_pool_index
index of buffer pool this buffer belongs.
Definition: buffer.h:142
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
unsigned int u32
Definition: types.h:88
#define foreach_vlib_main()
Definition: threads.h:237
u32 input_main_loops_per_call
For input nodes: decremented on each main loop interation until it reaches zero and function is calle...
Definition: node.h:481
u32 * dispatch_buffer_trace_nodes
Definition: main.c:17
vlib_trace_header_t ** trace_buffer_pool
Definition: trace.h:86
uword unformat_vlib_tmpfile(unformat_input_t *input, va_list *args)
Definition: format.c:192
PCAP main state data structure.
Definition: pcap.h:156
u32 trace_enable
Definition: trace.h:98
clib_spinlock_t lock
spinlock to protect e.g.
Definition: pcap.h:159
vlib_node_function_t * function
Node function to call.
Definition: node.h:459
dispatch_trace_main_t dispatch_trace_main
Definition: main.c:22
vlib_get_buffers(vm, from, b, n_left_from)
static int vlib_pcap_dispatch_trace_configure(vlib_pcap_dispatch_trace_args_t *a)
Definition: main.c:208
description fragment has unexpected format
Definition: map.api:433
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
format_function_t format_vnet_buffer_opaque2
Definition: buffer.h:519
int __clib_unused rv
Definition: application.c:491
#define VLIB_FRAME_SIZE
Definition: node.h:369
u8 * vnet_trace_placeholder
Definition: trace.c:44
unformat_function_t unformat_line_input
Definition: format.h:275
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:65
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
u32 epoll_input_node_index
Definition: main.c:19
format_function_t format_vnet_buffer_flags
Definition: buffer.h:517
Definition: cJSON.c:88
__clib_export clib_error_t * pcap_close(pcap_main_t *pm)
Close PCAP file.
Definition: pcap.c:74
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:35
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
format_function_t format_vnet_buffer_opaque
Definition: buffer.h:518
void(**volatile worker_thread_main_loop_callback_tmp)(struct vlib_main_t *, u64 t)
Definition: main.h:227
format_function_t format_vlib_trace
Definition: trace.h:114
u8 * pcap_data
Vector of pcap data.
Definition: pcap.h:184
struct _unformat_input_t unformat_input_t
u32 trace_handle
Specifies trace buffer handle if VLIB_PACKET_IS_TRACED flag is set.
Definition: buffer.h:172
#define PREDICT_FALSE(x)
Definition: clib.h:124
#define A(x)
Definition: main.c:57
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
u8 protocol_hint
Definition: node.h:306
u32 node_index
Node index.
Definition: node.h:479
static u8 * format_buffer_metadata(u8 *s, va_list *args)
Definition: main.c:39
static void * pcap_add_packet(pcap_main_t *pm, f64 time_now, u32 n_bytes_in_trace, u32 n_bytes_in_packet)
Add packet.
Definition: pcap_funcs.h:41
u32 n_left
u8 * name
Definition: node.h:254
static clib_error_t * dispatch_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:352
u32 filter_count
Definition: trace.h:95
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
u16 n_vectors
Definition: node.h:388
static void pcap_postmortem_dump(void)
Definition: main.c:190
u32 flow_id
Generic flow identifier.
Definition: buffer.h:136
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
#define clib_warning(format, args...)
Definition: error.h:59
#define FILTER_FLAG_POST_MORTEM
Definition: trace.h:94
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:116
u8 data[]
Packet data.
Definition: buffer.h:204
void(**volatile worker_thread_main_loop_callbacks)(struct vlib_main_t *, u64 t)
Definition: main.h:225
#define VLIB_PCAP_MAJOR_VERSION
Definition: main.c:24
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:156
static int vlib_node_set_dispatch_wrapper(vlib_main_t *vm, vlib_node_function_t *fn)
Definition: node_funcs.h:1264
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
signed int i32
Definition: types.h:77
#define PCAP_MAIN_INIT_DONE
Definition: pcap.h:175
#define ASSERT(truth)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
#define clib_callback_enable_disable(h, tmp, l, f, enable)
Add or remove a callback to the specified callback set.
Definition: callback.h:38
#define clib_error_report(e)
Definition: error.h:113
vlib_trace_main_t trace_main
Definition: main.h:174
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
pcap_packet_type_t packet_type
Packet type.
Definition: pcap.h:168
void vlib_add_del_post_mortem_callback(void *cb, int is_add)
Definition: main.c:1789
uword dispatch_pcap_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: main.c:60
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:149
pcap_main_t dispatch_pcap_main
Definition: main.c:16
VLIB buffer representation.
Definition: buffer.h:111
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:155
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
node node_index
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:1241
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:56
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:86
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:176
static void pcap_postmortem_reset(vlib_main_t *vm)
Definition: main.c:171
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:106
volatile u8 ref_count
Reference count for this buffer.
Definition: buffer.h:139
u32 n_packets_captured
Number of packets currently captured.
Definition: pcap.h:171
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
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:163