FD.io VPP  v21.01.1
Vector Packet Processing
main.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  * main.c: main vector processing loop
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 <math.h>
41 #include <vppinfra/format.h>
42 #include <vlib/vlib.h>
43 #include <vlib/threads.h>
45 
46 #include <vlib/unix/unix.h>
47 
48 /* Actually allocate a few extra slots of vector data to support
49  speculative vector enqueues which overflow vector data in next frame. */
50 #define VLIB_FRAME_SIZE_ALLOC (VLIB_FRAME_SIZE + 4)
51 
53 vlib_frame_bytes (u32 n_scalar_bytes, u32 n_vector_bytes)
54 {
55  u32 n_bytes;
56 
57  /* Make room for vlib_frame_t plus scalar arguments. */
58  n_bytes = vlib_frame_vector_byte_offset (n_scalar_bytes);
59 
60  /* Make room for vector arguments.
61  Allocate a few extra slots of vector data to support
62  speculative vector enqueues which overflow vector data in next frame. */
63 #define VLIB_FRAME_SIZE_EXTRA 4
64  n_bytes += (VLIB_FRAME_SIZE + VLIB_FRAME_SIZE_EXTRA) * n_vector_bytes;
65 
66  /* Magic number is first 32bit number after vector data.
67  Used to make sure that vector data is never overrun. */
68 #define VLIB_FRAME_MAGIC (0xabadc0ed)
69  n_bytes += sizeof (u32);
70 
71  /* Pad to cache line. */
72  n_bytes = round_pow2 (n_bytes, CLIB_CACHE_LINE_BYTES);
73 
74  return n_bytes;
75 }
76 
79 {
80  void *p = f;
81 
83 
85 
86  return p;
87 }
88 
89 static inline vlib_frame_size_t *
91  u32 n_scalar_bytes, u32 n_vector_bytes)
92 {
93 #ifdef VLIB_SUPPORTS_ARBITRARY_SCALAR_SIZES
94  uword key = (n_scalar_bytes << 16) | n_vector_bytes;
95  uword *p, i;
96 
97  p = hash_get (nm->frame_size_hash, key);
98  if (p)
99  i = p[0];
100  else
101  {
102  i = vec_len (nm->frame_sizes);
103  vec_validate (nm->frame_sizes, i);
104  hash_set (nm->frame_size_hash, key, i);
105  }
106 
107  return vec_elt_at_index (nm->frame_sizes, i);
108 #else
109  ASSERT (vlib_frame_bytes (n_scalar_bytes, n_vector_bytes)
110  == (vlib_frame_bytes (0, 4)));
111  return vec_elt_at_index (nm->frame_sizes, 0);
112 #endif
113 }
114 
115 static vlib_frame_t *
117  u32 frame_flags)
118 {
119  vlib_node_main_t *nm = &vm->node_main;
120  vlib_frame_size_t *fs;
121  vlib_node_t *to_node;
122  vlib_frame_t *f;
123  u32 l, n, scalar_size, vector_size;
124 
125  to_node = vlib_get_node (vm, to_node_index);
126 
127  scalar_size = to_node->scalar_size;
128  vector_size = to_node->vector_size;
129 
130  fs = get_frame_size_info (nm, scalar_size, vector_size);
131  n = vlib_frame_bytes (scalar_size, vector_size);
132  if ((l = vec_len (fs->free_frames)) > 0)
133  {
134  /* Allocate from end of free list. */
135  f = fs->free_frames[l - 1];
136  _vec_len (fs->free_frames) = l - 1;
137  }
138  else
139  {
141  }
142 
143  /* Poison frame when debugging. */
144  if (CLIB_DEBUG > 0)
145  clib_memset (f, 0xfe, n);
146 
147  /* Insert magic number. */
148  {
149  u32 *magic;
150 
151  magic = vlib_frame_find_magic (f, to_node);
152  *magic = VLIB_FRAME_MAGIC;
153  }
154 
155  f->frame_flags = VLIB_FRAME_IS_ALLOCATED | frame_flags;
156  f->n_vectors = 0;
157  f->scalar_size = scalar_size;
158  f->vector_size = vector_size;
159  f->flags = 0;
160 
161  fs->n_alloc_frames += 1;
162 
163  return f;
164 }
165 
166 /* Allocate a frame for from FROM_NODE to TO_NODE via TO_NEXT_INDEX.
167  Returns frame index. */
168 static vlib_frame_t *
170  u32 to_next_index)
171 {
172  vlib_node_t *from_node;
173 
174  from_node = vlib_get_node (vm, from_node_runtime->node_index);
175  ASSERT (to_next_index < vec_len (from_node->next_nodes));
176 
177  return vlib_frame_alloc_to_node (vm, from_node->next_nodes[to_next_index],
178  /* frame_flags */ 0);
179 }
180 
181 vlib_frame_t *
183 {
184  vlib_frame_t *f = vlib_frame_alloc_to_node (vm, to_node_index,
185  /* frame_flags */
187  return vlib_get_frame (vm, f);
188 }
189 
190 static inline void
192 {
193  if (CLIB_DEBUG > 0)
194  {
195  int i;
196  u32 *from = vlib_frame_vector_args (f);
197 
198  /* Check for bad buffer index values */
199  for (i = 0; i < f->n_vectors; i++)
200  {
201  if (from[i] == 0)
202  {
203  clib_warning ("BUG: buffer index 0 at index %d", i);
204  ASSERT (0);
205  }
206  else if (from[i] == 0xfefefefe)
207  {
208  clib_warning ("BUG: frame poison pattern at index %d", i);
209  ASSERT (0);
210  }
211  }
212  }
213 }
214 
215 void
217 {
219  vlib_node_t *to_node;
220 
221  if (f->n_vectors == 0)
222  return;
223 
225 
226  to_node = vlib_get_node (vm, to_node_index);
227 
228  vec_add2 (vm->node_main.pending_frames, p, 1);
229 
231  p->frame = vlib_get_frame (vm, f);
232  p->node_runtime_index = to_node->runtime_index;
234 }
235 
236 /* Free given frame. */
237 void
239 {
240  vlib_node_main_t *nm = &vm->node_main;
241  vlib_node_t *node;
242  vlib_frame_size_t *fs;
243 
245 
246  node = vlib_get_node (vm, r->node_index);
247  fs = get_frame_size_info (nm, node->scalar_size, node->vector_size);
248 
250 
251  /* No next frames may point to freed frame. */
252  if (CLIB_DEBUG > 0)
253  {
254  vlib_next_frame_t *nf;
255  vec_foreach (nf, vm->node_main.next_frames) ASSERT (nf->frame != f);
256  }
257 
259 
260  vec_add1 (fs->free_frames, f);
261  ASSERT (fs->n_alloc_frames > 0);
262  fs->n_alloc_frames -= 1;
263 }
264 
265 static clib_error_t *
267  unformat_input_t * input, vlib_cli_command_t * cmd)
268 {
269  vlib_node_main_t *nm = &vm->node_main;
270  vlib_frame_size_t *fs;
271 
272  vlib_cli_output (vm, "%=6s%=12s%=12s", "Size", "# Alloc", "# Free");
273  vec_foreach (fs, nm->frame_sizes)
274  {
275  u32 n_alloc = fs->n_alloc_frames;
276  u32 n_free = vec_len (fs->free_frames);
277 
278  if (n_alloc + n_free > 0)
279  vlib_cli_output (vm, "%=6d%=12d%=12d",
280  fs - nm->frame_sizes, n_alloc, n_free);
281  }
282 
283  return 0;
284 }
285 
286 /* *INDENT-OFF* */
287 VLIB_CLI_COMMAND (show_frame_stats_cli, static) = {
288  .path = "show vlib frame-allocation",
289  .short_help = "Show node dispatch frame statistics",
290  .function = show_frame_stats,
291 };
292 /* *INDENT-ON* */
293 
294 /* Change ownership of enqueue rights to given next node. */
295 static void
297  vlib_node_runtime_t * node_runtime,
298  u32 next_index)
299 {
300  vlib_node_main_t *nm = &vm->node_main;
301  vlib_next_frame_t *next_frame;
302  vlib_node_t *node, *next_node;
303 
304  node = vec_elt (nm->nodes, node_runtime->node_index);
305 
306  /* Only internal & input nodes are allowed to call other nodes. */
308  || node->type == VLIB_NODE_TYPE_INPUT
309  || node->type == VLIB_NODE_TYPE_PROCESS);
310 
311  ASSERT (vec_len (node->next_nodes) == node_runtime->n_next_nodes);
312 
313  next_frame =
314  vlib_node_runtime_get_next_frame (vm, node_runtime, next_index);
315  next_node = vec_elt (nm->nodes, node->next_nodes[next_index]);
316 
317  if (next_node->owner_node_index != VLIB_INVALID_NODE_INDEX)
318  {
319  /* Get frame from previous owner. */
320  vlib_next_frame_t *owner_next_frame;
321  vlib_next_frame_t tmp;
322 
323  owner_next_frame =
325  next_node->owner_node_index,
326  next_node->owner_next_index);
327 
328  /* Swap target next frame with owner's. */
329  tmp = owner_next_frame[0];
330  owner_next_frame[0] = next_frame[0];
331  next_frame[0] = tmp;
332 
333  /*
334  * If next_frame is already pending, we have to track down
335  * all pending frames and fix their next_frame_index fields.
336  */
337  if (next_frame->flags & VLIB_FRAME_PENDING)
338  {
340  if (next_frame->frame != NULL)
341  {
342  vec_foreach (p, nm->pending_frames)
343  {
344  if (p->frame == next_frame->frame)
345  {
346  p->next_frame_index =
347  next_frame - vm->node_main.next_frames;
348  }
349  }
350  }
351  }
352  }
353  else
354  {
355  /* No previous owner. Take ownership. */
356  next_frame->flags |= VLIB_FRAME_OWNER;
357  }
358 
359  /* Record new owner. */
360  next_node->owner_node_index = node->index;
361  next_node->owner_next_index = next_index;
362 
363  /* Now we should be owner. */
364  ASSERT (next_frame->flags & VLIB_FRAME_OWNER);
365 }
366 
367 /* Make sure that magic number is still there.
368  Otherwise, it is likely that caller has overrun frame arguments. */
369 always_inline void
371  vlib_frame_t * f, vlib_node_t * n, uword next_index)
372 {
373  vlib_node_t *next_node = vlib_get_node (vm, n->next_nodes[next_index]);
374  u32 *magic = vlib_frame_find_magic (f, next_node);
375  ASSERT (VLIB_FRAME_MAGIC == magic[0]);
376 }
377 
378 vlib_frame_t *
381  u32 next_index, u32 allocate_new_next_frame)
382 {
383  vlib_frame_t *f;
384  vlib_next_frame_t *nf;
385  u32 n_used;
386 
387  nf = vlib_node_runtime_get_next_frame (vm, node, next_index);
388 
389  /* Make sure this next frame owns right to enqueue to destination frame. */
390  if (PREDICT_FALSE (!(nf->flags & VLIB_FRAME_OWNER)))
391  vlib_next_frame_change_ownership (vm, node, next_index);
392 
393  /* ??? Don't need valid flag: can use frame_index == ~0 */
395  {
396  nf->frame = vlib_frame_alloc (vm, node, next_index);
398  }
399 
400  f = nf->frame;
401 
402  /* Has frame been removed from pending vector (e.g. finished dispatching)?
403  If so we can reuse frame. */
404  if ((nf->flags & VLIB_FRAME_PENDING)
405  && !(f->frame_flags & VLIB_FRAME_PENDING))
406  {
407  nf->flags &= ~VLIB_FRAME_PENDING;
408  f->n_vectors = 0;
409  f->flags = 0;
410  }
411 
412  /* Allocate new frame if current one is marked as no-append or
413  it is already full. */
414  n_used = f->n_vectors;
415  if (n_used >= VLIB_FRAME_SIZE || (allocate_new_next_frame && n_used > 0) ||
417  {
418  /* Old frame may need to be freed after dispatch, since we'll have
419  two redundant frames from node -> next node. */
421  {
422  vlib_frame_t *f_old = vlib_get_frame (vm, nf->frame);
424  }
425 
426  /* Allocate new frame to replace full one. */
427  f = nf->frame = vlib_frame_alloc (vm, node, next_index);
428  n_used = f->n_vectors;
429  }
430 
431  /* Should have free vectors in frame now. */
432  ASSERT (n_used < VLIB_FRAME_SIZE);
433 
434  if (CLIB_DEBUG > 0)
435  {
436  validate_frame_magic (vm, f,
437  vlib_get_node (vm, node->node_index), next_index);
438  }
439 
440  return f;
441 }
442 
443 static void
445  vlib_node_runtime_t * rt,
446  u32 next_index, u32 n_vectors_left)
447 {
448  vlib_node_main_t *nm = &vm->node_main;
449  vlib_next_frame_t *nf;
450  vlib_frame_t *f;
451  vlib_node_runtime_t *next_rt;
452  vlib_node_t *next_node;
453  u32 n_before, n_after;
454 
455  nf = vlib_node_runtime_get_next_frame (vm, rt, next_index);
456  f = vlib_get_frame (vm, nf->frame);
457 
458  ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
459 
461 
462  n_after = VLIB_FRAME_SIZE - n_vectors_left;
463  n_before = f->n_vectors;
464 
465  ASSERT (n_after >= n_before);
466 
468  nf->node_runtime_index);
469  next_node = vlib_get_node (vm, next_rt->node_index);
470  if (n_after > 0 && next_node->validate_frame)
471  {
472  u8 *msg = next_node->validate_frame (vm, rt, f);
473  if (msg)
474  {
475  clib_warning ("%v", msg);
476  ASSERT (0);
477  }
478  vec_free (msg);
479  }
480 }
481 
482 void
485  u32 next_index, u32 n_vectors_left)
486 {
487  vlib_node_main_t *nm = &vm->node_main;
488  vlib_next_frame_t *nf;
489  vlib_frame_t *f;
490  u32 n_vectors_in_frame;
491 
492  if (CLIB_DEBUG > 0)
493  vlib_put_next_frame_validate (vm, r, next_index, n_vectors_left);
494 
495  nf = vlib_node_runtime_get_next_frame (vm, r, next_index);
496  f = vlib_get_frame (vm, nf->frame);
497 
498  /* Make sure that magic number is still there. Otherwise, caller
499  has overrun frame meta data. */
500  if (CLIB_DEBUG > 0)
501  {
503  validate_frame_magic (vm, f, node, next_index);
504  }
505 
506  /* Convert # of vectors left -> number of vectors there. */
507  ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
508  n_vectors_in_frame = VLIB_FRAME_SIZE - n_vectors_left;
509 
510  f->n_vectors = n_vectors_in_frame;
511 
512  /* If vectors were added to frame, add to pending vector. */
513  if (PREDICT_TRUE (n_vectors_in_frame > 0))
514  {
516  u32 v0, v1;
517 
518  r->cached_next_index = next_index;
519 
520  if (!(f->frame_flags & VLIB_FRAME_PENDING))
521  {
522  __attribute__ ((unused)) vlib_node_t *node;
523  vlib_node_t *next_node;
524  vlib_node_runtime_t *next_runtime;
525 
526  node = vlib_get_node (vm, r->node_index);
527  next_node = vlib_get_next_node (vm, r->node_index, next_index);
528  next_runtime = vlib_node_get_runtime (vm, next_node->index);
529 
530  vec_add2 (nm->pending_frames, p, 1);
531 
532  p->frame = nf->frame;
534  p->next_frame_index = nf - nm->next_frames;
535  nf->flags |= VLIB_FRAME_PENDING;
537 
538  /*
539  * If we're going to dispatch this frame on another thread,
540  * force allocation of a new frame. Otherwise, we create
541  * a dangling frame reference. Each thread has its own copy of
542  * the next_frames vector.
543  */
544  if (0 && r->thread_index != next_runtime->thread_index)
545  {
546  nf->frame = NULL;
548  }
549  }
550 
551  /* Copy trace flag from next_frame and from runtime. */
552  nf->flags |=
553  (nf->flags & VLIB_NODE_FLAG_TRACE) | (r->
555 
557  v1 = v0 + n_vectors_in_frame;
559  if (PREDICT_FALSE (v1 < v0))
560  {
562  vec_elt (node->n_vectors_by_next_node, next_index) += v0;
563  }
564  }
565 }
566 
567 /* Sync up runtime (32 bit counters) and main node stats (64 bit counters). */
568 never_inline void
571  uword n_calls, uword n_vectors, uword n_clocks)
572 {
573  vlib_node_t *n = vlib_get_node (vm, r->node_index);
574 
575  n->stats_total.calls += n_calls + r->calls_since_last_overflow;
576  n->stats_total.vectors += n_vectors + r->vectors_since_last_overflow;
577  n->stats_total.clocks += n_clocks + r->clocks_since_last_overflow;
580 
584 }
585 
586 always_inline void __attribute__ ((unused))
588  vlib_process_t * p,
589  uword n_calls, uword n_vectors, uword n_clocks)
590 {
591  vlib_node_runtime_t *rt = &p->node_runtime;
592  vlib_node_t *n = vlib_get_node (vm, rt->node_index);
593  vlib_node_runtime_sync_stats (vm, rt, n_calls, n_vectors, n_clocks);
594  n->stats_total.suspends += p->n_suspends;
595  p->n_suspends = 0;
596 }
597 
598 void
600 {
602 
603  if (n->type == VLIB_NODE_TYPE_PROCESS)
604  {
605  /* Nothing to do for PROCESS nodes except in main thread */
606  if (vm != &vlib_global_main)
607  return;
608 
611  p->n_suspends = 0;
612  rt = &p->node_runtime;
613  }
614  else
615  rt =
617  n->runtime_index);
618 
619  vlib_node_runtime_sync_stats (vm, rt, 0, 0, 0);
620 
621  /* Sync up runtime next frame vector counters with main node structure. */
622  {
623  vlib_next_frame_t *nf;
624  uword i;
625  for (i = 0; i < rt->n_next_nodes; i++)
626  {
627  nf = vlib_node_runtime_get_next_frame (vm, rt, i);
631  }
632  }
633 }
634 
638  uword n_calls,
639  uword n_vectors, uword n_clocks)
640 {
641  u32 ca0, ca1, v0, v1, cl0, cl1, r;
642 
643  cl0 = cl1 = node->clocks_since_last_overflow;
644  ca0 = ca1 = node->calls_since_last_overflow;
645  v0 = v1 = node->vectors_since_last_overflow;
646 
647  ca1 = ca0 + n_calls;
648  v1 = v0 + n_vectors;
649  cl1 = cl0 + n_clocks;
650 
651  node->calls_since_last_overflow = ca1;
652  node->clocks_since_last_overflow = cl1;
653  node->vectors_since_last_overflow = v1;
654 
655  node->max_clock_n = node->max_clock > n_clocks ?
656  node->max_clock_n : n_vectors;
657  node->max_clock = node->max_clock > n_clocks ? node->max_clock : n_clocks;
658 
659  r = vlib_node_runtime_update_main_loop_vector_stats (vm, node, n_vectors);
660 
661  if (PREDICT_FALSE (ca1 < ca0 || v1 < v0 || cl1 < cl0))
662  {
663  node->calls_since_last_overflow = ca0;
664  node->clocks_since_last_overflow = cl0;
665  node->vectors_since_last_overflow = v0;
666 
667  vlib_node_runtime_sync_stats (vm, node, n_calls, n_vectors, n_clocks);
668  }
669 
670  return r;
671 }
672 
673 always_inline void
675  vlib_process_t * p,
676  uword n_calls, uword n_vectors, uword n_clocks)
677 {
679  n_calls, n_vectors, n_clocks);
680 }
681 
682 static clib_error_t *
684  unformat_input_t * input, vlib_cli_command_t * cmd)
685 {
687  return 0;
688 }
689 
690 /* *INDENT-OFF* */
691 VLIB_CLI_COMMAND (elog_clear_cli, static) = {
692  .path = "event-logger clear",
693  .short_help = "Clear the event log",
694  .function = vlib_cli_elog_clear,
695 };
696 /* *INDENT-ON* */
697 
698 #ifdef CLIB_UNIX
699 static clib_error_t *
701  unformat_input_t * input, vlib_cli_command_t * cmd)
702 {
703  elog_main_t *em = &vm->elog_main;
704  char *file, *chroot_file;
705  clib_error_t *error = 0;
706 
707  if (!unformat (input, "%s", &file))
708  {
709  vlib_cli_output (vm, "expected file name, got `%U'",
710  format_unformat_error, input);
711  return 0;
712  }
713 
714  /* It's fairly hard to get "../oopsie" through unformat; just in case */
715  if (strstr (file, "..") || index (file, '/'))
716  {
717  vlib_cli_output (vm, "illegal characters in filename '%s'", file);
718  return 0;
719  }
720 
721  chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
722 
723  vec_free (file);
724 
725  vlib_cli_output (vm, "Saving %wd of %wd events to %s",
727  elog_buffer_capacity (em), chroot_file);
728 
730  error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
732  vec_free (chroot_file);
733  return error;
734 }
735 
736 void
738 {
740  elog_main_t *em = &vm->elog_main;
741 
742  u8 *filename;
744 
745  if ((vm->elog_post_mortem_dump + vm->dispatch_pcap_postmortem) == 0)
746  return;
747 
748  if (vm->dispatch_pcap_postmortem)
749  {
750  clib_error_t *error;
751  pcap_main_t *pm = &vm->dispatch_pcap_main;
752 
754  pm->file_name = (char *) format (0, "/tmp/dispatch_post_mortem.%d%c",
755  getpid (), 0);
756  error = pcap_write (pm);
757  pcap_close (pm);
758  if (error)
759  clib_error_report (error);
760  /*
761  * We're in the middle of crashing. Don't try to free the filename.
762  */
763  }
764 
765  if (vm->elog_post_mortem_dump)
766  {
767  filename = format (0, "/tmp/elog_post_mortem.%d%c", getpid (), 0);
768  error = elog_write_file (em, (char *) filename, 1 /* flush ring */ );
769  if (error)
770  clib_error_report (error);
771  /*
772  * We're in the middle of crashing. Don't try to free the filename.
773  */
774  }
775 }
776 
777 /* *INDENT-OFF* */
778 VLIB_CLI_COMMAND (elog_save_cli, static) = {
779  .path = "event-logger save",
780  .short_help = "event-logger save <filename> (saves log in /tmp/<filename>)",
781  .function = elog_save_buffer,
782 };
783 /* *INDENT-ON* */
784 
785 static clib_error_t *
787  unformat_input_t * input, vlib_cli_command_t * cmd)
788 {
789  elog_main_t *em = &vm->elog_main;
790 
792 
793  vlib_cli_output (vm, "Stopped the event logger...");
794  return 0;
795 }
796 
797 /* *INDENT-OFF* */
798 VLIB_CLI_COMMAND (elog_stop_cli, static) = {
799  .path = "event-logger stop",
800  .short_help = "Stop the event-logger",
801  .function = elog_stop,
802 };
803 /* *INDENT-ON* */
804 
805 static clib_error_t *
807  unformat_input_t * input, vlib_cli_command_t * cmd)
808 {
809  elog_main_t *em = &vm->elog_main;
810 
812 
813  vlib_cli_output (vm, "Restarted the event logger...");
814  return 0;
815 }
816 
817 /* *INDENT-OFF* */
818 VLIB_CLI_COMMAND (elog_restart_cli, static) = {
819  .path = "event-logger restart",
820  .short_help = "Restart the event-logger",
821  .function = elog_restart,
822 };
823 /* *INDENT-ON* */
824 
825 static clib_error_t *
827  unformat_input_t * input, vlib_cli_command_t * cmd)
828 {
829  elog_main_t *em = &vm->elog_main;
830  u32 tmp;
831 
832  /* Stop the parade */
834 
835  if (unformat (input, "%d", &tmp))
836  {
837  elog_alloc (em, tmp);
839  }
840  else
841  return clib_error_return (0, "Must specify how many events in the ring");
842 
843  vlib_cli_output (vm, "Resized ring and restarted the event logger...");
844  return 0;
845 }
846 
847 /* *INDENT-OFF* */
848 VLIB_CLI_COMMAND (elog_resize_cli, static) = {
849  .path = "event-logger resize",
850  .short_help = "event-logger resize <nnn>",
851  .function = elog_resize_command_fn,
852 };
853 /* *INDENT-ON* */
854 
855 #endif /* CLIB_UNIX */
856 
857 static void
859 {
860  elog_main_t *em = &vm->elog_main;
861  elog_event_t *e, *es;
862  f64 dt;
863 
864  /* Show events in VLIB time since log clock starts after VLIB clock. */
865  dt = (em->init_time.cpu - vm->clib_time.init_cpu_time)
867 
868  es = elog_peek_events (em);
869  vlib_cli_output (vm, "%d of %d events in buffer, logger %s", vec_len (es),
870  em->event_ring_size,
872  "running" : "stopped");
873  vec_foreach (e, es)
874  {
875  vlib_cli_output (vm, "%18.9f: %U",
876  e->time + dt, format_elog_event, em, e);
877  n_events_to_show--;
878  if (n_events_to_show == 0)
879  break;
880  }
881  vec_free (es);
882 
883 }
884 
885 static clib_error_t *
887  unformat_input_t * input, vlib_cli_command_t * cmd)
888 {
889  u32 n_events_to_show;
890  clib_error_t *error = 0;
891 
892  n_events_to_show = 250;
894  {
895  if (unformat (input, "%d", &n_events_to_show))
896  ;
897  else if (unformat (input, "all"))
898  n_events_to_show = ~0;
899  else
900  return unformat_parse_error (input);
901  }
902  elog_show_buffer_internal (vm, n_events_to_show);
903  return error;
904 }
905 
906 /* *INDENT-OFF* */
907 VLIB_CLI_COMMAND (elog_show_cli, static) = {
908  .path = "show event-logger",
909  .short_help = "Show event logger info",
910  .function = elog_show_buffer,
911 };
912 /* *INDENT-ON* */
913 
914 void
916 {
918 }
919 
920 static inline void
922  u32 node_index,
923  u64 time, u32 n_vectors, u32 is_return)
924 {
926  elog_main_t *em = &evm->elog_main;
927  int enabled = evm->elog_trace_graph_dispatch |
929 
930  if (PREDICT_FALSE (enabled && n_vectors))
931  {
932  if (PREDICT_FALSE (!elog_is_enabled (em)))
933  {
934  evm->elog_trace_graph_dispatch = 0;
935  evm->elog_trace_graph_circuit = 0;
936  return;
937  }
938  if (PREDICT_TRUE
940  (evm->elog_trace_graph_circuit &&
941  node_index == evm->elog_trace_graph_circuit_node_index)))
942  {
943  elog_track (em,
944  /* event type */
945  vec_elt_at_index (is_return
948  node_index),
949  /* track */
950  (vm->thread_index ?
952  : &em->default_track),
953  /* data to log */ n_vectors);
954  }
955  }
956 }
957 
958 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0
959 void (*vlib_buffer_trace_trajectory_cb) (vlib_buffer_t * b, u32 node_index);
960 void (*vlib_buffer_trace_trajectory_init_cb) (vlib_buffer_t * b);
961 
962 void
963 vlib_buffer_trace_trajectory_init (vlib_buffer_t * b)
964 {
965  if (PREDICT_TRUE (vlib_buffer_trace_trajectory_init_cb != 0))
966  {
967  (*vlib_buffer_trace_trajectory_init_cb) (b);
968  }
969 }
970 
971 #endif
972 
973 static inline void
975 {
976 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0
977  if (PREDICT_TRUE (vlib_buffer_trace_trajectory_cb != 0))
978  {
979  (*vlib_buffer_trace_trajectory_cb) (b, node_index);
980  }
981 #endif
982 }
983 
984 u8 *format_vnet_buffer_flags (u8 * s, va_list * args) __attribute__ ((weak));
985 u8 *
986 format_vnet_buffer_flags (u8 * s, va_list * args)
987 {
988  s = format (s, "BUG STUB %s", __FUNCTION__);
989  return s;
990 }
991 
992 u8 *format_vnet_buffer_opaque (u8 * s, va_list * args) __attribute__ ((weak));
993 u8 *
994 format_vnet_buffer_opaque (u8 * s, va_list * args)
995 {
996  s = format (s, "BUG STUB %s", __FUNCTION__);
997  return s;
998 }
999 
1000 u8 *format_vnet_buffer_opaque2 (u8 * s, va_list * args)
1001  __attribute__ ((weak));
1002 u8 *
1003 format_vnet_buffer_opaque2 (u8 * s, va_list * args)
1004 {
1005  s = format (s, "BUG STUB %s", __FUNCTION__);
1006  return s;
1007 }
1008 
1009 static u8 *
1010 format_buffer_metadata (u8 * s, va_list * args)
1011 {
1012  vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
1013 
1014  s = format (s, "flags: %U\n", format_vnet_buffer_flags, b);
1015  s = format (s, "current_data: %d, current_length: %d\n",
1016  (i32) (b->current_data), (i32) (b->current_length));
1017  s = format
1018  (s,
1019  "current_config_index/punt_reason: %d, flow_id: %x, next_buffer: %x\n",
1021  s =
1022  format (s, "error: %d, ref_count: %d, buffer_pool_index: %d\n",
1023  (u32) (b->error), (u32) (b->ref_count),
1024  (u32) (b->buffer_pool_index));
1025  s =
1026  format (s, "trace_handle: 0x%x, len_not_first_buf: %d\n", b->trace_handle,
1028  return s;
1029 }
1030 
1031 #define A(x) vec_add1(vm->pcap_buffer, (x))
1032 
1033 static void
1036 {
1037  int i;
1038  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **bufp, *b;
1039  pcap_main_t *pm = &vlib_global_main.dispatch_pcap_main;
1040  vlib_trace_main_t *tm = &vm->trace_main;
1041  u32 capture_size;
1042  vlib_node_t *n;
1043  i32 n_left;
1044  f64 time_now = vlib_time_now (vm);
1045  u32 *from;
1046  u8 *d;
1047  u8 string_count;
1048 
1049  /* Input nodes don't have frames yet */
1050  if (frame == 0 || frame->n_vectors == 0)
1051  return;
1052 
1053  from = vlib_frame_vector_args (frame);
1054  vlib_get_buffers (vm, from, bufs, frame->n_vectors);
1055  bufp = bufs;
1056 
1057  n = vlib_get_node (vm, node->node_index);
1058 
1059  for (i = 0; i < frame->n_vectors; i++)
1060  {
1062  {
1063  b = bufp[i];
1064 
1066  string_count = 0;
1067 
1068  /* Version, flags */
1071  A (0 /* string_count */ );
1072  A (n->protocol_hint);
1073 
1074  /* Buffer index (big endian) */
1075  A ((from[i] >> 24) & 0xff);
1076  A ((from[i] >> 16) & 0xff);
1077  A ((from[i] >> 8) & 0xff);
1078  A ((from[i] >> 0) & 0xff);
1079 
1080  /* Node name, NULL-terminated ASCII */
1081  vm->pcap_buffer = format (vm->pcap_buffer, "%v%c", n->name, 0);
1082  string_count++;
1083 
1084  vm->pcap_buffer = format (vm->pcap_buffer, "%U%c",
1085  format_buffer_metadata, b, 0);
1086  string_count++;
1087  vm->pcap_buffer = format (vm->pcap_buffer, "%U%c",
1089  string_count++;
1090  vm->pcap_buffer = format (vm->pcap_buffer, "%U%c",
1092  string_count++;
1093 
1094  /* Is this packet traced? */
1095  if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
1096  {
1100 
1101  vm->pcap_buffer = format (vm->pcap_buffer, "%U%c",
1102  format_vlib_trace, vm, h[0], 0);
1103  string_count++;
1104  }
1105 
1106  /* Save the string count */
1107  vm->pcap_buffer[2] = string_count;
1108 
1109  /* Figure out how many bytes in the pcap trace */
1110  capture_size = vec_len (vm->pcap_buffer) +
1111  +vlib_buffer_length_in_chain (vm, b);
1112 
1114  n_left = clib_min (capture_size, 16384);
1115  d = pcap_add_packet (pm, time_now, n_left, capture_size);
1116 
1117  /* Copy the header */
1119  d += vec_len (vm->pcap_buffer);
1120 
1121  n_left = clib_min
1122  (vlib_buffer_length_in_chain (vm, b),
1123  (16384 - vec_len (vm->pcap_buffer)));
1124  /* Copy the packet data */
1125  while (1)
1126  {
1127  u32 copy_length = clib_min ((u32) n_left, b->current_length);
1128  clib_memcpy_fast (d, b->data + b->current_data, copy_length);
1129  n_left -= b->current_length;
1130  if (n_left <= 0)
1131  break;
1132  d += b->current_length;
1133  ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
1134  b = vlib_get_buffer (vm, b->next_buffer);
1135  }
1137  }
1138  }
1139 }
1140 
1145  vlib_node_state_t dispatch_state,
1146  vlib_frame_t * frame, u64 last_time_stamp)
1147 {
1148  uword n, v;
1149  u64 t;
1150  vlib_node_main_t *nm = &vm->node_main;
1151  vlib_next_frame_t *nf;
1152 
1153  if (CLIB_DEBUG > 0)
1154  {
1155  vlib_node_t *n = vlib_get_node (vm, node->node_index);
1156  ASSERT (n->type == type);
1157  }
1158 
1159  /* Only non-internal nodes may be disabled. */
1160  if (type != VLIB_NODE_TYPE_INTERNAL && node->state != dispatch_state)
1161  {
1162  ASSERT (type != VLIB_NODE_TYPE_INTERNAL);
1163  return last_time_stamp;
1164  }
1165 
1166  if ((type == VLIB_NODE_TYPE_PRE_INPUT || type == VLIB_NODE_TYPE_INPUT)
1167  && dispatch_state != VLIB_NODE_STATE_INTERRUPT)
1168  {
1170  /* Only call node when count reaches zero. */
1171  if (c)
1172  {
1173  node->input_main_loops_per_call = c - 1;
1174  return last_time_stamp;
1175  }
1176  }
1177 
1178  /* Speculatively prefetch next frames. */
1179  if (node->n_next_nodes > 0)
1180  {
1181  nf = vec_elt_at_index (nm->next_frames, node->next_frame_index);
1182  CLIB_PREFETCH (nf, 4 * sizeof (nf[0]), WRITE);
1183  }
1184 
1185  vm->cpu_time_last_node_dispatch = last_time_stamp;
1186 
1188  last_time_stamp, frame ? frame->n_vectors : 0,
1189  /* is_after */ 0);
1190 
1191  vlib_node_runtime_perf_counter (vm, node, frame, 0, last_time_stamp,
1193 
1194  /*
1195  * Turn this on if you run into
1196  * "bad monkey" contexts, and you want to know exactly
1197  * which nodes they've visited... See ixge.c...
1198  */
1199  if (VLIB_BUFFER_TRACE_TRAJECTORY && frame)
1200  {
1201  int i;
1202  u32 *from;
1203  from = vlib_frame_vector_args (frame);
1204  for (i = 0; i < frame->n_vectors; i++)
1205  {
1206  vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
1207  add_trajectory_trace (b, node->node_index);
1208  }
1210  dispatch_pcap_trace (vm, node, frame);
1211  n = node->function (vm, node, frame);
1212  }
1213  else
1214  {
1216  dispatch_pcap_trace (vm, node, frame);
1217  n = node->function (vm, node, frame);
1218  }
1219 
1220  t = clib_cpu_time_now ();
1221 
1222  vlib_node_runtime_perf_counter (vm, node, frame, n, t,
1224 
1225  vlib_elog_main_loop_event (vm, node->node_index, t, n, 1 /* is_after */ );
1226 
1227  vm->main_loop_vectors_processed += n;
1228  vm->main_loop_nodes_processed += n > 0;
1229 
1230  v = vlib_node_runtime_update_stats (vm, node,
1231  /* n_calls */ 1,
1232  /* n_vectors */ n,
1233  /* n_clocks */ t - last_time_stamp);
1234 
1235  /* When in interrupt mode and vector rate crosses threshold switch to
1236  polling mode. */
1237  if (PREDICT_FALSE ((dispatch_state == VLIB_NODE_STATE_INTERRUPT)
1238  || (dispatch_state == VLIB_NODE_STATE_POLLING
1239  && (node->flags
1240  &
1242  {
1243  /* *INDENT-OFF* */
1244  ELOG_TYPE_DECLARE (e) =
1245  {
1246  .function = (char *) __FUNCTION__,
1247  .format = "%s vector length %d, switching to %s",
1248  .format_args = "T4i4t4",
1249  .n_enum_strings = 2,
1250  .enum_strings = {
1251  "interrupt", "polling",
1252  },
1253  };
1254  /* *INDENT-ON* */
1255  struct
1256  {
1257  u32 node_name, vector_length, is_polling;
1258  } *ed;
1259 
1260  if ((dispatch_state == VLIB_NODE_STATE_INTERRUPT
1261  && v >= nm->polling_threshold_vector_length) &&
1262  !(node->flags &
1264  {
1265  vlib_node_t *n = vlib_get_node (vm, node->node_index);
1266  n->state = VLIB_NODE_STATE_POLLING;
1267  node->state = VLIB_NODE_STATE_POLLING;
1268  node->flags &=
1271  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] -= 1;
1272  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] += 1;
1273 
1274  if (PREDICT_FALSE (vlib_global_main.elog_trace_graph_dispatch))
1275  {
1277  + vm->thread_index;
1278 
1279  ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
1280  w->elog_track);
1281  ed->node_name = n->name_elog_string;
1282  ed->vector_length = v;
1283  ed->is_polling = 1;
1284  }
1285  }
1286  else if (dispatch_state == VLIB_NODE_STATE_POLLING
1287  && v <= nm->interrupt_threshold_vector_length)
1288  {
1289  vlib_node_t *n = vlib_get_node (vm, node->node_index);
1290  if (node->flags &
1292  {
1293  /* Switch to interrupt mode after dispatch in polling one more time.
1294  This allows driver to re-enable interrupts. */
1295  n->state = VLIB_NODE_STATE_INTERRUPT;
1296  node->state = VLIB_NODE_STATE_INTERRUPT;
1297  node->flags &=
1299  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] -= 1;
1300  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] += 1;
1301 
1302  }
1303  else
1304  {
1306  + vm->thread_index;
1307  node->flags |=
1309  if (PREDICT_FALSE (vlib_global_main.elog_trace_graph_dispatch))
1310  {
1311  ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
1312  w->elog_track);
1313  ed->node_name = n->name_elog_string;
1314  ed->vector_length = v;
1315  ed->is_polling = 0;
1316  }
1317  }
1318  }
1319  }
1320 
1321  return t;
1322 }
1323 
1324 static u64
1325 dispatch_pending_node (vlib_main_t * vm, uword pending_frame_index,
1326  u64 last_time_stamp)
1327 {
1328  vlib_node_main_t *nm = &vm->node_main;
1329  vlib_frame_t *f;
1330  vlib_next_frame_t *nf, nf_placeholder;
1332  vlib_frame_t *restore_frame;
1334 
1335  /* See comment below about dangling references to nm->pending_frames */
1336  p = nm->pending_frames + pending_frame_index;
1337 
1339  p->node_runtime_index);
1340 
1341  f = vlib_get_frame (vm, p->frame);
1343  {
1344  /* No next frame: so use placeholder on stack. */
1345  nf = &nf_placeholder;
1347  nf->frame = NULL;
1348  }
1349  else
1351 
1353 
1354  /* Force allocation of new frame while current frame is being
1355  dispatched. */
1356  restore_frame = NULL;
1357  if (nf->frame == p->frame)
1358  {
1359  nf->frame = NULL;
1362  restore_frame = p->frame;
1363  }
1364 
1365  /* Frame must be pending. */
1367  ASSERT (f->n_vectors > 0);
1368 
1369  /* Copy trace flag from next frame to node.
1370  Trace flag indicates that at least one vector in the dispatched
1371  frame is traced. */
1372  n->flags &= ~VLIB_NODE_FLAG_TRACE;
1373  n->flags |= (nf->flags & VLIB_FRAME_TRACE) ? VLIB_NODE_FLAG_TRACE : 0;
1374  nf->flags &= ~VLIB_FRAME_TRACE;
1375 
1376  last_time_stamp = dispatch_node (vm, n,
1378  VLIB_NODE_STATE_POLLING,
1379  f, last_time_stamp);
1380  /* Internal node vector-rate accounting, for summary stats */
1381  vm->internal_node_vectors += f->n_vectors;
1382  vm->internal_node_calls++;
1386 
1388 
1389  /* Frame is ready to be used again, so restore it. */
1390  if (restore_frame != NULL)
1391  {
1392  /*
1393  * We musn't restore a frame that is flagged to be freed. This
1394  * shouldn't happen since frames to be freed post dispatch are
1395  * those used when the to-node frame becomes full i.e. they form a
1396  * sort of queue of frames to a single node. If we get here then
1397  * the to-node frame and the pending frame *were* the same, and so
1398  * we removed the to-node frame. Therefore this frame is no
1399  * longer part of the queue for that node and hence it cannot be
1400  * it's overspill.
1401  */
1403 
1404  /*
1405  * NB: dispatching node n can result in the creation and scheduling
1406  * of new frames, and hence in the reallocation of nm->pending_frames.
1407  * Recompute p, or no supper. This was broken for more than 10 years.
1408  */
1409  p = nm->pending_frames + pending_frame_index;
1410 
1411  /*
1412  * p->next_frame_index can change during node dispatch if node
1413  * function decides to change graph hook up.
1414  */
1417 
1418  if (NULL == nf->frame)
1419  {
1420  /* no new frame has been assigned to this node, use the saved one */
1421  nf->frame = restore_frame;
1422  f->n_vectors = 0;
1423  }
1424  else
1425  {
1426  /* The node has gained a frame, implying packets from the current frame
1427  were re-queued to this same node. we don't need the saved one
1428  anymore */
1429  vlib_frame_free (vm, n, f);
1430  }
1431  }
1432  else
1433  {
1435  {
1437  vlib_frame_free (vm, n, f);
1438  }
1439  }
1440 
1441  return last_time_stamp;
1442 }
1443 
1446 {
1447  return p->stack[0] == VLIB_PROCESS_STACK_MAGIC;
1448 }
1449 
1450 typedef struct
1451 {
1456 
1457 /* Called in process stack. */
1458 static uword
1460 {
1462  vlib_main_t *vm;
1464  vlib_frame_t *f;
1465  vlib_process_t *p;
1466  uword n;
1467 
1469 
1470  vm = a->vm;
1471  p = a->process;
1473 
1474  f = a->frame;
1475  node = &p->node_runtime;
1476 
1477  n = node->function (vm, node, f);
1478 
1480 
1482  clib_longjmp (&p->return_longjmp, n);
1483 
1484  return n;
1485 }
1486 
1487 /* Called in main stack. */
1490 {
1492  uword r;
1493 
1494  a.vm = vm;
1495  a.process = p;
1496  a.frame = f;
1497 
1500  {
1503  (void *) p->stack + (1 << p->log2_n_stack_bytes));
1504  }
1505  else
1507 
1508  return r;
1509 }
1510 
1513 {
1514  uword r;
1520  {
1523  }
1524  else
1526  return r;
1527 }
1528 
1529 static u64
1531  vlib_process_t * p, vlib_frame_t * f, u64 last_time_stamp)
1532 {
1533  vlib_node_main_t *nm = &vm->node_main;
1534  vlib_node_runtime_t *node_runtime = &p->node_runtime;
1535  vlib_node_t *node = vlib_get_node (vm, node_runtime->node_index);
1536  u32 old_process_index;
1537  u64 t;
1538  uword n_vectors, is_suspend;
1539 
1540  if (node->state != VLIB_NODE_STATE_POLLING
1543  return last_time_stamp;
1544 
1546 
1547  t = last_time_stamp;
1548  vlib_elog_main_loop_event (vm, node_runtime->node_index, t,
1549  f ? f->n_vectors : 0, /* is_after */ 0);
1550 
1551  /* Save away current process for suspend. */
1552  old_process_index = nm->current_process_index;
1554 
1555  vlib_node_runtime_perf_counter (vm, node_runtime, f, 0, last_time_stamp,
1557 
1558  n_vectors = vlib_process_startup (vm, p, f);
1559 
1560  nm->current_process_index = old_process_index;
1561 
1563  is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
1564  if (is_suspend)
1565  {
1567 
1568  n_vectors = 0;
1570  pf->node_runtime_index = node->runtime_index;
1571  pf->frame = f;
1572  pf->next_frame_index = ~0;
1573 
1574  p->n_suspends += 1;
1576 
1578  {
1579  TWT (tw_timer_wheel) * tw =
1580  (TWT (tw_timer_wheel) *) nm->timing_wheel;
1581  p->stop_timer_handle =
1582  TW (tw_timer_start) (tw,
1584  (node->runtime_index) /* [sic] pool idex */ ,
1585  0 /* timer_id */ ,
1587  }
1588  }
1589  else
1591 
1592  t = clib_cpu_time_now ();
1593 
1594  vlib_elog_main_loop_event (vm, node_runtime->node_index, t, is_suspend,
1595  /* is_after */ 1);
1596 
1597  vlib_node_runtime_perf_counter (vm, node_runtime, f, n_vectors, t,
1599 
1601  /* n_calls */ !is_suspend,
1602  /* n_vectors */ n_vectors,
1603  /* n_clocks */ t - last_time_stamp);
1604 
1605  return t;
1606 }
1607 
1608 void
1610 {
1611  vlib_node_main_t *nm = &vm->node_main;
1612  vlib_process_t *p = vec_elt (nm->processes, process_index);
1613  dispatch_process (vm, p, /* frame */ 0, /* cpu_time_now */ 0);
1614 }
1615 
1616 static u64
1618  uword process_index, u64 last_time_stamp)
1619 {
1620  vlib_node_main_t *nm = &vm->node_main;
1621  vlib_node_runtime_t *node_runtime;
1622  vlib_node_t *node;
1623  vlib_frame_t *f;
1624  vlib_process_t *p;
1626  u64 t, n_vectors, is_suspend;
1627 
1628  t = last_time_stamp;
1629 
1630  p = vec_elt (nm->processes, process_index);
1632  return last_time_stamp;
1633 
1636 
1639 
1640  node_runtime = &p->node_runtime;
1641  node = vlib_get_node (vm, node_runtime->node_index);
1642  f = pf->frame;
1643 
1644  vlib_elog_main_loop_event (vm, node_runtime->node_index, t,
1645  f ? f->n_vectors : 0, /* is_after */ 0);
1646 
1647  /* Save away current process for suspend. */
1649 
1650  vlib_node_runtime_perf_counter (vm, node_runtime, f, 0, last_time_stamp,
1652 
1653  n_vectors = vlib_process_resume (vm, p);
1654  t = clib_cpu_time_now ();
1655 
1656  nm->current_process_index = ~0;
1657 
1658  is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
1659  if (is_suspend)
1660  {
1661  /* Suspend it again. */
1662  n_vectors = 0;
1663  p->n_suspends += 1;
1665  {
1666  p->stop_timer_handle =
1667  TW (tw_timer_start) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
1669  (node->runtime_index) /* [sic] pool idex */ ,
1670  0 /* timer_id */ ,
1672  }
1673  }
1674  else
1675  {
1680  }
1681 
1682  t = clib_cpu_time_now ();
1683  vlib_elog_main_loop_event (vm, node_runtime->node_index, t, !is_suspend,
1684  /* is_after */ 1);
1685 
1686  vlib_node_runtime_perf_counter (vm, node_runtime, f, n_vectors, t,
1688 
1690  /* n_calls */ !is_suspend,
1691  /* n_vectors */ n_vectors,
1692  /* n_clocks */ t - last_time_stamp);
1693 
1694  return t;
1695 }
1696 
1697 void vl_api_send_pending_rpc_requests (vlib_main_t *) __attribute__ ((weak));
1698 void
1700 {
1701 }
1702 
1705  u64 cpu_time_now,
1706  vlib_node_interrupt_t * interrupts)
1707 {
1709 
1710  for (int i = 0; i < _vec_len (interrupts); i++)
1711  {
1713  in = vec_elt_at_index (interrupts, i);
1715  in->node_runtime_index);
1716  n->interrupt_data = in->data;
1717  cpu_time_now = dispatch_node (vm, n, VLIB_NODE_TYPE_INPUT,
1718  VLIB_NODE_STATE_INTERRUPT, /* frame */ 0,
1719  cpu_time_now);
1720  }
1721  return cpu_time_now;
1722 }
1723 
1724 static inline void
1726 {
1727  pcap_main_t *pm = &vm->dispatch_pcap_main;
1728 
1729  /* Reset the trace buffer and capture count */
1732  pm->n_packets_captured = 0;
1734 }
1735 
1736 
1739 {
1740  vlib_node_main_t *nm = &vm->node_main;
1742  uword i;
1743  u64 cpu_time_now;
1744  f64 now;
1746  u32 frame_queue_check_counter = 0;
1747  vlib_node_interrupt_t *empty_int_list = 0;
1748 
1749  /* Initialize pending node vector. */
1750  if (is_main)
1751  {
1752  vec_resize (nm->pending_frames, 32);
1753  _vec_len (nm->pending_frames) = 0;
1754  }
1755 
1756  /* Mark time of main loop start. */
1757  if (is_main)
1758  {
1759  cpu_time_now = vm->clib_time.last_cpu_time;
1760  vm->cpu_time_main_loop_start = cpu_time_now;
1761  }
1762  else
1763  cpu_time_now = clib_cpu_time_now ();
1764 
1765  /* Pre-allocate interupt runtime indices and lock. */
1768  vec_alloc (empty_int_list, 32);
1772 
1773  /* Pre-allocate expired nodes. */
1778 
1782 
1783  /* Start all processes. */
1784  if (is_main)
1785  {
1786  uword i;
1787 
1788  /*
1789  * Perform an initial barrier sync. Pays no attention to
1790  * the barrier sync hold-down timer scheme, which won't work
1791  * at this point in time.
1792  */
1794 
1795  nm->current_process_index = ~0;
1796  for (i = 0; i < vec_len (nm->processes); i++)
1797  cpu_time_now = dispatch_process (vm, nm->processes[i], /* frame */ 0,
1798  cpu_time_now);
1799  }
1800 
1801  while (1)
1802  {
1804 
1805  if (PREDICT_FALSE (_vec_len (vm->pending_rpc_requests) > 0))
1806  {
1807  if (!is_main)
1809  }
1810 
1811  if (!is_main)
1813 
1814  if (PREDICT_FALSE (vm->check_frame_queues + frame_queue_check_counter))
1815  {
1816  u32 processed = 0;
1817 
1818  if (vm->check_frame_queues)
1819  {
1820  frame_queue_check_counter = 100;
1821  vm->check_frame_queues = 0;
1822  }
1823 
1824  vec_foreach (fqm, tm->frame_queue_mains)
1825  processed += vlib_frame_queue_dequeue (vm, fqm);
1826 
1827  /* No handoff queue work found? */
1828  if (processed)
1829  frame_queue_check_counter = 100;
1830  else
1831  frame_queue_check_counter--;
1832  }
1833 
1836  cpu_time_now);
1837 
1838  /*
1839  * When trying to understand aggravating, hard-to-reproduce
1840  * bugs: reset / restart the pcap dispatch trace once per
1841  * main thread dispatch cycle. All threads share the same
1842  * (spinlock-protected) dispatch trace buffer. It might take
1843  * a few tries to capture a good post-mortem trace of
1844  * a multi-thread issue. Best we can do without a big refactor job.
1845  */
1846  if (is_main && PREDICT_FALSE (vm->dispatch_pcap_postmortem != 0))
1847  pcap_postmortem_reset (vm);
1848 
1849  /* Process pre-input nodes. */
1850  cpu_time_now = clib_cpu_time_now ();
1852  cpu_time_now = dispatch_node (vm, n,
1854  VLIB_NODE_STATE_POLLING,
1855  /* frame */ 0,
1856  cpu_time_now);
1857 
1858  /* Next process input nodes. */
1860  cpu_time_now = dispatch_node (vm, n,
1862  VLIB_NODE_STATE_POLLING,
1863  /* frame */ 0,
1864  cpu_time_now);
1865 
1866  if (PREDICT_TRUE (is_main && vm->queue_signal_pending == 0))
1867  vm->queue_signal_callback (vm);
1868 
1869  /* handle local interruots */
1870  if (_vec_len (nm->pending_local_interrupts))
1871  {
1873  nm->pending_local_interrupts = empty_int_list;
1874  cpu_time_now = dispatch_pending_interrupts (vm, nm, cpu_time_now,
1875  interrupts);
1876  empty_int_list = interrupts;
1877  vec_reset_length (empty_int_list);
1878  }
1879 
1880  /* handle remote interruots */
1881  if (PREDICT_FALSE (_vec_len (nm->pending_remote_interrupts)))
1882  {
1883  vlib_node_interrupt_t *interrupts;
1884 
1885  /* at this point it is known that
1886  * vec_len (nm->pending_local_interrupts) is zero so we quickly swap
1887  * local and remote vector under the spinlock */
1889  interrupts = nm->pending_remote_interrupts;
1890  nm->pending_remote_interrupts = empty_int_list;
1893 
1894  cpu_time_now = dispatch_pending_interrupts (vm, nm, cpu_time_now,
1895  interrupts);
1896  empty_int_list = interrupts;
1897  vec_reset_length (empty_int_list);
1898  }
1899 
1900  /* Input nodes may have added work to the pending vector.
1901  Process pending vector until there is nothing left.
1902  All pending vectors will be processed from input -> output. */
1903  for (i = 0; i < _vec_len (nm->pending_frames); i++)
1904  cpu_time_now = dispatch_pending_node (vm, i, cpu_time_now);
1905  /* Reset pending vector for next iteration. */
1906  _vec_len (nm->pending_frames) = 0;
1907 
1908  if (is_main)
1909  {
1910  /* *INDENT-OFF* */
1911  ELOG_TYPE_DECLARE (es) =
1912  {
1913  .format = "process tw start",
1914  .format_args = "",
1915  };
1916  ELOG_TYPE_DECLARE (ee) =
1917  {
1918  .format = "process tw end: %d",
1919  .format_args = "i4",
1920  };
1921  /* *INDENT-ON* */
1922 
1923  struct
1924  {
1925  int nready_procs;
1926  } *ed;
1927 
1928  /* Check if process nodes have expired from timing wheel. */
1930 
1932  ed = ELOG_DATA (&vlib_global_main.elog_main, es);
1933 
1936  ((TWT (tw_timer_wheel) *) nm->timing_wheel, vlib_time_now (vm),
1938 
1940 
1942  {
1943  ed = ELOG_DATA (&vlib_global_main.elog_main, ee);
1944  ed->nready_procs =
1945  _vec_len (nm->data_from_advancing_timing_wheel);
1946  }
1947 
1948  if (PREDICT_FALSE
1949  (_vec_len (nm->data_from_advancing_timing_wheel) > 0))
1950  {
1951  uword i;
1952 
1953  for (i = 0; i < _vec_len (nm->data_from_advancing_timing_wheel);
1954  i++)
1955  {
1958 
1960  {
1963  di);
1964  vlib_node_t *n =
1966  vlib_process_t *p =
1967  vec_elt (nm->processes, n->runtime_index);
1968  void *data;
1969  data =
1971  te->event_type_index,
1972  te->n_data_elts,
1973  te->n_data_elt_bytes);
1974  if (te->n_data_bytes < sizeof (te->inline_event_data))
1976  te->n_data_bytes);
1977  else
1978  {
1980  te->n_data_bytes);
1982  }
1984  }
1985  else
1986  {
1987  cpu_time_now = clib_cpu_time_now ();
1988  cpu_time_now =
1989  dispatch_suspended_process (vm, di, cpu_time_now);
1990  }
1991  }
1992  _vec_len (nm->data_from_advancing_timing_wheel) = 0;
1993  }
1994  }
1996  /* Record time stamp in case there are no enabled nodes and above
1997  calls do not update time stamp. */
1998  cpu_time_now = clib_cpu_time_now ();
2000  now = clib_time_now_internal (&vm->clib_time, cpu_time_now);
2001  /* Time to update loops_per_second? */
2002  if (PREDICT_FALSE (now >= vm->loop_interval_end))
2003  {
2004  /* Next sample ends in 20ms */
2005  if (vm->loop_interval_start)
2006  {
2007  f64 this_loops_per_second;
2008 
2009  this_loops_per_second =
2010  ((f64) vm->loops_this_reporting_interval) / (now -
2011  vm->loop_interval_start);
2012 
2013  vm->loops_per_second =
2015  (1.0 - vm->damping_constant) * this_loops_per_second;
2016  if (vm->loops_per_second != 0.0)
2017  vm->seconds_per_loop = 1.0 / vm->loops_per_second;
2018  else
2019  vm->seconds_per_loop = 0.0;
2020  }
2021  /* New interval starts now, and ends in 20ms */
2022  vm->loop_interval_start = now;
2023  vm->loop_interval_end = now + 2e-4;
2025  }
2026  }
2027 }
2028 
2029 static void
2031 {
2032  vlib_main_or_worker_loop (vm, /* is_main */ 1);
2033 }
2034 
2035 void
2037 {
2038  vlib_main_or_worker_loop (vm, /* is_main */ 0);
2039 }
2040 
2042 
2043 static clib_error_t *
2045 {
2046  int turn_on_mem_trace = 0;
2047 
2048  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2049  {
2050  if (unformat (input, "memory-trace"))
2051  turn_on_mem_trace = 1;
2052 
2053  else if (unformat (input, "elog-events %d",
2057  else if (unformat (input, "elog-post-mortem-dump"))
2058  vm->elog_post_mortem_dump = 1;
2059  else if (unformat (input, "buffer-alloc-success-rate %f",
2061  {
2062  if (VLIB_BUFFER_ALLOC_FAULT_INJECTOR == 0)
2063  return clib_error_return
2064  (0, "Buffer fault injection not configured");
2065  }
2066  else if (unformat (input, "buffer-alloc-success-seed %u",
2068  {
2069  if (VLIB_BUFFER_ALLOC_FAULT_INJECTOR == 0)
2070  return clib_error_return
2071  (0, "Buffer fault injection not configured");
2072  }
2073  else
2074  return unformat_parse_error (input);
2075  }
2076 
2077  unformat_free (input);
2078 
2079  /* Enable memory trace as early as possible. */
2080  if (turn_on_mem_trace)
2081  clib_mem_trace (1);
2082 
2083  return 0;
2084 }
2085 
2087 
2088 static void
2090 {
2091 }
2092 
2093 #define foreach_weak_reference_stub \
2094 _(vlib_map_stat_segment_init) \
2095 _(vpe_api_init) \
2096 _(vlibmemory_init) \
2097 _(map_api_segment_init)
2098 
2099 #define _(name) \
2100 clib_error_t *name (vlib_main_t *vm) __attribute__((weak)); \
2101 clib_error_t *name (vlib_main_t *vm) { return 0; }
2103 #undef _
2104 
2105 void vl_api_set_elog_main (elog_main_t * m) __attribute__ ((weak));
2106 void
2108 {
2109  clib_warning ("STUB");
2110 }
2111 
2112 int vl_api_set_elog_trace_api_messages (int enable) __attribute__ ((weak));
2113 int
2115 {
2116  clib_warning ("STUB");
2117  return 0;
2118 }
2119 
2120 int vl_api_get_elog_trace_api_messages (void) __attribute__ ((weak));
2121 int
2123 {
2124  clib_warning ("STUB");
2125  return 0;
2126 }
2127 
2128 /* Main function. */
2129 int
2131 {
2132  clib_error_t *volatile error;
2133  vlib_node_main_t *nm = &vm->node_main;
2134 
2136 
2137  /* Reconfigure event log which is enabled very early */
2138  if (vm->configured_elog_ring_size &&
2143 
2144  /* Default name. */
2145  if (!vm->name)
2146  vm->name = "VLIB";
2147 
2148  if ((error = vlib_physmem_init (vm)))
2149  {
2150  clib_error_report (error);
2151  goto done;
2152  }
2153 
2154  if ((error = vlib_map_stat_segment_init (vm)))
2155  {
2156  clib_error_report (error);
2157  goto done;
2158  }
2159 
2160  if ((error = vlib_buffer_main_init (vm)))
2161  {
2162  clib_error_report (error);
2163  goto done;
2164  }
2165 
2166  if ((error = vlib_thread_init (vm)))
2167  {
2168  clib_error_report (error);
2169  goto done;
2170  }
2171 
2172  /* Register static nodes so that init functions may use them. */
2174 
2175  /* Set seed for random number generator.
2176  Allow user to specify seed to make random sequence deterministic. */
2177  if (!unformat (input, "seed %wd", &vm->random_seed))
2178  vm->random_seed = clib_cpu_time_now ();
2180 
2181  /* Initialize node graph. */
2182  if ((error = vlib_node_main_init (vm)))
2183  {
2184  /* Arrange for graph hook up error to not be fatal when debugging. */
2185  if (CLIB_DEBUG > 0)
2186  clib_error_report (error);
2187  else
2188  goto done;
2189  }
2190 
2191  /* Direct call / weak reference, for vlib standalone use-cases */
2192  if ((error = vpe_api_init (vm)))
2193  {
2194  clib_error_report (error);
2195  goto done;
2196  }
2197 
2198  if ((error = vlibmemory_init (vm)))
2199  {
2200  clib_error_report (error);
2201  goto done;
2202  }
2203 
2204  if ((error = map_api_segment_init (vm)))
2205  {
2206  clib_error_report (error);
2207  goto done;
2208  }
2209 
2210  /* See unix/main.c; most likely already set up */
2211  if (vm->init_functions_called == 0)
2212  vm->init_functions_called = hash_create (0, /* value bytes */ 0);
2213  if ((error = vlib_call_all_init_functions (vm)))
2214  goto done;
2215 
2216  nm->timing_wheel = clib_mem_alloc_aligned (sizeof (TWT (tw_timer_wheel)),
2218 
2220  _vec_len (nm->data_from_advancing_timing_wheel) = 0;
2221 
2222  /* Create the process timing wheel */
2223  TW (tw_timer_wheel_init) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
2224  0 /* no callback */ ,
2225  10e-6 /* timer period 10us */ ,
2226  ~0 /* max expirations per call */ );
2227 
2229  _vec_len (vm->pending_rpc_requests) = 0;
2231  _vec_len (vm->processing_rpc_requests) = 0;
2232 
2233  /* Default params for the buffer allocator fault injector, if configured */
2234  if (VLIB_BUFFER_ALLOC_FAULT_INJECTOR > 0)
2235  {
2236  vm->buffer_alloc_success_seed = 0xdeaddabe;
2237  vm->buffer_alloc_success_rate = 0.80;
2238  }
2239 
2240  if ((error = vlib_call_all_config_functions (vm, input, 0 /* is_early */ )))
2241  goto done;
2242 
2243  /*
2244  * Use exponential smoothing, with a half-life of 1 second
2245  * reported_rate(t) = reported_rate(t-1) * K + rate(t)*(1-K)
2246  *
2247  * Sample every 20ms, aka 50 samples per second
2248  * K = exp (-1.0/20.0);
2249  * K = 0.95
2250  */
2251  vm->damping_constant = exp (-1.0 / 20.0);
2252 
2253  /* Sort per-thread init functions before we start threads */
2255 
2256  /* Call all main loop enter functions. */
2257  {
2258  clib_error_t *sub_error;
2259  sub_error = vlib_call_all_main_loop_enter_functions (vm);
2260  if (sub_error)
2261  clib_error_report (sub_error);
2262  }
2263 
2265  {
2267  vm->main_loop_exit_set = 1;
2268  break;
2269 
2271  goto done;
2272 
2273  default:
2274  error = vm->main_loop_error;
2275  goto done;
2276  }
2277 
2278  vlib_main_loop (vm);
2279 
2280 done:
2281  /* Call all exit functions. */
2282  {
2283  clib_error_t *sub_error;
2284  sub_error = vlib_call_all_main_loop_exit_functions (vm);
2285  if (sub_error)
2286  clib_error_report (sub_error);
2287  }
2288 
2289  if (error)
2290  clib_error_report (error);
2291 
2292  return 0;
2293 }
2294 
2295 int
2297 {
2299  pcap_main_t *pm = &vm->dispatch_pcap_main;
2300  vlib_trace_main_t *tm;
2301  vlib_trace_node_t *tn;
2302 
2303  if (a->status)
2304  {
2305  if (vm->dispatch_pcap_enable)
2306  {
2307  int i;
2309  (vm, "pcap dispatch capture enabled: %d of %d pkts...",
2311  vlib_cli_output (vm, "capture to file %s", pm->file_name);
2312 
2313  for (i = 0; i < vec_len (vm->dispatch_buffer_trace_nodes); i++)
2314  {
2315  vlib_cli_output (vm,
2316  "Buffer trace of %d pkts from %U enabled...",
2320  }
2321  }
2322  else
2323  vlib_cli_output (vm, "pcap dispatch capture disabled");
2324  return 0;
2325  }
2326 
2327  /* Consistency checks */
2328 
2329  /* Enable w/ capture already enabled not allowed */
2330  if (vm->dispatch_pcap_enable && a->enable)
2331  return -7; /* VNET_API_ERROR_INVALID_VALUE */
2332 
2333  /* Disable capture with capture already disabled, not interesting */
2334  if (vm->dispatch_pcap_enable == 0 && a->enable == 0)
2335  return -81; /* VNET_API_ERROR_VALUE_EXIST */
2336 
2337  /* Change number of packets to capture while capturing */
2338  if (vm->dispatch_pcap_enable && a->enable
2340  return -8; /* VNET_API_ERROR_INVALID_VALUE_2 */
2341 
2342  /* Independent of enable/disable, to allow buffer trace multi nodes */
2343  if (a->buffer_trace_node_index != ~0)
2344  {
2345  /* *INDENT-OFF* */
2347  {
2348  tm = &this_vlib_main->trace_main;
2349  tm->verbose = 0; /* not sure this ever did anything... */
2351  tn = tm->nodes + a->buffer_trace_node_index;
2352  tn->limit += a->buffer_traces_to_capture;
2353  if (a->post_mortem)
2354  {
2356  tm->filter_count = ~0;
2357  }
2358  tm->trace_enable = 1;
2359  }));
2360  /* *INDENT-ON* */
2362  }
2363 
2364  if (a->enable)
2365  {
2366  /* Clean up from previous run, if any */
2367  vec_free (pm->file_name);
2368  vec_free (pm->pcap_data);
2369  memset (pm, 0, sizeof (*pm));
2370 
2373  if (pm->lock == 0)
2374  clib_spinlock_init (&(pm->lock));
2375 
2376  if (a->filename == 0)
2377  a->filename = format (0, "/tmp/dispatch.pcap%c", 0);
2378 
2379  pm->file_name = (char *) a->filename;
2380  pm->n_packets_captured = 0;
2381  pm->packet_type = PCAP_PACKET_TYPE_vpp;
2384  /* *INDENT-OFF* */
2385  foreach_vlib_main (({ this_vlib_main->dispatch_pcap_enable = 1;}));
2386  /* *INDENT-ON* */
2387  }
2388  else
2389  {
2390  /* *INDENT-OFF* */
2392  {
2393  this_vlib_main->dispatch_pcap_enable = 0;
2394  this_vlib_main->dispatch_pcap_postmortem = 0;
2395  tm = &this_vlib_main->trace_main;
2396  tm->filter_flag = 0;
2397  tm->filter_count = 0;
2398  tm->trace_enable = 0;
2399  }));
2400  /* *INDENT-ON* */
2402  if (pm->n_packets_captured)
2403  {
2406  vlib_cli_output (vm, "Write %d packets to %s, and stop capture...",
2407  pm->n_packets_captured, pm->file_name);
2408  error = pcap_write (pm);
2409  if (pm->flags & PCAP_MAIN_INIT_DONE)
2410  pcap_close (pm);
2411  /* Report I/O errors... */
2412  if (error)
2413  {
2414  clib_error_report (error);
2415  return -11; /* VNET_API_ERROR_SYSCALL_ERROR_1 */
2416  }
2417  return 0;
2418  }
2419  else
2420  return -6; /* VNET_API_ERROR_NO_SUCH_ENTRY */
2421  }
2422 
2423  return 0;
2424 }
2425 
2426 static clib_error_t *
2428  unformat_input_t * input, vlib_cli_command_t * cmd)
2429 {
2430  unformat_input_t _line_input, *line_input = &_line_input;
2432  u8 *filename = 0;
2433  u32 max = 1000;
2434  int rv;
2435  int enable = 0;
2436  int status = 0;
2437  int post_mortem = 0;
2438  u32 node_index = ~0, buffer_traces_to_capture = 100;
2439 
2440  /* Get a line of input. */
2441  if (!unformat_user (input, unformat_line_input, line_input))
2442  return 0;
2443 
2444  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2445  {
2446  if (unformat (line_input, "on %=", &enable, 1))
2447  ;
2448  else if (unformat (line_input, "enable %=", &enable, 1))
2449  ;
2450  else if (unformat (line_input, "off %=", &enable, 0))
2451  ;
2452  else if (unformat (line_input, "disable %=", &enable, 0))
2453  ;
2454  else if (unformat (line_input, "max %d", &max))
2455  ;
2456  else if (unformat (line_input, "packets-to-capture %d", &max))
2457  ;
2458  else if (unformat (line_input, "file %U", unformat_vlib_tmpfile,
2459  &filename))
2460  ;
2461  else if (unformat (line_input, "status %=", &status, 1))
2462  ;
2463  else if (unformat (line_input, "buffer-trace %U %d",
2464  unformat_vlib_node, vm, &node_index,
2465  &buffer_traces_to_capture))
2466  ;
2467  else if (unformat (line_input, "post-mortem %=", &post_mortem, 1))
2468  ;
2469  else
2470  {
2471  return clib_error_return (0, "unknown input `%U'",
2472  format_unformat_error, line_input);
2473  }
2474  }
2475 
2476  unformat_free (line_input);
2477 
2478  /* no need for memset (a, 0, sizeof (*a)), set all fields here. */
2479  a->filename = filename;
2480  a->enable = enable;
2481  a->status = status;
2482  a->packets_to_capture = max;
2483  a->buffer_trace_node_index = node_index;
2484  a->buffer_traces_to_capture = buffer_traces_to_capture;
2485  a->post_mortem = post_mortem;
2486 
2488 
2489  switch (rv)
2490  {
2491  case 0:
2492  break;
2493 
2494  case -7:
2495  return clib_error_return (0, "dispatch trace already enabled...");
2496 
2497  case -81:
2498  return clib_error_return (0, "dispatch trace already disabled...");
2499 
2500  case -8:
2501  return clib_error_return
2502  (0, "can't change number of records to capture while tracing...");
2503 
2504  case -11:
2505  return clib_error_return (0, "I/O writing trace capture...");
2506 
2507  case -6:
2508  return clib_error_return (0, "No packets captured...");
2509 
2510  default:
2511  vlib_cli_output (vm, "WARNING: trace configure returned %d", rv);
2512  break;
2513  }
2514  return 0;
2515 }
2516 
2517 /*?
2518  * This command is used to start or stop pcap dispatch trace capture, or show
2519  * the capture status.
2520  *
2521  * This command has the following optional parameters:
2522  *
2523  * - <b>on|off</b> - Used to start or stop capture.
2524  *
2525  * - <b>max <nn></b> - Depth of local buffer. Once '<em>nn</em>' number
2526  * of packets have been received, buffer is flushed to file. Once another
2527  * '<em>nn</em>' number of packets have been received, buffer is flushed
2528  * to file, overwriting previous write. If not entered, value defaults
2529  * to 100. Can only be updated if packet capture is off.
2530  *
2531  * - <b>file <name></b> - Used to specify the output filename. The file will
2532  * be placed in the '<em>/tmp</em>' directory, so only the filename is
2533  * supported. Directory should not be entered. If file already exists, file
2534  * will be overwritten. If no filename is provided, '<em>/tmp/vpe.pcap</em>'
2535  * will be used. Can only be updated if packet capture is off.
2536  *
2537  * - <b>status</b> - Displays the current status and configured attributes
2538  * associated with a packet capture. If packet capture is in progress,
2539  * '<em>status</em>' also will return the number of packets currently in
2540  * the local buffer. All additional attributes entered on command line
2541  * with '<em>status</em>' will be ignored and not applied.
2542  *
2543  * @cliexpar
2544  * Example of how to display the status of capture when off:
2545  * @cliexstart{pcap dispatch trace status}
2546  * max is 100, for any interface to file /tmp/vpe.pcap
2547  * pcap dispatch capture is off...
2548  * @cliexend
2549  * Example of how to start a dispatch trace capture:
2550  * @cliexstart{pcap dispatch trace on max 35 file dispatchTrace.pcap}
2551  * pcap dispatch capture on...
2552  * @cliexend
2553  * Example of how to start a dispatch trace capture with buffer tracing
2554  * @cliexstart{pcap dispatch trace on max 10000 file dispatchTrace.pcap buffer-trace dpdk-input 1000}
2555  * pcap dispatch capture on...
2556  * @cliexend
2557  * Example of how to display the status of a tx packet capture in progress:
2558  * @cliexstart{pcap tx trace status}
2559  * max is 35, dispatch trace to file /tmp/vppTest.pcap
2560  * pcap tx capture is on: 20 of 35 pkts...
2561  * @cliexend
2562  * Example of how to stop a tx packet capture:
2563  * @cliexstart{vppctl pcap dispatch trace off}
2564  * captured 21 pkts...
2565  * saved to /tmp/dispatchTrace.pcap...
2566  * Example of how to start a post-mortem dispatch trace:
2567  * pcap dispatch trace on max 20000 buffer-trace
2568  * dpdk-input 3000000000 post-mortem
2569  * @cliexend
2570 ?*/
2571 /* *INDENT-OFF* */
2573  .path = "pcap dispatch trace",
2574  .short_help =
2575  "pcap dispatch trace [on|off] [max <nn>] [file <name>] [status]\n"
2576  " [buffer-trace <input-node-name> <nn>][post-mortem]",
2577  .function = dispatch_trace_command_fn,
2578 };
2579 /* *INDENT-ON* */
2580 
2581 vlib_main_t *
2583 {
2584  return vlib_get_main ();
2585 }
2586 
2587 elog_main_t *
2589 {
2590  return &vlib_global_main.elog_main;
2591 }
2592 
2593 /*
2594  * fd.io coding-style-patch-verification: ON
2595  *
2596  * Local Variables:
2597  * eval: (c-set-style "gnu")
2598  * End:
2599  */
_vlib_init_function_list_elt_t * worker_init_function_registrations
Definition: main.h:256
u32 * next_nodes
Definition: node.h:335
#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
clib_error_t * vlib_call_all_main_loop_exit_functions(vlib_main_t *vm)
Definition: init.c:398
__clib_export u32 *TW() tw_timer_expire_timers_vec(TWT(tw_timer_wheel) *tw, f64 now, u32 *vec)
static vlib_frame_t * vlib_frame_alloc(vlib_main_t *vm, vlib_node_runtime_t *from_node_runtime, u32 to_next_index)
Definition: main.c:169
uword * pending_rpc_requests
Definition: main.h:314
u64 internal_node_vectors
Definition: main.h:142
vlib_main_t vlib_global_main
Definition: main.c:2041
vlib_main_t * vlib_get_main_not_inline(void)
Definition: main.c:2582
f64 time
Absolute time as floating point number in seconds.
Definition: elog.h:67
u16 vector_size
Definition: node.h:321
volatile u32 * pending_remote_interrupts_notify
Definition: node.h:695
u32 max_clock
Maximum clock cycle for an invocation.
Definition: node.h:474
u32 next_frame_index
Start of next frames for this node.
Definition: node.h:485
never_inline void vlib_node_runtime_sync_stats(vlib_main_t *vm, vlib_node_runtime_t *r, uword n_calls, uword n_vectors, uword n_clocks)
Definition: main.c:569
static clib_error_t * show_frame_stats(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:266
#define hash_set(h, key, value)
Definition: hash.h:255
char * file_name
File name of pcap output.
Definition: pcap.h:162
__clib_export void elog_alloc(elog_main_t *em, u32 n_events)
Definition: elog.c:501
vlib_node_type_t
Definition: node.h:69
#define clib_min(x, y)
Definition: clib.h:328
clib_error_t * vlib_call_all_main_loop_enter_functions(vlib_main_t *vm)
Definition: init.c:391
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:121
static void vlib_next_frame_change_ownership(vlib_main_t *vm, vlib_node_runtime_t *node_runtime, u32 next_index)
Definition: main.c:296
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:82
static vlib_next_frame_t * vlib_node_get_next_frame(vlib_main_t *vm, u32 node_index, u32 next_index)
Get pointer to frame by (node_index, next_index).
Definition: node_funcs.h:352
u32 interrupt_threshold_vector_length
Definition: node.h:702
vlib_process_t ** processes
Definition: node.h:723
__clib_export clib_error_t * pcap_write(pcap_main_t *pm)
Write PCAP file.
Definition: pcap.c:89
int vl_api_get_elog_trace_api_messages(void)
Definition: main.c:2122
u32 flags
flags
Definition: pcap.h:174
static uword vlib_process_bootstrap(uword _a)
Definition: main.c:1459
format_function_t format_vlib_node_name
Definition: node_funcs.h:1222
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
vlib_node_runtime_t node_runtime
Definition: node.h:551
a
Definition: bitmap.h:544
static void placeholder_queue_signal_callback(vlib_main_t *vm)
Definition: main.c:2089
u32 n_suspends
Definition: node.h:579
#define VLIB_PENDING_FRAME_NO_NEXT_FRAME
Definition: node.h:461
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:392
vlib_frame_t * vlib_get_next_frame_internal(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next_index, u32 allocate_new_next_frame)
Definition: main.c:379
uword * processing_rpc_requests
Definition: main.h:315
static u32 clib_get_current_numa_node()
Definition: cpu.h:195
u8 * format_vnet_buffer_opaque2(u8 *s, va_list *args)
Definition: main.c:1003
#define VLIB_PCAP_MAJOR_VERSION
Definition: main.h:479
vlib_trace_node_t * nodes
Definition: trace.h:101
static void vlib_elog_main_loop_event(vlib_main_t *vm, u32 node_index, u64 time, u32 n_vectors, u32 is_return)
Definition: main.c:921
static clib_error_t * elog_save_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:700
int elog_post_mortem_dump
Definition: main.h:279
uword dispatch_pcap_enable
Definition: main.h:198
#define PREDICT_TRUE(x)
Definition: clib.h:122
uword random_seed
Definition: main.h:241
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
unsigned long u64
Definition: types.h:89
static void vlib_increment_main_loop_counter(vlib_main_t *vm)
Definition: main.h:426
f64 loop_interval_start
Definition: main.h:290
elog_time_stamp_t init_time
Timestamps.
Definition: elog.h:172
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 index
Definition: node.h:280
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:334
f64 buffer_alloc_success_rate
Definition: main.h:320
u32 current_process_index
Definition: node.h:726
void vlib_register_all_static_nodes(vlib_main_t *vm)
Definition: node.c:505
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:129
static u32 clib_get_current_cpu_id()
Definition: cpu.h:187
u32 thread_index
Definition: main.h:250
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
static_always_inline uword vlib_process_startup(vlib_main_t *vm, vlib_process_t *p, vlib_frame_t *f)
Definition: main.c:1489
u32 main_loop_exit_set
Definition: main.h:157
static u64 dispatch_pending_node(vlib_main_t *vm, uword pending_frame_index, u64 last_time_stamp)
Definition: main.c:1325
static vlib_frame_t * vlib_get_frame(vlib_main_t *vm, vlib_frame_t *f)
Definition: node_funcs.h:269
static void vlib_validate_frame_indices(vlib_frame_t *f)
Definition: main.c:191
f64 loops_per_second
Definition: main.h:291
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
static u64 clib_cpu_time_now(void)
Definition: time.h:81
u8 * format_vnet_buffer_opaque(u8 *s, va_list *args)
Definition: main.c:994
elog_track_t elog_track
Definition: threads.h:101
u32 clocks_since_last_overflow
Number of clock cycles.
Definition: node.h:472
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:630
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
static void vlib_process_update_stats(vlib_main_t *vm, vlib_process_t *p, uword n_calls, uword n_vectors, uword n_clocks)
Definition: main.c:674
static void elog_show_buffer_internal(vlib_main_t *vm, u32 n_events_to_show)
Definition: main.c:858
#define VLIB_MAIN_LOOP_EXIT_CLI
Definition: main.h:164
void vlib_post_mortem_dump(void)
Definition: main.c:737
void clib_longjmp(clib_longjmp_t *save, uword return_value)
vlib_main_t * vm
Definition: in2out_ed.c:1580
static vlib_frame_size_t * get_frame_size_info(vlib_node_main_t *nm, u32 n_scalar_bytes, u32 n_vector_bytes)
Definition: main.c:90
static clib_error_t * elog_show_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:886
clib_time_t clib_time
Definition: main.h:123
u32 numa_node
Definition: main.h:252
u32 configured_elog_ring_size
Definition: main.h:225
u8 * format_vnet_buffer_flags(u8 *s, va_list *args)
Definition: main.c:986
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:520
clib_spinlock_t pending_interrupt_lock
Definition: node.h:696
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:402
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:251
uword clib_setjmp(clib_longjmp_t *save, uword return_value_not_taken)
#define vec_alloc(V, N)
Allocate space for N more elements (no header, unspecified alignment)
Definition: vec.h:319
unsigned char u8
Definition: types.h:56
clib_error_t * vlib_sort_init_exit_functions(_vlib_init_function_list_elt_t **head)
Topological sorter for init function chains.
Definition: init.c:76
static uword vlib_process_stack_is_valid(vlib_process_t *p)
Definition: main.c:1445
u8 data[128]
Definition: ipsec_types.api:90
u8 buffer_pool_index
index of buffer pool this buffer belongs.
Definition: buffer.h:133
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
u16 scalar_size
Definition: node.h:321
u8 state
Definition: node.h:309
u16 thread_index
thread this node runs on
Definition: node.h:517
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:205
u64 internal_node_calls
Definition: main.h:143
volatile uword check_frame_queues
Definition: main.h:311
static void vlib_worker_thread_barrier_check(void)
Definition: threads.h:401
static clib_error_t * dispatch_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:2427
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:490
static void vlib_main_loop(vlib_main_t *vm)
Definition: main.c:2030
#define foreach_weak_reference_stub
Definition: main.c:2093
vlib_trace_header_t ** trace_buffer_pool
Definition: trace.h:86
#define static_always_inline
Definition: clib.h:109
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
#define VLIB_FRAME_NO_APPEND
Definition: node.h:419
vlib_node_function_t * function
Node function to call.
Definition: node.h:468
#define VLIB_FRAME_MAGIC
void vl_api_set_elog_main(elog_main_t *m)
Definition: main.c:2107
u32 main_loop_vectors_processed
Definition: main.h:138
#define VLIB_INVALID_NODE_INDEX
Definition: node.h:375
u16 log2_n_stack_bytes
Definition: node.h:574
vlib_node_t ** nodes
Definition: node.h:680
description fragment has unexpected format
Definition: map.api:433
u32 vectors_since_last_overflow
Number of vector elements processed by this node.
Definition: node.h:482
vlib_frame_t * frame
Definition: main.c:1454
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
#define clib_error_return(e, args...)
Definition: error.h:99
static void dispatch_pcap_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: main.c:1034
#define VLIB_FRAME_ALIGN
Definition: node.h:379
u32 cpu_id
Definition: main.h:251
static void vlib_process_sync_stats(vlib_main_t *vm, vlib_process_t *p, uword n_calls, uword n_vectors, uword n_clocks)
Definition: main.c:587
static uword vlib_timing_wheel_data_is_timed_event(u32 d)
Definition: node.h:648
#define VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE
Definition: node.h:304
const cJSON *const b
Definition: cJSON.h:255
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
Definition: node.h:565
vlib_node_interrupt_t * pending_remote_interrupts
Definition: node.h:694
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:281
static_always_inline void vlib_process_start_switch_stack(vlib_main_t *vm, vlib_process_t *p)
Definition: node_funcs.h:56
unsigned int u32
Definition: types.h:88
static_always_inline uword vlib_process_resume(vlib_main_t *vm, vlib_process_t *p)
Definition: main.c:1512
u64 cpu_time_main_loop_start
Definition: main.h:132
vlib_node_runtime_t * nodes_by_type[VLIB_N_NODE_TYPE]
Definition: node.h:690
__clib_export void clib_random_buffer_init(clib_random_buffer_t *b, uword seed)
Definition: random_buffer.c:62
static u32 vlib_frame_bytes(u32 n_scalar_bytes, u32 n_vector_bytes)
Definition: main.c:53
#define VLIB_MAIN_LOOP_EXIT_NONE
Definition: main.h:161
#define VLIB_FRAME_SIZE
Definition: node.h:378
static vlib_next_frame_t * vlib_node_runtime_get_next_frame(vlib_main_t *vm, vlib_node_runtime_t *n, u32 next_index)
Definition: node_funcs.h:317
u8 * pcap_buffer
Definition: main.h:201
#define VLIB_PROCESS_IS_RUNNING
Definition: node.h:571
#define VLIB_PROCESS_RETURN_LONGJMP_RETURN
Definition: node.h:556
u8 * vnet_trace_placeholder
Definition: trace.c:44
f64 seconds_per_loop
Definition: main.h:292
u64 max_clock_n
Definition: node.h:238
unformat_function_t unformat_line_input
Definition: format.h:282
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:65
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
u32 calls_since_last_overflow
Number of calls.
Definition: node.h:480
char * name
Definition: main.h:170
Definition: cJSON.c:84
__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:34
#define hash_get(h, key)
Definition: hash.h:249
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
static clib_error_t * elog_write_file(elog_main_t *em, char *clib_file, int flush_ring)
Definition: elog.h:533
u32 next_frame_index
Definition: node.h:458
static void * vlib_process_signal_event_helper(vlib_node_main_t *nm, vlib_node_t *n, vlib_process_t *p, uword t, uword n_data_elts, uword n_data_elt_bytes)
Definition: node_funcs.h:824
vlib_node_stats_t stats_total
Definition: node.h:270
static void vlib_put_next_frame_validate(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 next_index, u32 n_vectors_left)
Definition: main.c:444
u16 state
Input node state.
Definition: node.h:503
static u8 * format_buffer_metadata(u8 *s, va_list *args)
Definition: main.c:1010
format_function_t format_vlib_trace
Definition: trace.h:114
vlib_signal_timed_event_data_t * signal_timed_event_data_pool
Definition: node.h:713
u16 frame_flags
Definition: node.h:385
#define VLIB_FRAME_IS_ALLOCATED
Definition: node.h:426
#define VLIB_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:415
u8 * pcap_data
Vector of pcap data.
Definition: pcap.h:184
struct _unformat_input_t unformat_input_t
static_always_inline u64 dispatch_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_node_type_t type, vlib_node_state_t dispatch_state, vlib_frame_t *frame, u64 last_time_stamp)
Definition: main.c:1142
u32 n_alloc_frames
Definition: node.h:535
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:216
vec_header_t h
Definition: buffer.c:322
static uword vlib_timing_wheel_data_get_index(u32 d)
Definition: node.h:666
#define vec_alloc_aligned(V, N, A)
Allocate space for N more elements (no header, given alignment)
Definition: vec.h:328
void di(unformat_input_t *i)
Definition: unformat.c:163
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
__clib_export void TW() tw_timer_wheel_init(TWT(tw_timer_wheel) *tw, void *expired_timer_callback, f64 timer_interval_in_seconds, u32 max_expirations)
Initialize a tw timer wheel template instance.
elog_event_type_t * node_return_elog_event_types
Definition: main.h:236
#define TWT(a)
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
Definition: main.c:238
u32 polling_threshold_vector_length
Definition: node.h:701
uword dispatch_pcap_postmortem
Definition: main.h:199
#define ELOG_DATA(em, f)
Definition: elog.h:484
u64 * n_vectors_by_next_node
Definition: node.h:344
u32 trace_handle
Specifies trace buffer handle if VLIB_PACKET_IS_TRACED flag is set.
Definition: buffer.h:163
#define PREDICT_FALSE(x)
Definition: clib.h:121
#define always_inline
Definition: ipsec.h:28
f64 seconds_per_clock
Definition: time.h:58
u8 protocol_hint
Definition: node.h:315
vlib_frame_t * frame
Definition: node.h:455
u32 node_index
Node index.
Definition: node.h:488
#define foreach_vlib_main(body)
Definition: threads.h:242
uword * init_functions_called
Definition: main.h:247
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
#define VLIB_PROCESS_STACK_MAGIC
Definition: node.h:612
#define VLIB_PROCESS_RESUME_LONGJMP_RESUME
Definition: node.h:562
uword * frame_size_hash
Definition: node.h:738
clib_error_t * vlibmemory_init(vlib_main_t *vm)
Definition: memory_api.c:931
volatile u32 queue_signal_pending
Definition: main.h:263
static vlib_frame_t * vlib_frame_alloc_to_node(vlib_main_t *vm, u32 to_node_index, u32 frame_flags)
Definition: main.c:116
clib_error_t * map_api_segment_init(vlib_main_t *vm)
Definition: memory_api.c:474
f64 damping_constant
Definition: main.h:293
u8 * name
Definition: node.h:264
static u64 dispatch_process(vlib_main_t *vm, vlib_process_t *p, vlib_frame_t *f, u64 last_time_stamp)
Definition: main.c:1530
u32 filter_count
Definition: trace.h:95
static_always_inline void os_set_numa_index(uword numa_index)
Definition: os.h:81
u32 owner_node_index
Definition: node.h:355
#define VLIB_EARLY_CONFIG_FUNCTION(x, n,...)
Definition: init.h:226
static u32 vlib_node_runtime_update_main_loop_vector_stats(vlib_main_t *vm, vlib_node_runtime_t *node, uword n_vectors)
Definition: node_funcs.h:1110
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u8 inline_event_data[64 - 3 *sizeof(u32) - 2 *sizeof(u16)]
Definition: node.h:639
svmdb_client_t * c
u16 n_vectors
Definition: node.h:397
u32 runtime_index
Definition: node.h:283
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
int elog_trace_graph_dispatch
Definition: main.h:230
static uword elog_n_events_in_buffer(elog_main_t *em)
Return number of events in the event-log buffer.
Definition: elog.h:191
static_always_inline void vlib_main_or_worker_loop(vlib_main_t *vm, int is_main)
Definition: main.c:1738
u32 node_runtime_index
Definition: node.h:452
vlib_pending_frame_t * pending_frames
Definition: node.h:708
u32 flow_id
Generic flow identifier.
Definition: buffer.h:127
int vlib_frame_queue_dequeue(vlib_main_t *vm, vlib_frame_queue_main_t *fqm)
Definition: threads.c:1710
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
clib_error_t * vpe_api_init(vlib_main_t *vm)
Definition: api.c:655
#define VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:293
static u32 vlib_node_runtime_update_stats(vlib_main_t *vm, vlib_node_runtime_t *node, uword n_calls, uword n_vectors, uword n_clocks)
Definition: main.c:636
#define clib_warning(format, args...)
Definition: error.h:59
#define VLIB_PROCESS_RESUME_PENDING
Definition: node.h:568
#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:115
u8 data[]
Packet data.
Definition: buffer.h:181
#define VLIB_BUFFER_TRACE_TRAJECTORY
Compile time buffer trajectory tracing option Turn this on if you run into "bad monkey" contexts...
Definition: buffer.h:488
elog_main_t elog_main
Definition: main.h:224
void(**volatile worker_thread_main_loop_callbacks)(struct vlib_main_t *, u64 t)
Definition: main.h:270
clib_error_t * vlib_buffer_main_init(struct vlib_main_t *vm)
Definition: buffer.c:852
#define VLIB_FRAME_PENDING
Definition: node.h:429
__clib_export void elog_resize(elog_main_t *em, u32 n_events)
Definition: elog.c:507
static u32 vlib_frame_vector_byte_offset(u32 scalar_size)
Definition: node_funcs.h:286
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:147
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:442
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:265
u32 n_total_events_disable_limit
When count reaches limit logging is disabled.
Definition: elog.h:139
vlib_frame_t ** free_frames
Definition: node.h:538
static void pcap_postmortem_reset(vlib_main_t *vm)
Definition: main.c:1725
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
u8 exp
Definition: fib_types.api:27
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
#define VLIB_PCAP_MINOR_VERSION
Definition: main.h:480
u32 node_runtime_index
Definition: node.h:673
vlib_node_interrupt_t * pending_local_interrupts
Definition: node.h:693
#define never_inline
Definition: clib.h:105
signed int i32
Definition: types.h:77
#define hash_create(elts, value_bytes)
Definition: hash.h:696
#define uword_to_pointer(u, type)
Definition: types.h:136
static clib_error_t * elog_resize_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:826
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:511
static void vlib_node_runtime_perf_counter(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, uword n, u64 t, vlib_node_runtime_perf_call_type_t call_type)
Definition: main.h:442
clib_error_t * vlib_node_main_init(vlib_main_t *vm)
Definition: node.c:596
#define PCAP_MAIN_INIT_DONE
Definition: pcap.h:175
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:330
#define ASSERT(truth)
u64 last_cpu_time
Definition: time.h:51
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
static void elog_reset_buffer(elog_main_t *em)
Reset the event buffer.
Definition: elog.h:210
vlib_frame_queue_main_t * frame_queue_mains
Definition: threads.h:333
#define ELOG_TRACK_DATA(em, f, track)
Definition: elog.h:478
vlib_frame_t * frame
Definition: node.h:406
__clib_export u32 TW() tw_timer_start(TWT(tw_timer_wheel) *tw, u32 user_id, u32 timer_id, u64 interval)
Start a Tw Timer.
uword event_ring_size
Power of 2 number of elements in ring.
Definition: elog.h:145
u16 flags
Definition: node.h:388
u32 main_loop_nodes_processed
Definition: main.h:139
u64 cpu
CPU cycle counter.
Definition: elog.h:126
u64 loops_this_reporting_interval
Definition: main.h:288
void vlib_worker_thread_initial_barrier_sync_and_release(vlib_main_t *vm)
Definition: threads.c:1430
static_always_inline void vlib_process_finish_switch_stack(vlib_main_t *vm)
Definition: node_funcs.h:66
#define clib_error_report(e)
Definition: error.h:113
u32 elog_trace_graph_circuit_node_index
Definition: main.h:232
vlib_trace_main_t trace_main
Definition: main.h:194
int vl_api_set_elog_trace_api_messages(int enable)
Definition: main.c:2114
static uword pointer_to_uword(const void *p)
Definition: types.h:131
#define A(x)
Definition: main.c:1031
void(* queue_signal_callback)(struct vlib_main_t *)
Definition: main.h:265
void vlib_gdb_show_event_log(void)
Definition: main.c:915
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#define VLIB_FRAME_OWNER
Definition: node.h:423
void vlib_node_sync_stats(vlib_main_t *vm, vlib_node_t *n)
Definition: main.c:599
#define vec_elt(v, i)
Get vector value at index i.
int vlib_main(vlib_main_t *volatile vm, unformat_input_t *input)
Definition: main.c:2130
#define unformat_parse_error(input)
Definition: format.h:268
typedef key
Definition: ipsec_types.api:86
pcap_packet_type_t packet_type
Packet type.
Definition: pcap.h:168
void vlib_worker_loop(vlib_main_t *vm)
Definition: main.c:2036
static vlib_node_t * vlib_get_next_node(vlib_main_t *vm, u32 node_index, u32 next_index)
Get vlib node by graph arc (next) index.
Definition: node_funcs.h:98
void vl_api_send_pending_rpc_requests(vlib_main_t *)
Definition: main.c:1699
elog_main_t * vlib_get_elog_main_not_inline()
Definition: main.c:2588
#define clib_mem_alloc_aligned_no_fail(size, align)
Definition: mem.h:287
u32 buffer_alloc_success_seed
Definition: main.h:319
u32 * data_from_advancing_timing_wheel
Definition: node.h:716
clib_error_t * vlib_physmem_init(vlib_main_t *vm)
Definition: physmem.c:94
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 input_node_counts_by_state[VLIB_N_NODE_STATE]
Definition: node.h:735
vlib_pending_frame_t * suspended_process_frames
Definition: node.h:729
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:140
vlib_node_main_t node_main
Definition: main.h:188
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1581
static u32 * vlib_frame_find_magic(vlib_frame_t *f, vlib_node_t *node)
Definition: main.c:78
static uword max_log2(uword x)
Definition: clib.h:209
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
u32 owner_next_index
Definition: node.h:355
u8 vector_size
Definition: node.h:394
vlib_next_frame_t * next_frames
Definition: node.h:705
static clib_error_t * elog_stop(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:786
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
clib_error_t * vlib_call_all_config_functions(vlib_main_t *vm, unformat_input_t *input, int is_early)
Definition: init.c:405
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
static uword elog_is_enabled(elog_main_t *em)
event logging enabled predicate
Definition: elog.h:276
static f64 clib_time_now_internal(clib_time_t *c, u64 n)
Definition: time.h:210
u32 index
Definition: flow_types.api:221
#define VLIB_FRAME_TRACE
Definition: node.h:435
u32 interrupt_data
Data passed together with interrupt.
Definition: node.h:505
u32 stop_timer_handle
Definition: node.h:604
clib_error_t * vlib_call_all_init_functions(vlib_main_t *vm)
Definition: init.c:378
#define VLIB_FRAME_SIZE_EXTRA
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:1228
static void elog_track(elog_main_t *em, elog_event_type_t *type, elog_track_t *track, u32 data)
Log a single-datum event to a specific track, non-inline version.
Definition: elog.h:398
static u64 dispatch_suspended_process(vlib_main_t *vm, uword process_index, u64 last_time_stamp)
Definition: main.c:1617
vlib_frame_size_t * frame_sizes
Definition: node.h:741
u64 resume_clock_interval
Definition: node.h:601
static void add_trajectory_trace(vlib_buffer_t *b, u32 node_index)
Definition: main.c:974
u16 flags
Definition: node.h:564
elog_event_type_t * node_call_elog_event_types
Definition: main.h:235
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:261
vlib_node_type_t type
Definition: node.h:277
static vlib_process_t * vlib_get_process_from_node(vlib_main_t *vm, vlib_node_t *node)
Definition: node_funcs.h:261
__clib_export elog_event_t * elog_peek_events(elog_main_t *em)
convert event ring events to events, and return them as a vector.
Definition: elog.c:557
uword clib_calljmp(uword(*func)(uword func_arg), uword func_arg, void *stack)
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u32 name_elog_string
Definition: node.h:267
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1561
#define clib_call_callbacks(h,...)
call the specified callback set
Definition: callback.h:67
vlib_node_state_t
Definition: node.h:250
u64 init_cpu_time
Definition: time.h:61
pcap_main_t dispatch_pcap_main
Definition: main.h:197
u32 * stack
Definition: node.h:613
u32 suspended_process_frame_index
Definition: node.h:576
static void validate_frame_magic(vlib_main_t *vm, vlib_frame_t *f, vlib_node_t *n, uword next_index)
Definition: main.c:370
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
f64 loop_interval_end
Definition: main.h:289
static clib_error_t * vlib_main_configure(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:2044
static vlib_cli_command_t pcap_dispatch_trace_command
(constructor) VLIB_CLI_COMMAND (pcap_dispatch_trace_command)
Definition: main.c:2572
u32 internal_node_last_vectors_per_main_loop
Definition: main.h:148
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:85
static clib_error_t * vlib_cli_elog_clear(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:683
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT
Definition: node.h:566
#define vec_foreach(var, vec)
Vector iterator.
elog_track_t default_track
Default track.
Definition: elog.h:166
clib_longjmp_t return_longjmp
Definition: node.h:554
u16 flags
Copy of main node flags.
Definition: node.h:501
u32 node_runtime_index
Definition: node.h:409
u32 n_total_events
Total number of events in buffer.
Definition: elog.h:135
static_always_inline u64 dispatch_pending_interrupts(vlib_main_t *vm, vlib_node_main_t *nm, u64 cpu_time_now, vlib_node_interrupt_t *interrupts)
Definition: main.c:1704
u8 scalar_size
Definition: node.h:391
clib_longjmp_t main_loop_exit
Definition: main.h:160
clib_longjmp_t resume_longjmp
Definition: node.h:560
void clib_mem_trace(int enable)
Definition: mem_dlmalloc.c:500
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:280
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
#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:167
#define TW(a)
clib_error_t * vlib_map_stat_segment_init(void)
Definition: stat_segment.c:314
static u32 vlib_timing_wheel_data_set_suspended_process(u32 i)
Definition: node.h:654
void vlib_start_process(vlib_main_t *vm, uword process_index)
Definition: main.c:1609
int vlib_pcap_dispatch_trace_configure(vlib_pcap_dispatch_trace_args_t *a)
Definition: main.c:2296
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:106
void * timing_wheel
Definition: node.h:711
volatile u8 ref_count
Reference count for this buffer.
Definition: buffer.h:130
int elog_trace_graph_circuit
Definition: main.h:231
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:85
clib_random_buffer_t random_buffer
Definition: main.h:244
static clib_error_t * elog_restart(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:806
#define VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE
Definition: node.h:305
u8 *(* validate_frame)(struct vlib_main_t *vm, struct vlib_node_runtime_t *, struct vlib_frame_t *f)
Definition: node.h:365
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
u32 * dispatch_buffer_trace_nodes
Definition: main.h:200
clib_error_t * main_loop_error
Definition: main.h:167
__clib_export u8 * format_elog_event(u8 *s, va_list *va)
Definition: elog.c:296
vlib_process_t * process
Definition: main.c:1453
static uword elog_buffer_capacity(elog_main_t *em)
Return number of events which can fit in the event buffer.
Definition: elog.h:201
u64 cpu_time_last_node_dispatch
Definition: main.h:129
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
#define VLIB_FRAME_FREE_AFTER_DISPATCH
Definition: node.h:432
clib_error_t * vlib_thread_init(vlib_main_t *vm)
Definition: threads.c:207
u32 vectors_since_last_overflow
Definition: node.h:438
u32 max_clock_n
Number of vectors in the recorded max_clock.
Definition: node.h:477
#define VLIB_PROCESS_RETURN_LONGJMP_SUSPEND
Definition: node.h:557