FD.io VPP  v19.01.3-6-g70449b9b9
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 #include <vlib/unix/cj.h>
48 
50 
51 /* Actually allocate a few extra slots of vector data to support
52  speculative vector enqueues which overflow vector data in next frame. */
53 #define VLIB_FRAME_SIZE_ALLOC (VLIB_FRAME_SIZE + 4)
54 
56 
58 vlib_frame_bytes (u32 n_scalar_bytes, u32 n_vector_bytes)
59 {
60  u32 n_bytes;
61 
62  /* Make room for vlib_frame_t plus scalar arguments. */
63  n_bytes = vlib_frame_vector_byte_offset (n_scalar_bytes);
64 
65  /* Make room for vector arguments.
66  Allocate a few extra slots of vector data to support
67  speculative vector enqueues which overflow vector data in next frame. */
68 #define VLIB_FRAME_SIZE_EXTRA 4
69  n_bytes += (VLIB_FRAME_SIZE + VLIB_FRAME_SIZE_EXTRA) * n_vector_bytes;
70 
71  /* Magic number is first 32bit number after vector data.
72  Used to make sure that vector data is never overrun. */
73 #define VLIB_FRAME_MAGIC (0xabadc0ed)
74  n_bytes += sizeof (u32);
75 
76  /* Pad to cache line. */
77  n_bytes = round_pow2 (n_bytes, CLIB_CACHE_LINE_BYTES);
78 
79  return n_bytes;
80 }
81 
84 {
85  void *p = f;
86 
88 
90 
91  return p;
92 }
93 
94 static vlib_frame_size_t *
96  u32 n_scalar_bytes, u32 n_vector_bytes)
97 {
98  uword key = (n_scalar_bytes << 16) | n_vector_bytes;
99  uword *p, i;
100 
101  p = hash_get (nm->frame_size_hash, key);
102  if (p)
103  i = p[0];
104  else
105  {
106  i = vec_len (nm->frame_sizes);
107  vec_validate (nm->frame_sizes, i);
108  hash_set (nm->frame_size_hash, key, i);
109  }
110 
111  return vec_elt_at_index (nm->frame_sizes, i);
112 }
113 
114 static vlib_frame_t *
116  u32 frame_flags)
117 {
118  vlib_node_main_t *nm = &vm->node_main;
119  vlib_frame_size_t *fs;
120  vlib_node_t *to_node;
121  vlib_frame_t *f;
122  u32 l, n, scalar_size, vector_size;
123 
124  to_node = vlib_get_node (vm, to_node_index);
125 
126  scalar_size = to_node->scalar_size;
127  vector_size = to_node->vector_size;
128 
129  fs = get_frame_size_info (nm, scalar_size, vector_size);
130  n = vlib_frame_bytes (scalar_size, vector_size);
131  if ((l = vec_len (fs->free_frames)) > 0)
132  {
133  /* Allocate from end of free list. */
134  f = fs->free_frames[l - 1];
135  _vec_len (fs->free_frames) = l - 1;
136  }
137  else
138  {
140  }
141 
142  /* Poison frame when debugging. */
143  if (CLIB_DEBUG > 0)
144  clib_memset (f, 0xfe, n);
145 
146  /* Insert magic number. */
147  {
148  u32 *magic;
149 
150  magic = vlib_frame_find_magic (f, to_node);
151  *magic = VLIB_FRAME_MAGIC;
152  }
153 
154  f->frame_flags = VLIB_FRAME_IS_ALLOCATED | frame_flags;
155  f->n_vectors = 0;
156  f->scalar_size = scalar_size;
157  f->vector_size = vector_size;
158  f->flags = 0;
159 
160  fs->n_alloc_frames += 1;
161 
162  return f;
163 }
164 
165 /* Allocate a frame for from FROM_NODE to TO_NODE via TO_NEXT_INDEX.
166  Returns frame index. */
167 static vlib_frame_t *
169  u32 to_next_index)
170 {
171  vlib_node_t *from_node;
172 
173  from_node = vlib_get_node (vm, from_node_runtime->node_index);
174  ASSERT (to_next_index < vec_len (from_node->next_nodes));
175 
176  return vlib_frame_alloc_to_node (vm, from_node->next_nodes[to_next_index],
177  /* frame_flags */ 0);
178 }
179 
180 vlib_frame_t *
182 {
183  vlib_frame_t *f = vlib_frame_alloc_to_node (vm, to_node_index,
184  /* frame_flags */
186  return vlib_get_frame (vm, f);
187 }
188 
189 void
191 {
193  vlib_node_t *to_node;
194 
195  if (f->n_vectors == 0)
196  return;
197 
198  to_node = vlib_get_node (vm, to_node_index);
199 
200  vec_add2 (vm->node_main.pending_frames, p, 1);
201 
203  p->frame = vlib_get_frame (vm, f);
204  p->node_runtime_index = to_node->runtime_index;
206 }
207 
208 /* Free given frame. */
209 void
211 {
212  vlib_node_main_t *nm = &vm->node_main;
213  vlib_node_t *node;
214  vlib_frame_size_t *fs;
215 
217 
218  node = vlib_get_node (vm, r->node_index);
219  fs = get_frame_size_info (nm, node->scalar_size, node->vector_size);
220 
222 
223  /* No next frames may point to freed frame. */
224  if (CLIB_DEBUG > 0)
225  {
226  vlib_next_frame_t *nf;
227  vec_foreach (nf, vm->node_main.next_frames) ASSERT (nf->frame != f);
228  }
229 
231 
232  vec_add1 (fs->free_frames, f);
233  ASSERT (fs->n_alloc_frames > 0);
234  fs->n_alloc_frames -= 1;
235 }
236 
237 static clib_error_t *
239  unformat_input_t * input, vlib_cli_command_t * cmd)
240 {
241  vlib_node_main_t *nm = &vm->node_main;
242  vlib_frame_size_t *fs;
243 
244  vlib_cli_output (vm, "%=6s%=12s%=12s", "Size", "# Alloc", "# Free");
245  vec_foreach (fs, nm->frame_sizes)
246  {
247  u32 n_alloc = fs->n_alloc_frames;
248  u32 n_free = vec_len (fs->free_frames);
249 
250  if (n_alloc + n_free > 0)
251  vlib_cli_output (vm, "%=6d%=12d%=12d",
252  fs - nm->frame_sizes, n_alloc, n_free);
253  }
254 
255  return 0;
256 }
257 
258 /* *INDENT-OFF* */
259 VLIB_CLI_COMMAND (show_frame_stats_cli, static) = {
260  .path = "show vlib frame-allocation",
261  .short_help = "Show node dispatch frame statistics",
262  .function = show_frame_stats,
263 };
264 /* *INDENT-ON* */
265 
266 /* Change ownership of enqueue rights to given next node. */
267 static void
269  vlib_node_runtime_t * node_runtime,
270  u32 next_index)
271 {
272  vlib_node_main_t *nm = &vm->node_main;
273  vlib_next_frame_t *next_frame;
274  vlib_node_t *node, *next_node;
275 
276  node = vec_elt (nm->nodes, node_runtime->node_index);
277 
278  /* Only internal & input nodes are allowed to call other nodes. */
280  || node->type == VLIB_NODE_TYPE_INPUT
281  || node->type == VLIB_NODE_TYPE_PROCESS);
282 
283  ASSERT (vec_len (node->next_nodes) == node_runtime->n_next_nodes);
284 
285  next_frame =
286  vlib_node_runtime_get_next_frame (vm, node_runtime, next_index);
287  next_node = vec_elt (nm->nodes, node->next_nodes[next_index]);
288 
289  if (next_node->owner_node_index != VLIB_INVALID_NODE_INDEX)
290  {
291  /* Get frame from previous owner. */
292  vlib_next_frame_t *owner_next_frame;
293  vlib_next_frame_t tmp;
294 
295  owner_next_frame =
297  next_node->owner_node_index,
298  next_node->owner_next_index);
299 
300  /* Swap target next frame with owner's. */
301  tmp = owner_next_frame[0];
302  owner_next_frame[0] = next_frame[0];
303  next_frame[0] = tmp;
304 
305  /*
306  * If next_frame is already pending, we have to track down
307  * all pending frames and fix their next_frame_index fields.
308  */
309  if (next_frame->flags & VLIB_FRAME_PENDING)
310  {
312  if (next_frame->frame != NULL)
313  {
314  vec_foreach (p, nm->pending_frames)
315  {
316  if (p->frame == next_frame->frame)
317  {
318  p->next_frame_index =
319  next_frame - vm->node_main.next_frames;
320  }
321  }
322  }
323  }
324  }
325  else
326  {
327  /* No previous owner. Take ownership. */
328  next_frame->flags |= VLIB_FRAME_OWNER;
329  }
330 
331  /* Record new owner. */
332  next_node->owner_node_index = node->index;
333  next_node->owner_next_index = next_index;
334 
335  /* Now we should be owner. */
336  ASSERT (next_frame->flags & VLIB_FRAME_OWNER);
337 }
338 
339 /* Make sure that magic number is still there.
340  Otherwise, it is likely that caller has overrun frame arguments. */
341 always_inline void
343  vlib_frame_t * f, vlib_node_t * n, uword next_index)
344 {
345  vlib_node_t *next_node = vlib_get_node (vm, n->next_nodes[next_index]);
346  u32 *magic = vlib_frame_find_magic (f, next_node);
347  ASSERT (VLIB_FRAME_MAGIC == magic[0]);
348 }
349 
350 vlib_frame_t *
352  vlib_node_runtime_t * node,
353  u32 next_index, u32 allocate_new_next_frame)
354 {
355  vlib_frame_t *f;
356  vlib_next_frame_t *nf;
357  u32 n_used;
358 
359  nf = vlib_node_runtime_get_next_frame (vm, node, next_index);
360 
361  /* Make sure this next frame owns right to enqueue to destination frame. */
362  if (PREDICT_FALSE (!(nf->flags & VLIB_FRAME_OWNER)))
363  vlib_next_frame_change_ownership (vm, node, next_index);
364 
365  /* ??? Don't need valid flag: can use frame_index == ~0 */
367  {
368  nf->frame = vlib_frame_alloc (vm, node, next_index);
370  }
371 
372  f = nf->frame;
373 
374  /* Has frame been removed from pending vector (e.g. finished dispatching)?
375  If so we can reuse frame. */
376  if ((nf->flags & VLIB_FRAME_PENDING)
377  && !(f->frame_flags & VLIB_FRAME_PENDING))
378  {
379  nf->flags &= ~VLIB_FRAME_PENDING;
380  f->n_vectors = 0;
381  f->flags = 0;
382  }
383 
384  /* Allocate new frame if current one is marked as no-append or
385  it is already full. */
386  n_used = f->n_vectors;
387  if (n_used >= VLIB_FRAME_SIZE || (allocate_new_next_frame && n_used > 0) ||
389  {
390  /* Old frame may need to be freed after dispatch, since we'll have
391  two redundant frames from node -> next node. */
393  {
394  vlib_frame_t *f_old = vlib_get_frame (vm, nf->frame);
396  }
397 
398  /* Allocate new frame to replace full one. */
399  f = nf->frame = vlib_frame_alloc (vm, node, next_index);
400  n_used = f->n_vectors;
401  }
402 
403  /* Should have free vectors in frame now. */
404  ASSERT (n_used < VLIB_FRAME_SIZE);
405 
406  if (CLIB_DEBUG > 0)
407  {
408  validate_frame_magic (vm, f,
409  vlib_get_node (vm, node->node_index), next_index);
410  }
411 
412  return f;
413 }
414 
415 static void
417  vlib_node_runtime_t * rt,
418  u32 next_index, u32 n_vectors_left)
419 {
420  vlib_node_main_t *nm = &vm->node_main;
421  vlib_next_frame_t *nf;
422  vlib_frame_t *f;
423  vlib_node_runtime_t *next_rt;
424  vlib_node_t *next_node;
425  u32 n_before, n_after;
426 
427  nf = vlib_node_runtime_get_next_frame (vm, rt, next_index);
428  f = vlib_get_frame (vm, nf->frame);
429 
430  ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
431  n_after = VLIB_FRAME_SIZE - n_vectors_left;
432  n_before = f->n_vectors;
433 
434  ASSERT (n_after >= n_before);
435 
437  nf->node_runtime_index);
438  next_node = vlib_get_node (vm, next_rt->node_index);
439  if (n_after > 0 && next_node->validate_frame)
440  {
441  u8 *msg = next_node->validate_frame (vm, rt, f);
442  if (msg)
443  {
444  clib_warning ("%v", msg);
445  ASSERT (0);
446  }
447  vec_free (msg);
448  }
449 }
450 
451 void
454  u32 next_index, u32 n_vectors_left)
455 {
456  vlib_node_main_t *nm = &vm->node_main;
457  vlib_next_frame_t *nf;
458  vlib_frame_t *f;
459  u32 n_vectors_in_frame;
460 
461  if (buffer_main.callbacks_registered == 0 && CLIB_DEBUG > 0)
462  vlib_put_next_frame_validate (vm, r, next_index, n_vectors_left);
463 
464  nf = vlib_node_runtime_get_next_frame (vm, r, next_index);
465  f = vlib_get_frame (vm, nf->frame);
466 
467  /* Make sure that magic number is still there. Otherwise, caller
468  has overrun frame meta data. */
469  if (CLIB_DEBUG > 0)
470  {
471  vlib_node_t *node = vlib_get_node (vm, r->node_index);
472  validate_frame_magic (vm, f, node, next_index);
473  }
474 
475  /* Convert # of vectors left -> number of vectors there. */
476  ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
477  n_vectors_in_frame = VLIB_FRAME_SIZE - n_vectors_left;
478 
479  f->n_vectors = n_vectors_in_frame;
480 
481  /* If vectors were added to frame, add to pending vector. */
482  if (PREDICT_TRUE (n_vectors_in_frame > 0))
483  {
485  u32 v0, v1;
486 
487  r->cached_next_index = next_index;
488 
489  if (!(f->frame_flags & VLIB_FRAME_PENDING))
490  {
491  __attribute__ ((unused)) vlib_node_t *node;
492  vlib_node_t *next_node;
493  vlib_node_runtime_t *next_runtime;
494 
495  node = vlib_get_node (vm, r->node_index);
496  next_node = vlib_get_next_node (vm, r->node_index, next_index);
497  next_runtime = vlib_node_get_runtime (vm, next_node->index);
498 
499  vec_add2 (nm->pending_frames, p, 1);
500 
501  p->frame = nf->frame;
503  p->next_frame_index = nf - nm->next_frames;
504  nf->flags |= VLIB_FRAME_PENDING;
506 
507  /*
508  * If we're going to dispatch this frame on another thread,
509  * force allocation of a new frame. Otherwise, we create
510  * a dangling frame reference. Each thread has its own copy of
511  * the next_frames vector.
512  */
513  if (0 && r->thread_index != next_runtime->thread_index)
514  {
515  nf->frame = NULL;
517  }
518  }
519 
520  /* Copy trace flag from next_frame and from runtime. */
521  nf->flags |=
522  (nf->flags & VLIB_NODE_FLAG_TRACE) | (r->
524 
526  v1 = v0 + n_vectors_in_frame;
528  if (PREDICT_FALSE (v1 < v0))
529  {
530  vlib_node_t *node = vlib_get_node (vm, r->node_index);
531  vec_elt (node->n_vectors_by_next_node, next_index) += v0;
532  }
533  }
534 }
535 
536 /* Sync up runtime (32 bit counters) and main node stats (64 bit counters). */
537 never_inline void
540  uword n_calls, uword n_vectors, uword n_clocks,
541  uword n_ticks)
542 {
543  vlib_node_t *n = vlib_get_node (vm, r->node_index);
544 
545  n->stats_total.calls += n_calls + r->calls_since_last_overflow;
546  n->stats_total.vectors += n_vectors + r->vectors_since_last_overflow;
547  n->stats_total.clocks += n_clocks + r->clocks_since_last_overflow;
548  n->stats_total.perf_counter_ticks += n_ticks +
550  n->stats_total.perf_counter_vectors += n_vectors +
554 
560 }
561 
562 always_inline void __attribute__ ((unused))
564  vlib_process_t * p,
565  uword n_calls, uword n_vectors, uword n_clocks,
566  uword n_ticks)
567 {
568  vlib_node_runtime_t *rt = &p->node_runtime;
570  vlib_node_runtime_sync_stats (vm, rt, n_calls, n_vectors, n_clocks,
571  n_ticks);
572  n->stats_total.suspends += p->n_suspends;
573  p->n_suspends = 0;
574 }
575 
576 void
578 {
580 
581  if (n->type == VLIB_NODE_TYPE_PROCESS)
582  {
583  /* Nothing to do for PROCESS nodes except in main thread */
584  if (vm != &vlib_global_main)
585  return;
586 
589  p->n_suspends = 0;
590  rt = &p->node_runtime;
591  }
592  else
593  rt =
595  n->runtime_index);
596 
597  vlib_node_runtime_sync_stats (vm, rt, 0, 0, 0, 0);
598 
599  /* Sync up runtime next frame vector counters with main node structure. */
600  {
601  vlib_next_frame_t *nf;
602  uword i;
603  for (i = 0; i < rt->n_next_nodes; i++)
604  {
605  nf = vlib_node_runtime_get_next_frame (vm, rt, i);
609  }
610  }
611 }
612 
615  vlib_node_runtime_t * node,
616  uword n_calls,
617  uword n_vectors, uword n_clocks,
618  uword n_ticks)
619 {
620  u32 ca0, ca1, v0, v1, cl0, cl1, r;
621  u32 ptick0, ptick1, pvec0, pvec1;
622 
623  cl0 = cl1 = node->clocks_since_last_overflow;
624  ca0 = ca1 = node->calls_since_last_overflow;
625  v0 = v1 = node->vectors_since_last_overflow;
626  ptick0 = ptick1 = node->perf_counter_ticks_since_last_overflow;
627  pvec0 = pvec1 = node->perf_counter_vectors_since_last_overflow;
628 
629  ca1 = ca0 + n_calls;
630  v1 = v0 + n_vectors;
631  cl1 = cl0 + n_clocks;
632  ptick1 = ptick0 + n_ticks;
633  pvec1 = pvec0 + n_vectors;
634 
635  node->calls_since_last_overflow = ca1;
636  node->clocks_since_last_overflow = cl1;
637  node->vectors_since_last_overflow = v1;
640 
641  node->max_clock_n = node->max_clock > n_clocks ?
642  node->max_clock_n : n_vectors;
643  node->max_clock = node->max_clock > n_clocks ? node->max_clock : n_clocks;
644 
645  r = vlib_node_runtime_update_main_loop_vector_stats (vm, node, n_vectors);
646 
647  if (PREDICT_FALSE (ca1 < ca0 || v1 < v0 || cl1 < cl0) || (ptick1 < ptick0)
648  || (pvec1 < pvec0))
649  {
650  node->calls_since_last_overflow = ca0;
651  node->clocks_since_last_overflow = cl0;
652  node->vectors_since_last_overflow = v0;
655 
656  vlib_node_runtime_sync_stats (vm, node, n_calls, n_vectors, n_clocks,
657  n_ticks);
658  }
659 
660  return r;
661 }
662 
663 static inline u64
665 {
667  return ((*vm->vlib_node_runtime_perf_counter_cb) (vm));
668  return 0ULL;
669 }
670 
671 always_inline void
673  vlib_process_t * p,
674  uword n_calls, uword n_vectors, uword n_clocks,
675  uword n_ticks)
676 {
678  n_calls, n_vectors, n_clocks, n_ticks);
679 }
680 
681 static clib_error_t *
683  unformat_input_t * input, vlib_cli_command_t * cmd)
684 {
686  return 0;
687 }
688 
689 /* *INDENT-OFF* */
690 VLIB_CLI_COMMAND (elog_clear_cli, static) = {
691  .path = "event-logger clear",
692  .short_help = "Clear the event log",
693  .function = vlib_cli_elog_clear,
694 };
695 /* *INDENT-ON* */
696 
697 #ifdef CLIB_UNIX
698 static clib_error_t *
700  unformat_input_t * input, vlib_cli_command_t * cmd)
701 {
702  elog_main_t *em = &vm->elog_main;
703  char *file, *chroot_file;
704  clib_error_t *error = 0;
705 
706  if (!unformat (input, "%s", &file))
707  {
708  vlib_cli_output (vm, "expected file name, got `%U'",
709  format_unformat_error, input);
710  return 0;
711  }
712 
713  /* It's fairly hard to get "../oopsie" through unformat; just in case */
714  if (strstr (file, "..") || index (file, '/'))
715  {
716  vlib_cli_output (vm, "illegal characters in filename '%s'", file);
717  return 0;
718  }
719 
720  chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
721 
722  vec_free (file);
723 
724  vlib_cli_output (vm, "Saving %wd of %wd events to %s",
726  elog_buffer_capacity (em), chroot_file);
727 
729  error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
731  vec_free (chroot_file);
732  return error;
733 }
734 
735 void
737 {
739  elog_main_t *em = &vm->elog_main;
740  u8 *filename;
741  clib_error_t *error;
742 
743  if (!vm->elog_post_mortem_dump)
744  return;
745 
746  filename = format (0, "/tmp/elog_post_mortem.%d%c", getpid (), 0);
747  error = elog_write_file (em, (char *) filename, 1 /* flush ring */ );
748  if (error)
749  clib_error_report (error);
750  vec_free (filename);
751 }
752 
753 /* *INDENT-OFF* */
754 VLIB_CLI_COMMAND (elog_save_cli, static) = {
755  .path = "event-logger save",
756  .short_help = "event-logger save <filename> (saves log in /tmp/<filename>)",
757  .function = elog_save_buffer,
758 };
759 /* *INDENT-ON* */
760 
761 static clib_error_t *
763  unformat_input_t * input, vlib_cli_command_t * cmd)
764 {
765  elog_main_t *em = &vm->elog_main;
766 
768 
769  vlib_cli_output (vm, "Stopped the event logger...");
770  return 0;
771 }
772 
773 /* *INDENT-OFF* */
774 VLIB_CLI_COMMAND (elog_stop_cli, static) = {
775  .path = "event-logger stop",
776  .short_help = "Stop the event-logger",
777  .function = elog_stop,
778 };
779 /* *INDENT-ON* */
780 
781 static clib_error_t *
783  unformat_input_t * input, vlib_cli_command_t * cmd)
784 {
785  elog_main_t *em = &vm->elog_main;
786 
788 
789  vlib_cli_output (vm, "Restarted the event logger...");
790  return 0;
791 }
792 
793 /* *INDENT-OFF* */
794 VLIB_CLI_COMMAND (elog_restart_cli, static) = {
795  .path = "event-logger restart",
796  .short_help = "Restart the event-logger",
797  .function = elog_restart,
798 };
799 /* *INDENT-ON* */
800 
801 static clib_error_t *
803  unformat_input_t * input, vlib_cli_command_t * cmd)
804 {
805  elog_main_t *em = &vm->elog_main;
806  u32 tmp;
807 
808  /* Stop the parade */
810 
811  if (unformat (input, "%d", &tmp))
812  {
813  elog_alloc (em, tmp);
815  }
816  else
817  return clib_error_return (0, "Must specify how many events in the ring");
818 
819  vlib_cli_output (vm, "Resized ring and restarted the event logger...");
820  return 0;
821 }
822 
823 /* *INDENT-OFF* */
824 VLIB_CLI_COMMAND (elog_resize_cli, static) = {
825  .path = "event-logger resize",
826  .short_help = "event-logger resize <nnn>",
827  .function = elog_resize,
828 };
829 /* *INDENT-ON* */
830 
831 #endif /* CLIB_UNIX */
832 
833 static void
835 {
836  elog_main_t *em = &vm->elog_main;
837  elog_event_t *e, *es;
838  f64 dt;
839 
840  /* Show events in VLIB time since log clock starts after VLIB clock. */
841  dt = (em->init_time.cpu - vm->clib_time.init_cpu_time)
843 
844  es = elog_peek_events (em);
845  vlib_cli_output (vm, "%d of %d events in buffer, logger %s", vec_len (es),
846  em->event_ring_size,
848  "running" : "stopped");
849  vec_foreach (e, es)
850  {
851  vlib_cli_output (vm, "%18.9f: %U",
852  e->time + dt, format_elog_event, em, e);
853  n_events_to_show--;
854  if (n_events_to_show == 0)
855  break;
856  }
857  vec_free (es);
858 
859 }
860 
861 static clib_error_t *
863  unformat_input_t * input, vlib_cli_command_t * cmd)
864 {
865  u32 n_events_to_show;
866  clib_error_t *error = 0;
867 
868  n_events_to_show = 250;
870  {
871  if (unformat (input, "%d", &n_events_to_show))
872  ;
873  else if (unformat (input, "all"))
874  n_events_to_show = ~0;
875  else
876  return unformat_parse_error (input);
877  }
878  elog_show_buffer_internal (vm, n_events_to_show);
879  return error;
880 }
881 
882 /* *INDENT-OFF* */
883 VLIB_CLI_COMMAND (elog_show_cli, static) = {
884  .path = "show event-logger",
885  .short_help = "Show event logger info",
886  .function = elog_show_buffer,
887 };
888 /* *INDENT-ON* */
889 
890 void
892 {
894 }
895 
896 static inline void
898  u32 node_index,
899  u64 time, u32 n_vectors, u32 is_return)
900 {
902  elog_main_t *em = &evm->elog_main;
903 
904  if (VLIB_ELOG_MAIN_LOOP && n_vectors)
905  elog_track (em,
906  /* event type */
907  vec_elt_at_index (is_return
910  node_index),
911  /* track */
913  elog_track : &em->default_track),
914  /* data to log */ n_vectors);
915 }
916 
917 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0
918 void (*vlib_buffer_trace_trajectory_cb) (vlib_buffer_t * b, u32 node_index);
919 void (*vlib_buffer_trace_trajectory_init_cb) (vlib_buffer_t * b);
920 
921 void
922 vlib_buffer_trace_trajectory_init (vlib_buffer_t * b)
923 {
924  if (PREDICT_TRUE (vlib_buffer_trace_trajectory_init_cb != 0))
925  {
926  (*vlib_buffer_trace_trajectory_init_cb) (b);
927  }
928 }
929 
930 #endif
931 
932 static inline void
934 {
935 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0
936  if (PREDICT_TRUE (vlib_buffer_trace_trajectory_cb != 0))
937  {
938  (*vlib_buffer_trace_trajectory_cb) (b, node_index);
939  }
940 #endif
941 }
942 
943 u8 *format_vnet_buffer_flags (u8 * s, va_list * args) __attribute__ ((weak));
944 u8 *
945 format_vnet_buffer_flags (u8 * s, va_list * args)
946 {
947  s = format (s, "BUG STUB %s", __FUNCTION__);
948  return s;
949 }
950 
951 u8 *format_vnet_buffer_opaque (u8 * s, va_list * args) __attribute__ ((weak));
952 u8 *
953 format_vnet_buffer_opaque (u8 * s, va_list * args)
954 {
955  s = format (s, "BUG STUB %s", __FUNCTION__);
956  return s;
957 }
958 
959 u8 *format_vnet_buffer_opaque2 (u8 * s, va_list * args)
960  __attribute__ ((weak));
961 u8 *
962 format_vnet_buffer_opaque2 (u8 * s, va_list * args)
963 {
964  s = format (s, "BUG STUB %s", __FUNCTION__);
965  return s;
966 }
967 
968 static u8 *
969 format_buffer_metadata (u8 * s, va_list * args)
970 {
971  vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
972 
973  s = format (s, "flags: %U\n", format_vnet_buffer_flags, b);
974  s = format (s, "current_data: %d, current_length: %d\n",
975  (i32) (b->current_data), (i32) (b->current_length));
976  s = format (s, "current_config_index: %d, flow_id: %x, next_buffer: %x\n",
978  s = format (s, "error: %d, n_add_refs: %d, buffer_pool_index: %d\n",
979  (u32) (b->error), (u32) (b->n_add_refs),
980  (u32) (b->buffer_pool_index));
981  s = format (s,
982  "trace_index: %d, recycle_count: %d, len_not_first_buf: %d\n",
983  b->trace_index, b->recycle_count,
985  s = format (s, "free_list_index: %d\n", (u32) (b->free_list_index));
986  return s;
987 }
988 
989 #define A(x) vec_add1(vm->pcap_buffer, (x))
990 
991 static void
993  vlib_node_runtime_t * node, vlib_frame_t * frame)
994 {
995  int i;
996  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **bufp, *b;
997  pcap_main_t *pm = &vm->dispatch_pcap_main;
998  vlib_trace_main_t *tm = &vm->trace_main;
999  u32 capture_size;
1000  vlib_node_t *n;
1001  i32 n_left;
1002  f64 time_now = vlib_time_now (vm);
1003  u32 *from;
1004  u8 *d;
1005  u8 string_count;
1006 
1007  /* Input nodes don't have frames yet */
1008  if (frame == 0 || frame->n_vectors == 0)
1009  return;
1010 
1011  from = vlib_frame_vector_args (frame);
1012  vlib_get_buffers (vm, from, bufs, frame->n_vectors);
1013  bufp = bufs;
1014 
1015  n = vlib_get_node (vm, node->node_index);
1016 
1017  for (i = 0; i < frame->n_vectors; i++)
1018  {
1020  {
1021  b = bufp[i];
1022 
1024  string_count = 0;
1025 
1026  /* Version, flags */
1029  A (0 /* string_count */ );
1030  A (n->protocol_hint);
1031 
1032  /* Buffer index (big endian) */
1033  A ((from[i] >> 24) & 0xff);
1034  A ((from[i] >> 16) & 0xff);
1035  A ((from[i] >> 8) & 0xff);
1036  A ((from[i] >> 0) & 0xff);
1037 
1038  /* Node name, NULL-terminated ASCII */
1039  vm->pcap_buffer = format (vm->pcap_buffer, "%v%c", n->name, 0);
1040  string_count++;
1041 
1042  vm->pcap_buffer = format (vm->pcap_buffer, "%U%c",
1043  format_buffer_metadata, b, 0);
1044  string_count++;
1045  vm->pcap_buffer = format (vm->pcap_buffer, "%U%c",
1047  string_count++;
1048  vm->pcap_buffer = format (vm->pcap_buffer, "%U%c",
1050  string_count++;
1051 
1052  /* Is this packet traced? */
1053  if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
1054  {
1057 
1058  vm->pcap_buffer = format (vm->pcap_buffer, "%U%c",
1059  format_vlib_trace, vm, h[0], 0);
1060  string_count++;
1061  }
1062 
1063  /* Save the string count */
1064  vm->pcap_buffer[2] = string_count;
1065 
1066  /* Figure out how many bytes in the pcap trace */
1067  capture_size = vec_len (vm->pcap_buffer) +
1068  +vlib_buffer_length_in_chain (vm, b);
1069 
1071  n_left = clib_min (capture_size, 16384);
1072  d = pcap_add_packet (pm, time_now, n_left, capture_size);
1073 
1074  /* Copy the header */
1076  d += vec_len (vm->pcap_buffer);
1077 
1078  n_left = clib_min
1079  (vlib_buffer_length_in_chain (vm, b),
1080  (16384 - vec_len (vm->pcap_buffer)));
1081  /* Copy the packet data */
1082  while (1)
1083  {
1084  u32 copy_length = clib_min ((u32) n_left, b->current_length);
1085  clib_memcpy_fast (d, b->data + b->current_data, copy_length);
1086  n_left -= b->current_length;
1087  if (n_left <= 0)
1088  break;
1089  d += b->current_length;
1090  ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
1091  b = vlib_get_buffer (vm, b->next_buffer);
1092  }
1094  }
1095  }
1096 }
1097 
1100  vlib_node_runtime_t * node,
1101  vlib_node_type_t type,
1102  vlib_node_state_t dispatch_state,
1103  vlib_frame_t * frame, u64 last_time_stamp)
1104 {
1105  uword n, v;
1106  u64 t;
1107  vlib_node_main_t *nm = &vm->node_main;
1108  vlib_next_frame_t *nf;
1109 
1110  if (CLIB_DEBUG > 0)
1111  {
1112  vlib_node_t *n = vlib_get_node (vm, node->node_index);
1113  ASSERT (n->type == type);
1114  }
1115 
1116  /* Only non-internal nodes may be disabled. */
1117  if (type != VLIB_NODE_TYPE_INTERNAL && node->state != dispatch_state)
1118  {
1119  ASSERT (type != VLIB_NODE_TYPE_INTERNAL);
1120  return last_time_stamp;
1121  }
1122 
1123  if ((type == VLIB_NODE_TYPE_PRE_INPUT || type == VLIB_NODE_TYPE_INPUT)
1124  && dispatch_state != VLIB_NODE_STATE_INTERRUPT)
1125  {
1127  /* Only call node when count reaches zero. */
1128  if (c)
1129  {
1130  node->input_main_loops_per_call = c - 1;
1131  return last_time_stamp;
1132  }
1133  }
1134 
1135  /* Speculatively prefetch next frames. */
1136  if (node->n_next_nodes > 0)
1137  {
1138  nf = vec_elt_at_index (nm->next_frames, node->next_frame_index);
1139  CLIB_PREFETCH (nf, 4 * sizeof (nf[0]), WRITE);
1140  }
1141 
1142  vm->cpu_time_last_node_dispatch = last_time_stamp;
1143 
1144  if (1 /* || vm->thread_index == node->thread_index */ )
1145  {
1146  u64 pmc_before, pmc_delta;
1147 
1149  last_time_stamp,
1150  frame ? frame->n_vectors : 0,
1151  /* is_after */ 0);
1152 
1153  /*
1154  * To validate accounting: pmc_before = last_time_stamp
1155  * perf ticks should equal clocks/pkt...
1156  */
1157  pmc_before = vlib_node_runtime_perf_counter (vm);
1158 
1159  /*
1160  * Turn this on if you run into
1161  * "bad monkey" contexts, and you want to know exactly
1162  * which nodes they've visited... See ixge.c...
1163  */
1164  if (VLIB_BUFFER_TRACE_TRAJECTORY && frame)
1165  {
1166  int i;
1167  u32 *from;
1168  from = vlib_frame_vector_args (frame);
1169  for (i = 0; i < frame->n_vectors; i++)
1170  {
1171  vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
1172  add_trajectory_trace (b, node->node_index);
1173  }
1175  dispatch_pcap_trace (vm, node, frame);
1176  n = node->function (vm, node, frame);
1177  }
1178  else
1179  {
1181  dispatch_pcap_trace (vm, node, frame);
1182  n = node->function (vm, node, frame);
1183  }
1184 
1185  t = clib_cpu_time_now ();
1186 
1187  /*
1188  * To validate accounting: pmc_delta = t - pmc_before;
1189  * perf ticks should equal clocks/pkt...
1190  */
1191  pmc_delta = vlib_node_runtime_perf_counter (vm) - pmc_before;
1192 
1193  vlib_elog_main_loop_event (vm, node->node_index, t, n, /* is_after */
1194  1);
1195 
1196  vm->main_loop_vectors_processed += n;
1197  vm->main_loop_nodes_processed += n > 0;
1198 
1199  v = vlib_node_runtime_update_stats (vm, node,
1200  /* n_calls */ 1,
1201  /* n_vectors */ n,
1202  /* n_clocks */ t - last_time_stamp,
1203  pmc_delta /* PMC ticks */ );
1204 
1205  /* When in interrupt mode and vector rate crosses threshold switch to
1206  polling mode. */
1207  if ((dispatch_state == VLIB_NODE_STATE_INTERRUPT)
1208  || (dispatch_state == VLIB_NODE_STATE_POLLING
1209  && (node->flags
1211  {
1212 #ifdef DISPATCH_NODE_ELOG_REQUIRED
1213  ELOG_TYPE_DECLARE (e) =
1214  {
1215  .function = (char *) __FUNCTION__,.format =
1216  "%s vector length %d, switching to %s",.format_args =
1217  "T4i4t4",.n_enum_strings = 2,.enum_strings =
1218  {
1219  "interrupt", "polling",},};
1220  struct
1221  {
1222  u32 node_name, vector_length, is_polling;
1223  } *ed;
1225 #endif
1226 
1227  if ((dispatch_state == VLIB_NODE_STATE_INTERRUPT
1228  && v >= nm->polling_threshold_vector_length) &&
1229  !(node->flags &
1231  {
1232  vlib_node_t *n = vlib_get_node (vm, node->node_index);
1233  n->state = VLIB_NODE_STATE_POLLING;
1234  node->state = VLIB_NODE_STATE_POLLING;
1235  node->flags &=
1237  node->flags |=
1239  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] -= 1;
1240  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] += 1;
1241 
1242 #ifdef DISPATCH_NODE_ELOG_REQUIRED
1243  ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
1244  w->elog_track);
1245  ed->node_name = n->name_elog_string;
1246  ed->vector_length = v;
1247  ed->is_polling = 1;
1248 #endif
1249  }
1250  else if (dispatch_state == VLIB_NODE_STATE_POLLING
1251  && v <= nm->interrupt_threshold_vector_length)
1252  {
1253  vlib_node_t *n = vlib_get_node (vm, node->node_index);
1254  if (node->flags &
1256  {
1257  /* Switch to interrupt mode after dispatch in polling one more time.
1258  This allows driver to re-enable interrupts. */
1259  n->state = VLIB_NODE_STATE_INTERRUPT;
1260  node->state = VLIB_NODE_STATE_INTERRUPT;
1261  node->flags &=
1263  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] -=
1264  1;
1265  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] +=
1266  1;
1267 
1268  }
1269  else
1270  {
1271  node->flags |=
1273 #ifdef DISPATCH_NODE_ELOG_REQUIRED
1274  ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
1275  w->elog_track);
1276  ed->node_name = n->name_elog_string;
1277  ed->vector_length = v;
1278  ed->is_polling = 0;
1279 #endif
1280  }
1281  }
1282  }
1283  }
1284 
1285  return t;
1286 }
1287 
1288 static u64
1289 dispatch_pending_node (vlib_main_t * vm, uword pending_frame_index,
1290  u64 last_time_stamp)
1291 {
1292  vlib_node_main_t *nm = &vm->node_main;
1293  vlib_frame_t *f;
1294  vlib_next_frame_t *nf, nf_dummy;
1296  vlib_frame_t *restore_frame;
1298 
1299  /* See comment below about dangling references to nm->pending_frames */
1300  p = nm->pending_frames + pending_frame_index;
1301 
1303  p->node_runtime_index);
1304 
1305  f = vlib_get_frame (vm, p->frame);
1307  {
1308  /* No next frame: so use dummy on stack. */
1309  nf = &nf_dummy;
1311  nf->frame = NULL;
1312  }
1313  else
1315 
1317 
1318  /* Force allocation of new frame while current frame is being
1319  dispatched. */
1320  restore_frame = NULL;
1321  if (nf->frame == p->frame)
1322  {
1323  nf->frame = NULL;
1326  restore_frame = p->frame;
1327  }
1328 
1329  /* Frame must be pending. */
1331  ASSERT (f->n_vectors > 0);
1332 
1333  /* Copy trace flag from next frame to node.
1334  Trace flag indicates that at least one vector in the dispatched
1335  frame is traced. */
1336  n->flags &= ~VLIB_NODE_FLAG_TRACE;
1337  n->flags |= (nf->flags & VLIB_FRAME_TRACE) ? VLIB_NODE_FLAG_TRACE : 0;
1338  nf->flags &= ~VLIB_FRAME_TRACE;
1339 
1340  last_time_stamp = dispatch_node (vm, n,
1342  VLIB_NODE_STATE_POLLING,
1343  f, last_time_stamp);
1344 
1346 
1347  /* Frame is ready to be used again, so restore it. */
1348  if (restore_frame != NULL)
1349  {
1350  /*
1351  * We musn't restore a frame that is flagged to be freed. This
1352  * shouldn't happen since frames to be freed post dispatch are
1353  * those used when the to-node frame becomes full i.e. they form a
1354  * sort of queue of frames to a single node. If we get here then
1355  * the to-node frame and the pending frame *were* the same, and so
1356  * we removed the to-node frame. Therefore this frame is no
1357  * longer part of the queue for that node and hence it cannot be
1358  * it's overspill.
1359  */
1361 
1362  /*
1363  * NB: dispatching node n can result in the creation and scheduling
1364  * of new frames, and hence in the reallocation of nm->pending_frames.
1365  * Recompute p, or no supper. This was broken for more than 10 years.
1366  */
1367  p = nm->pending_frames + pending_frame_index;
1368 
1369  /*
1370  * p->next_frame_index can change during node dispatch if node
1371  * function decides to change graph hook up.
1372  */
1375 
1376  if (NULL == nf->frame)
1377  {
1378  /* no new frame has been assigned to this node, use the saved one */
1379  nf->frame = restore_frame;
1380  f->n_vectors = 0;
1381  }
1382  else
1383  {
1384  /* The node has gained a frame, implying packets from the current frame
1385  were re-queued to this same node. we don't need the saved one
1386  anymore */
1387  vlib_frame_free (vm, n, f);
1388  }
1389  }
1390  else
1391  {
1393  {
1395  vlib_frame_free (vm, n, f);
1396  }
1397  }
1398 
1399  return last_time_stamp;
1400 }
1401 
1404 {
1405  return p->stack[0] == VLIB_PROCESS_STACK_MAGIC;
1406 }
1407 
1408 typedef struct
1409 {
1414 
1415 /* Called in process stack. */
1416 static uword
1418 {
1420  vlib_main_t *vm;
1421  vlib_node_runtime_t *node;
1422  vlib_frame_t *f;
1423  vlib_process_t *p;
1424  uword n;
1425 
1427 
1428  vm = a->vm;
1429  p = a->process;
1430  f = a->frame;
1431  node = &p->node_runtime;
1432 
1433  n = node->function (vm, node, f);
1434 
1436 
1437  clib_longjmp (&p->return_longjmp, n);
1438 
1439  return n;
1440 }
1441 
1442 /* Called in main stack. */
1445 {
1447  uword r;
1448 
1449  a.vm = vm;
1450  a.process = p;
1451  a.frame = f;
1452 
1456  (void *) p->stack + (1 << p->log2_n_stack_bytes));
1457 
1458  return r;
1459 }
1460 
1463 {
1464  uword r;
1471  return r;
1472 }
1473 
1474 static u64
1476  vlib_process_t * p, vlib_frame_t * f, u64 last_time_stamp)
1477 {
1478  vlib_node_main_t *nm = &vm->node_main;
1479  vlib_node_runtime_t *node_runtime = &p->node_runtime;
1480  vlib_node_t *node = vlib_get_node (vm, node_runtime->node_index);
1481  u32 old_process_index;
1482  u64 t;
1483  uword n_vectors, is_suspend;
1484 
1485  if (node->state != VLIB_NODE_STATE_POLLING
1488  return last_time_stamp;
1489 
1491 
1492  t = last_time_stamp;
1493  vlib_elog_main_loop_event (vm, node_runtime->node_index, t,
1494  f ? f->n_vectors : 0, /* is_after */ 0);
1495 
1496  /* Save away current process for suspend. */
1497  old_process_index = nm->current_process_index;
1499 
1500  n_vectors = vlib_process_startup (vm, p, f);
1501 
1502  nm->current_process_index = old_process_index;
1503 
1505  is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
1506  if (is_suspend)
1507  {
1509 
1510  n_vectors = 0;
1512  pf->node_runtime_index = node->runtime_index;
1513  pf->frame = f;
1514  pf->next_frame_index = ~0;
1515 
1516  p->n_suspends += 1;
1518 
1520  {
1521  TWT (tw_timer_wheel) * tw =
1522  (TWT (tw_timer_wheel) *) nm->timing_wheel;
1523  p->stop_timer_handle =
1524  TW (tw_timer_start) (tw,
1526  (node->runtime_index) /* [sic] pool idex */ ,
1527  0 /* timer_id */ ,
1529  }
1530  }
1531  else
1533 
1534  t = clib_cpu_time_now ();
1535 
1536  vlib_elog_main_loop_event (vm, node_runtime->node_index, t, is_suspend,
1537  /* is_after */ 1);
1538 
1540  /* n_calls */ !is_suspend,
1541  /* n_vectors */ n_vectors,
1542  /* n_clocks */ t - last_time_stamp,
1543  /* pmc_ticks */ 0ULL);
1544 
1545  return t;
1546 }
1547 
1548 void
1550 {
1551  vlib_node_main_t *nm = &vm->node_main;
1552  vlib_process_t *p = vec_elt (nm->processes, process_index);
1553  dispatch_process (vm, p, /* frame */ 0, /* cpu_time_now */ 0);
1554 }
1555 
1556 static u64
1558  uword process_index, u64 last_time_stamp)
1559 {
1560  vlib_node_main_t *nm = &vm->node_main;
1561  vlib_node_runtime_t *node_runtime;
1562  vlib_node_t *node;
1563  vlib_frame_t *f;
1564  vlib_process_t *p;
1566  u64 t, n_vectors, is_suspend;
1567 
1568  t = last_time_stamp;
1569 
1570  p = vec_elt (nm->processes, process_index);
1572  return last_time_stamp;
1573 
1576 
1579 
1580  node_runtime = &p->node_runtime;
1581  node = vlib_get_node (vm, node_runtime->node_index);
1582  f = pf->frame;
1583 
1584  vlib_elog_main_loop_event (vm, node_runtime->node_index, t,
1585  f ? f->n_vectors : 0, /* is_after */ 0);
1586 
1587  /* Save away current process for suspend. */
1589 
1590  n_vectors = vlib_process_resume (p);
1591  t = clib_cpu_time_now ();
1592 
1593  nm->current_process_index = ~0;
1594 
1595  is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
1596  if (is_suspend)
1597  {
1598  /* Suspend it again. */
1599  n_vectors = 0;
1600  p->n_suspends += 1;
1602  {
1603  p->stop_timer_handle =
1604  TW (tw_timer_start) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
1606  (node->runtime_index) /* [sic] pool idex */ ,
1607  0 /* timer_id */ ,
1609  }
1610  }
1611  else
1612  {
1617  }
1618 
1619  t = clib_cpu_time_now ();
1620  vlib_elog_main_loop_event (vm, node_runtime->node_index, t, !is_suspend,
1621  /* is_after */ 1);
1622 
1624  /* n_calls */ !is_suspend,
1625  /* n_vectors */ n_vectors,
1626  /* n_clocks */ t - last_time_stamp,
1627  /* pmc_ticks */ 0ULL);
1628 
1629  return t;
1630 }
1631 
1632 void vl_api_send_pending_rpc_requests (vlib_main_t *) __attribute__ ((weak));
1633 void
1635 {
1636 }
1637 
1638 
1641 {
1642  vlib_node_main_t *nm = &vm->node_main;
1644  uword i;
1645  u64 cpu_time_now;
1647  u32 *last_node_runtime_indices = 0;
1648 
1649  /* Initialize pending node vector. */
1650  if (is_main)
1651  {
1652  vec_resize (nm->pending_frames, 32);
1653  _vec_len (nm->pending_frames) = 0;
1654  }
1655 
1656  /* Mark time of main loop start. */
1657  if (is_main)
1658  {
1659  cpu_time_now = vm->clib_time.last_cpu_time;
1660  vm->cpu_time_main_loop_start = cpu_time_now;
1661  }
1662  else
1663  cpu_time_now = clib_cpu_time_now ();
1664 
1665  /* Pre-allocate interupt runtime indices and lock. */
1667  vec_alloc (last_node_runtime_indices, 32);
1668  if (!is_main)
1670 
1671  /* Pre-allocate expired nodes. */
1676 
1677  /* Make sure the performance monitor counter is disabled */
1678  vm->perf_counter_id = ~0;
1679 
1680  /* Start all processes. */
1681  if (is_main)
1682  {
1683  uword i;
1684  nm->current_process_index = ~0;
1685  for (i = 0; i < vec_len (nm->processes); i++)
1686  cpu_time_now = dispatch_process (vm, nm->processes[i], /* frame */ 0,
1687  cpu_time_now);
1688  }
1689 
1690  while (1)
1691  {
1693 
1694  if (PREDICT_FALSE (_vec_len (vm->pending_rpc_requests) > 0))
1695  {
1696  if (!is_main)
1698  }
1699 
1700  if (!is_main)
1701  {
1703  vec_foreach (fqm, tm->frame_queue_mains)
1704  vlib_frame_queue_dequeue (vm, fqm);
1706  ((void (*)(vlib_main_t *)) vm->worker_thread_main_loop_callback)
1707  (vm);
1708  }
1709 
1710  /* Process pre-input nodes. */
1712  cpu_time_now = dispatch_node (vm, n,
1714  VLIB_NODE_STATE_POLLING,
1715  /* frame */ 0,
1716  cpu_time_now);
1717 
1718  /* Next process input nodes. */
1720  cpu_time_now = dispatch_node (vm, n,
1722  VLIB_NODE_STATE_POLLING,
1723  /* frame */ 0,
1724  cpu_time_now);
1725 
1726  if (PREDICT_TRUE (is_main && vm->queue_signal_pending == 0))
1727  vm->queue_signal_callback (vm);
1728 
1729  /* Next handle interrupts. */
1730  {
1731  /* unlocked read, for performance */
1732  uword l = _vec_len (nm->pending_interrupt_node_runtime_indices);
1733  uword i;
1734  if (PREDICT_FALSE (l > 0))
1735  {
1736  u32 *tmp;
1737  if (!is_main)
1738  {
1740  /* Re-read w/ lock held, in case another thread added an item */
1741  l = _vec_len (nm->pending_interrupt_node_runtime_indices);
1742  }
1743 
1746  last_node_runtime_indices;
1747  last_node_runtime_indices = tmp;
1748  _vec_len (last_node_runtime_indices) = 0;
1749  if (!is_main)
1751  for (i = 0; i < l; i++)
1752  {
1754  last_node_runtime_indices[i]);
1755  cpu_time_now =
1757  VLIB_NODE_STATE_INTERRUPT,
1758  /* frame */ 0,
1759  cpu_time_now);
1760  }
1761  }
1762  }
1763  /* Input nodes may have added work to the pending vector.
1764  Process pending vector until there is nothing left.
1765  All pending vectors will be processed from input -> output. */
1766  for (i = 0; i < _vec_len (nm->pending_frames); i++)
1767  cpu_time_now = dispatch_pending_node (vm, i, cpu_time_now);
1768  /* Reset pending vector for next iteration. */
1769  _vec_len (nm->pending_frames) = 0;
1770 
1771  if (is_main)
1772  {
1773  /* Check if process nodes have expired from timing wheel. */
1775 
1778  ((TWT (tw_timer_wheel) *) nm->timing_wheel, vlib_time_now (vm),
1780 
1782 
1783  if (PREDICT_FALSE
1784  (_vec_len (nm->data_from_advancing_timing_wheel) > 0))
1785  {
1786  uword i;
1787 
1788  for (i = 0; i < _vec_len (nm->data_from_advancing_timing_wheel);
1789  i++)
1790  {
1793 
1795  {
1798  di);
1799  vlib_node_t *n =
1801  vlib_process_t *p =
1802  vec_elt (nm->processes, n->runtime_index);
1803  void *data;
1804  data =
1806  te->event_type_index,
1807  te->n_data_elts,
1808  te->n_data_elt_bytes);
1809  if (te->n_data_bytes < sizeof (te->inline_event_data))
1811  te->n_data_bytes);
1812  else
1813  {
1815  te->n_data_bytes);
1817  }
1819  }
1820  else
1821  {
1822  cpu_time_now = clib_cpu_time_now ();
1823  cpu_time_now =
1824  dispatch_suspended_process (vm, di, cpu_time_now);
1825  }
1826  }
1827  _vec_len (nm->data_from_advancing_timing_wheel) = 0;
1828  }
1829  }
1831 
1832  /* Record time stamp in case there are no enabled nodes and above
1833  calls do not update time stamp. */
1834  cpu_time_now = clib_cpu_time_now ();
1835  }
1836 }
1837 
1838 static void
1840 {
1841  vlib_main_or_worker_loop (vm, /* is_main */ 1);
1842 }
1843 
1844 void
1846 {
1847  vlib_main_or_worker_loop (vm, /* is_main */ 0);
1848 }
1849 
1851 
1852 static clib_error_t *
1854 {
1855  int turn_on_mem_trace = 0;
1856 
1857  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1858  {
1859  if (unformat (input, "memory-trace"))
1860  turn_on_mem_trace = 1;
1861 
1862  else if (unformat (input, "elog-events %d",
1863  &vm->elog_main.event_ring_size))
1864  ;
1865  else if (unformat (input, "elog-post-mortem-dump"))
1866  vm->elog_post_mortem_dump = 1;
1867  else
1868  return unformat_parse_error (input);
1869  }
1870 
1871  unformat_free (input);
1872 
1873  /* Enable memory trace as early as possible. */
1874  if (turn_on_mem_trace)
1875  clib_mem_trace (1);
1876 
1877  return 0;
1878 }
1879 
1881 
1882 static void
1884 {
1885 }
1886 
1887 #define foreach_weak_reference_stub \
1888 _(vlib_map_stat_segment_init) \
1889 _(vpe_api_init) \
1890 _(vlibmemory_init) \
1891 _(map_api_segment_init)
1892 
1893 #define _(name) \
1894 clib_error_t *name (vlib_main_t *vm) __attribute__((weak)); \
1895 clib_error_t *name (vlib_main_t *vm) { return 0; }
1897 #undef _
1898 
1899 /* Main function. */
1900 int
1902 {
1903  clib_error_t *volatile error;
1904  vlib_node_main_t *nm = &vm->node_main;
1905 
1907 
1908  clib_time_init (&vm->clib_time);
1909 
1910  /* Turn on event log. */
1911  if (!vm->elog_main.event_ring_size)
1912  vm->elog_main.event_ring_size = 128 << 10;
1914  elog_enable_disable (&vm->elog_main, 1);
1915 
1916  /* Default name. */
1917  if (!vm->name)
1918  vm->name = "VLIB";
1919 
1920  if ((error = vlib_physmem_init (vm)))
1921  {
1922  clib_error_report (error);
1923  goto done;
1924  }
1925 
1926  if ((error = vlib_buffer_main_init (vm)))
1927  {
1928  clib_error_report (error);
1929  goto done;
1930  }
1931 
1932  if ((error = vlib_thread_init (vm)))
1933  {
1934  clib_error_report (error);
1935  goto done;
1936  }
1937 
1938  if ((error = vlib_map_stat_segment_init (vm)))
1939  {
1940  clib_error_report (error);
1941  goto done;
1942  }
1943 
1944  /* Register static nodes so that init functions may use them. */
1946 
1947  /* Set seed for random number generator.
1948  Allow user to specify seed to make random sequence deterministic. */
1949  if (!unformat (input, "seed %wd", &vm->random_seed))
1950  vm->random_seed = clib_cpu_time_now ();
1952 
1953  /* Initialize node graph. */
1954  if ((error = vlib_node_main_init (vm)))
1955  {
1956  /* Arrange for graph hook up error to not be fatal when debugging. */
1957  if (CLIB_DEBUG > 0)
1958  clib_error_report (error);
1959  else
1960  goto done;
1961  }
1962 
1963  /* Direct call / weak reference, for vlib standalone use-cases */
1964  if ((error = vpe_api_init (vm)))
1965  {
1966  clib_error_report (error);
1967  goto done;
1968  }
1969 
1970  if ((error = vlibmemory_init (vm)))
1971  {
1972  clib_error_report (error);
1973  goto done;
1974  }
1975 
1976  if ((error = map_api_segment_init (vm)))
1977  {
1978  clib_error_report (error);
1979  goto done;
1980  }
1981 
1982  /* See unix/main.c; most likely already set up */
1983  if (vm->init_functions_called == 0)
1984  vm->init_functions_called = hash_create (0, /* value bytes */ 0);
1985  if ((error = vlib_call_all_init_functions (vm)))
1986  goto done;
1987 
1988  /* Create default buffer free list. */
1990  "default");
1991 
1992  nm->timing_wheel = clib_mem_alloc_aligned (sizeof (TWT (tw_timer_wheel)),
1994 
1996  _vec_len (nm->data_from_advancing_timing_wheel) = 0;
1997 
1998  /* Create the process timing wheel */
1999  TW (tw_timer_wheel_init) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
2000  0 /* no callback */ ,
2001  10e-6 /* timer period 10us */ ,
2002  ~0 /* max expirations per call */ );
2003 
2005  _vec_len (vm->pending_rpc_requests) = 0;
2007  _vec_len (vm->processing_rpc_requests) = 0;
2008 
2009  if ((error = vlib_call_all_config_functions (vm, input, 0 /* is_early */ )))
2010  goto done;
2011 
2012  /* Call all main loop enter functions. */
2013  {
2014  clib_error_t *sub_error;
2015  sub_error = vlib_call_all_main_loop_enter_functions (vm);
2016  if (sub_error)
2017  clib_error_report (sub_error);
2018  }
2019 
2021  {
2023  vm->main_loop_exit_set = 1;
2024  break;
2025 
2027  goto done;
2028 
2029  default:
2030  error = vm->main_loop_error;
2031  goto done;
2032  }
2033 
2034  vlib_main_loop (vm);
2035 
2036 done:
2037  /* Call all exit functions. */
2038  {
2039  clib_error_t *sub_error;
2040  sub_error = vlib_call_all_main_loop_exit_functions (vm);
2041  if (sub_error)
2042  clib_error_report (sub_error);
2043  }
2044 
2045  if (error)
2046  clib_error_report (error);
2047 
2048  return 0;
2049 }
2050 
2051 static inline clib_error_t *
2053  unformat_input_t * input,
2054  vlib_cli_command_t * cmd, int rx_tx)
2055 {
2056 #define PCAP_DEF_PKT_TO_CAPTURE (100)
2057 
2058  unformat_input_t _line_input, *line_input = &_line_input;
2059  pcap_main_t *pm = &vm->dispatch_pcap_main;
2060  u8 *filename;
2061  u8 *chroot_filename = 0;
2062  u32 max = 0;
2063  int enabled = 0;
2064  int errorFlag = 0;
2065  clib_error_t *error = 0;
2066  u32 node_index, add;
2067  vlib_trace_main_t *tm;
2068  vlib_trace_node_t *tn;
2069 
2070  /* Get a line of input. */
2071  if (!unformat_user (input, unformat_line_input, line_input))
2072  return 0;
2073 
2074  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2075  {
2076  if (unformat (line_input, "on"))
2077  {
2078  if (vm->dispatch_pcap_enable == 0)
2079  {
2080  enabled = 1;
2081  }
2082  else
2083  {
2084  vlib_cli_output (vm, "pcap dispatch capture already on...");
2085  errorFlag = 1;
2086  break;
2087  }
2088  }
2089  else if (unformat (line_input, "off"))
2090  {
2091  if (vm->dispatch_pcap_enable)
2092  {
2094  (vm, "captured %d pkts...", pm->n_packets_captured);
2095  if (pm->n_packets_captured)
2096  {
2098  error = pcap_write (pm);
2099  if (error)
2100  clib_error_report (error);
2101  else
2102  vlib_cli_output (vm, "saved to %s...", pm->file_name);
2103  }
2104  vm->dispatch_pcap_enable = 0;
2105  }
2106  else
2107  {
2108  vlib_cli_output (vm, "pcap tx capture already off...");
2109  errorFlag = 1;
2110  break;
2111  }
2112  }
2113  else if (unformat (line_input, "max %d", &max))
2114  {
2115  if (vm->dispatch_pcap_enable)
2116  {
2118  (vm,
2119  "can't change max value while pcap tx capture active...");
2120  errorFlag = 1;
2121  break;
2122  }
2123  pm->n_packets_to_capture = max;
2124  }
2125  else if (unformat (line_input, "file %s", &filename))
2126  {
2127  if (vm->dispatch_pcap_enable)
2128  {
2130  (vm, "can't change file while pcap tx capture active...");
2131  errorFlag = 1;
2132  break;
2133  }
2134 
2135  /* Brain-police user path input */
2136  if (strstr ((char *) filename, "..")
2137  || index ((char *) filename, '/'))
2138  {
2139  vlib_cli_output (vm, "illegal characters in filename '%s'",
2140  filename);
2141  vlib_cli_output (vm, "Hint: .. and / are not allowed.");
2142  vec_free (filename);
2143  errorFlag = 1;
2144  break;
2145  }
2146 
2147  chroot_filename = format (0, "/tmp/%s%c", filename, 0);
2148  vec_free (filename);
2149  }
2150  else if (unformat (line_input, "status"))
2151  {
2152  if (vm->dispatch_pcap_enable)
2153  {
2155  (vm, "pcap dispatch capture is on: %d of %d pkts...",
2157  vlib_cli_output (vm, "Capture to file %s", pm->file_name);
2158  }
2159  else
2160  {
2161  vlib_cli_output (vm, "pcap dispatch capture is off...");
2162  }
2163  break;
2164  }
2165  else if (unformat (line_input, "buffer-trace %U %d",
2166  unformat_vlib_node, vm, &node_index, &add))
2167  {
2168  if (vnet_trace_dummy == 0)
2171  vlib_cli_output (vm, "Buffer tracing of %d pkts from %U enabled...",
2172  add, format_vlib_node_name, vm, node_index);
2173 
2174  /* *INDENT-OFF* */
2176  {
2177  tm = &this_vlib_main->trace_main;
2178  tm->verbose = 0; /* not sure this ever did anything... */
2179  vec_validate (tm->nodes, node_index);
2180  tn = tm->nodes + node_index;
2181  tn->limit += add;
2182  tm->trace_enable = 1;
2183  }));
2184  /* *INDENT-ON* */
2185  }
2186 
2187  else
2188  {
2189  error = clib_error_return (0, "unknown input `%U'",
2190  format_unformat_error, line_input);
2191  errorFlag = 1;
2192  break;
2193  }
2194  }
2195  unformat_free (line_input);
2196 
2197 
2198  if (errorFlag == 0)
2199  {
2200  /* Since no error, save configured values. */
2201  if (chroot_filename)
2202  {
2203  if (pm->file_name)
2204  vec_free (pm->file_name);
2205  vec_add1 (chroot_filename, 0);
2206  pm->file_name = (char *) chroot_filename;
2207  }
2208 
2209  if (max)
2210  pm->n_packets_to_capture = max;
2211 
2212  if (enabled)
2213  {
2214  if (pm->file_name == 0)
2215  pm->file_name = (char *) format (0, "/tmp/dispatch.pcap%c", 0);
2216 
2217  pm->n_packets_captured = 0;
2218  pm->packet_type = PCAP_PACKET_TYPE_vpp;
2219  if (pm->lock == 0)
2220  clib_spinlock_init (&(pm->lock));
2221  vm->dispatch_pcap_enable = 1;
2222  vlib_cli_output (vm, "pcap dispatch capture on...");
2223  }
2224  }
2225  else if (chroot_filename)
2226  vec_free (chroot_filename);
2227 
2228  return error;
2229 }
2230 
2231 static clib_error_t *
2233  unformat_input_t * input,
2234  vlib_cli_command_t * cmd)
2235 {
2236  return pcap_dispatch_trace_command_internal (vm, input, cmd, VLIB_RX);
2237 }
2238 
2239 /*?
2240  * This command is used to start or stop pcap dispatch trace capture, or show
2241  * the capture status.
2242  *
2243  * This command has the following optional parameters:
2244  *
2245  * - <b>on|off</b> - Used to start or stop capture.
2246  *
2247  * - <b>max <nn></b> - Depth of local buffer. Once '<em>nn</em>' number
2248  * of packets have been received, buffer is flushed to file. Once another
2249  * '<em>nn</em>' number of packets have been received, buffer is flushed
2250  * to file, overwriting previous write. If not entered, value defaults
2251  * to 100. Can only be updated if packet capture is off.
2252  *
2253  * - <b>file <name></b> - Used to specify the output filename. The file will
2254  * be placed in the '<em>/tmp</em>' directory, so only the filename is
2255  * supported. Directory should not be entered. If file already exists, file
2256  * will be overwritten. If no filename is provided, '<em>/tmp/vpe.pcap</em>'
2257  * will be used. Can only be updated if packet capture is off.
2258  *
2259  * - <b>status</b> - Displays the current status and configured attributes
2260  * associated with a packet capture. If packet capture is in progress,
2261  * '<em>status</em>' also will return the number of packets currently in
2262  * the local buffer. All additional attributes entered on command line
2263  * with '<em>status</em>' will be ignored and not applied.
2264  *
2265  * @cliexpar
2266  * Example of how to display the status of capture when off:
2267  * @cliexstart{pcap dispatch trace status}
2268  * max is 100, for any interface to file /tmp/vpe.pcap
2269  * pcap dispatch capture is off...
2270  * @cliexend
2271  * Example of how to start a dispatch trace capture:
2272  * @cliexstart{pcap dispatch trace on max 35 file dispatchTrace.pcap}
2273  * pcap dispatch capture on...
2274  * @cliexend
2275  * Example of how to start a dispatch trace capture with buffer tracing
2276  * @cliexstart{pcap dispatch trace on max 10000 file dispatchTrace.pcap buffer-trace dpdk-input 1000}
2277  * pcap dispatch capture on...
2278  * @cliexend
2279  * Example of how to display the status of a tx packet capture in progress:
2280  * @cliexstart{pcap tx trace status}
2281  * max is 35, dispatch trace to file /tmp/vppTest.pcap
2282  * pcap tx capture is on: 20 of 35 pkts...
2283  * @cliexend
2284  * Example of how to stop a tx packet capture:
2285  * @cliexstart{vppctl pcap dispatch trace off}
2286  * captured 21 pkts...
2287  * saved to /tmp/dispatchTrace.pcap...
2288  * @cliexend
2289 ?*/
2290 /* *INDENT-OFF* */
2291 VLIB_CLI_COMMAND (pcap_dispatch_trace_command, static) = {
2292  .path = "pcap dispatch trace",
2293  .short_help =
2294  "pcap dispatch trace [on|off] [max <nn>] [file <name>] [status]\n"
2295  " [buffer-trace <input-node-name> <nn>]",
2296  .function = pcap_dispatch_trace_command_fn,
2297 };
2298 /* *INDENT-ON* */
2299 
2300 /*
2301  * fd.io coding-style-patch-verification: ON
2302  *
2303  * Local Variables:
2304  * eval: (c-set-style "gnu")
2305  * End:
2306  */
u32 * next_nodes
Definition: node.h:358
static void elog_enable_disable(elog_main_t *em, int is_enabled)
Enable or disable event logging.
Definition: elog.h:220
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
clib_error_t * vlib_call_all_main_loop_exit_functions(vlib_main_t *vm)
Definition: init.c:87
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:168
uword * pending_rpc_requests
Definition: main.h:220
vlib_main_t vlib_global_main
Definition: main.c:1850
f64 time
Absolute time as floating point number in seconds.
Definition: elog.h:67
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.
u16 vector_size
Definition: node.h:344
u32 max_clock
Maximum clock cycle for an invocation.
Definition: node.h:501
u32 next_frame_index
Start of next frames for this node.
Definition: node.h:515
static clib_error_t * show_frame_stats(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:238
#define hash_set(h, key, value)
Definition: hash.h:255
char * file_name
File name of pcap output.
Definition: pcap.h:162
u32 flags
Definition: vhost_user.h:115
vlib_node_type_t
Definition: node.h:69
#define clib_min(x, y)
Definition: clib.h:295
clib_error_t * vlib_call_all_main_loop_enter_functions(vlib_main_t *vm)
Definition: init.c:80
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:89
static void vlib_next_frame_change_ownership(vlib_main_t *vm, vlib_node_runtime_t *node_runtime, u32 next_index)
Definition: main.c:268
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:74
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:299
u32 interrupt_threshold_vector_length
Definition: node.h:741
vlib_process_t ** processes
Definition: node.h:762
static uword vlib_process_bootstrap(uword _a)
Definition: main.c:1417
format_function_t format_vlib_node_name
Definition: node_funcs.h:1141
vlib_node_runtime_t node_runtime
Definition: node.h:576
a
Definition: bitmap.h:538
u32 n_suspends
Definition: node.h:604
#define VLIB_PENDING_FRAME_NO_NEXT_FRAME
Definition: node.h:484
u32 n_packets_to_capture
Number of packets to capture.
Definition: pcap.h:165
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:136
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:351
uword * processing_rpc_requests
Definition: main.h:221
#define VLIB_PCAP_MAJOR_VERSION
Definition: main.h:378
vlib_trace_node_t * nodes
Definition: trace.h:86
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:897
static clib_error_t * elog_save_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:699
int elog_post_mortem_dump
Definition: main.h:202
uword dispatch_pcap_enable
Definition: main.h:139
#define PREDICT_TRUE(x)
Definition: clib.h:112
uword random_seed
Definition: main.h:170
unsigned long u64
Definition: types.h:89
static void vlib_increment_main_loop_counter(vlib_main_t *vm)
Definition: main.h:334
elog_time_stamp_t init_time
Timestamps.
Definition: elog.h:172
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
void clib_random_buffer_init(clib_random_buffer_t *b, uword seed)
Definition: random_buffer.c:62
#define NULL
Definition: clib.h:58
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 index
Definition: node.h:304
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:232
static void dummy_queue_signal_callback(vlib_main_t *vm)
Definition: main.c:1883
u32 current_process_index
Definition: node.h:765
static void vlib_process_update_stats(vlib_main_t *vm, vlib_process_t *p, uword n_calls, uword n_vectors, uword n_clocks, uword n_ticks)
Definition: main.c:672
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:98
static void vlib_process_sync_stats(vlib_main_t *vm, vlib_process_t *p, uword n_calls, uword n_vectors, uword n_clocks, uword n_ticks)
Definition: main.c:563
u32 thread_index
Definition: main.h:179
static_always_inline uword vlib_process_startup(vlib_main_t *vm, vlib_process_t *p, vlib_frame_t *f)
Definition: main.c:1444
u32 main_loop_exit_set
Definition: main.h:98
static u64 dispatch_pending_node(vlib_main_t *vm, uword pending_frame_index, u64 last_time_stamp)
Definition: main.c:1289
static vlib_frame_t * vlib_get_frame(vlib_main_t *vm, vlib_frame_t *f)
Definition: node_funcs.h:216
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:525
static u64 clib_cpu_time_now(void)
Definition: time.h:75
u8 buffer_pool_index
index of buffer pool this buffer belongs.
Definition: buffer.h:144
elog_track_t elog_track
Definition: threads.h:100
u32 clocks_since_last_overflow
Number of clock cycles.
Definition: node.h:499
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:564
int i
u32 recycle_count
Used by L2 path recycle code.
Definition: buffer.h:154
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
static void elog_show_buffer_internal(vlib_main_t *vm, u32 n_events_to_show)
Definition: main.c:834
#define VLIB_MAIN_LOOP_EXIT_CLI
Definition: main.h:105
void clib_longjmp(clib_longjmp_t *save, uword return_value)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
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:95
static clib_error_t * elog_show_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:862
u8 * format_elog_event(u8 *s, va_list *va)
Definition: elog.c:296
clib_time_t clib_time
Definition: main.h:65
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:450
clib_spinlock_t pending_interrupt_lock
Definition: node.h:735
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:267
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
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:280
unsigned char u8
Definition: types.h:56
static uword vlib_process_stack_is_valid(vlib_process_t *p)
Definition: main.c:1403
#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:344
u8 state
Definition: node.h:332
u16 thread_index
thread this node runs on
Definition: node.h:543
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:204
static void vlib_worker_thread_barrier_check(void)
Definition: threads.h:390
u32 * pending_interrupt_node_runtime_indices
Definition: node.h:734
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:520
static void vlib_main_loop(vlib_main_t *vm)
Definition: main.c:1839
#define foreach_weak_reference_stub
Definition: main.c:1887
vlib_trace_header_t ** trace_buffer_pool
Definition: trace.h:72
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
#define static_always_inline
Definition: clib.h:99
PCAP main state data structure.
Definition: pcap.h:156
u32 trace_enable
Definition: trace.h:83
clib_spinlock_t lock
spinlock to protect e.g.
Definition: pcap.h:159
#define VLIB_FRAME_NO_APPEND
Definition: node.h:442
vlib_node_function_t * function
Node function to call.
Definition: node.h:491
void elog_init(elog_main_t *em, u32 n_events)
Definition: elog.c:493
#define VLIB_FRAME_MAGIC
#define always_inline
Definition: clib.h:98
u32 main_loop_vectors_processed
Definition: main.h:80
#define VLIB_INVALID_NODE_INDEX
Definition: node.h:398
u16 log2_n_stack_bytes
Definition: node.h:599
vlib_node_t ** nodes
Definition: node.h:721
u32 vectors_since_last_overflow
Number of vector elements processed by this node.
Definition: node.h:509
vlib_frame_t * frame
Definition: main.c:1412
void di(unformat_input_t *i)
Definition: unformat.c:163
#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:181
#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:992
#define VLIB_FRAME_ALIGN
Definition: node.h:402
u64 perf_counter_vectors
Definition: node.h:262
u64 perf_counter_ticks
Definition: node.h:261
static uword vlib_timing_wheel_data_is_timed_event(u32 d)
Definition: node.h:695
#define VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE
Definition: node.h:328
#define VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES
Definition: buffer.h:443
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
Definition: node.h:590
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:242
unsigned int u32
Definition: types.h:88
u64 cpu_time_main_loop_start
Definition: main.h:74
vlib_node_runtime_t * nodes_by_type[VLIB_N_NODE_TYPE]
Definition: node.h:731
static u32 vlib_frame_bytes(u32 n_scalar_bytes, u32 n_vector_bytes)
Definition: main.c:58
#define VLIB_MAIN_LOOP_EXIT_NONE
Definition: main.h:102
clib_error_t * vlib_node_main_init(vlib_main_t *vm)
Definition: node.c:631
#define VLIB_FRAME_SIZE
Definition: node.h:401
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:264
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, uword n_ticks)
Definition: main.c:614
u8 * pcap_buffer
Definition: main.h:140
#define VLIB_PROCESS_IS_RUNNING
Definition: node.h:596
#define VLIB_PROCESS_RETURN_LONGJMP_RETURN
Definition: node.h:581
u64 max_clock_n
Definition: node.h:260
int callbacks_registered
Definition: buffer.h:458
unformat_function_t unformat_line_input
Definition: format.h:282
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:57
u32 calls_since_last_overflow
Number of calls.
Definition: node.h:507
char * name
Definition: main.h:111
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:36
#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:511
static clib_error_t * elog_write_file(elog_main_t *em, char *clib_file, int flush_ring)
Definition: elog.h:532
u32 next_frame_index
Definition: node.h:481
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:743
vlib_node_stats_t stats_total
Definition: node.h:294
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:416
u16 state
Input node state.
Definition: node.h:533
static u8 * format_buffer_metadata(u8 *s, va_list *args)
Definition: main.c:969
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:114
format_function_t format_vlib_trace
Definition: trace.h:92
vlib_signal_timed_event_data_t * signal_timed_event_data_pool
Definition: node.h:752
u16 frame_flags
Definition: node.h:408
#define VLIB_FRAME_IS_ALLOCATED
Definition: node.h:449
#define VLIB_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:438
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:1099
u32 n_alloc_frames
Definition: node.h:561
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:190
static clib_error_t * pcap_dispatch_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:2232
static uword vlib_timing_wheel_data_get_index(u32 d)
Definition: node.h:713
u32 *TW() tw_timer_expire_timers_vec(TWT(tw_timer_wheel) *tw, f64 now, u32 *vec)
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
elog_event_type_t * node_return_elog_event_types
Definition: main.h:165
#define TWT(a)
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
Definition: main.c:210
u32 polling_threshold_vector_length
Definition: node.h:740
u64 * n_vectors_by_next_node
Definition: node.h:367
#define PREDICT_FALSE(x)
Definition: clib.h:111
u32 perf_counter_ticks_since_last_overflow
Perf counter ticks.
Definition: node.h:512
f64 seconds_per_clock
Definition: time.h:57
void elog_post_mortem_dump(void)
Definition: main.c:736
u8 protocol_hint
Definition: node.h:338
vlib_frame_t * frame
Definition: node.h:478
u32 node_index
Node index.
Definition: node.h:518
#define foreach_vlib_main(body)
Definition: threads.h:235
uword * init_functions_called
Definition: main.h:176
#define VLIB_ELOG_MAIN_LOOP
Definition: main.h:58
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:37
#define VLIB_PROCESS_STACK_MAGIC
Definition: node.h:647
#define VLIB_PROCESS_RESUME_LONGJMP_RESUME
Definition: node.h:587
void clib_time_init(clib_time_t *c)
Definition: time.c:178
uword * frame_size_hash
Definition: node.h:777
void elog_alloc(elog_main_t *em, u32 n_events)
Definition: elog.c:479
clib_error_t * vlibmemory_init(vlib_main_t *vm)
Definition: memory_api.c:936
volatile u32 queue_signal_pending
Definition: main.h:190
int perf_counter_id
Definition: main.h:91
static vlib_frame_t * vlib_frame_alloc_to_node(vlib_main_t *vm, u32 to_node_index, u32 frame_flags)
Definition: main.c:115
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:139
clib_error_t * map_api_segment_init(vlib_main_t *vm)
Definition: memory_api.c:482
u8 * name
Definition: node.h:288
static u64 dispatch_process(vlib_main_t *vm, vlib_process_t *p, vlib_frame_t *f, u64 last_time_stamp)
Definition: main.c:1475
u32 wraps
Definition: main.c:55
u64(* vlib_node_runtime_perf_counter_cb)(struct vlib_main_t *)
Definition: main.h:90
u32 owner_node_index
Definition: node.h:378
void vlib_register_all_static_nodes(vlib_main_t *vm)
Definition: node.c:540
#define VLIB_EARLY_CONFIG_FUNCTION(x, n,...)
Definition: init.h:216
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:1029
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u8 inline_event_data[64 - 3 *sizeof(u32) - 2 *sizeof(u16)]
Definition: node.h:686
u32 flow_id
Generic flow identifier.
Definition: buffer.h:127
svmdb_client_t * c
u16 n_vectors
Definition: node.h:420
u32 runtime_index
Definition: node.h:307
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:301
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:1640
u32 node_runtime_index
Definition: node.h:475
vlib_pending_frame_t * pending_frames
Definition: node.h:747
int vlib_frame_queue_dequeue(vlib_main_t *vm, vlib_frame_queue_main_t *fqm)
Definition: threads.c:1581
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
clib_error_t * vpe_api_init(vlib_main_t *vm)
Definition: api.c:556
#define VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:317
#define clib_warning(format, args...)
Definition: error.h:59
#define VLIB_PROCESS_RESUME_PENDING
Definition: node.h:593
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:89
u32 perf_counter_vectors_since_last_overflow
Perf counter vectors.
Definition: node.h:513
#define VLIB_BUFFER_TRACE_TRAJECTORY
Compile time buffer trajectory tracing option Turn this on if you run into "bad monkey" contexts...
Definition: buffer.h:486
elog_main_t elog_main
Definition: main.h:157
clib_error_t * vlib_buffer_main_init(struct vlib_main_t *vm)
Definition: buffer.c:907
#define VLIB_FRAME_PENDING
Definition: node.h:452
static u32 vlib_frame_vector_byte_offset(u32 scalar_size)
Definition: node_funcs.h:233
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:452
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:442
clib_error_t * pcap_write(pcap_main_t *pm)
Write PCAP file.
Definition: pcap.c:89
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:241
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:564
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
#define VLIB_PCAP_MINOR_VERSION
Definition: main.h:379
#define never_inline
Definition: clib.h:95
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
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:537
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:311
#define ASSERT(truth)
u64 last_cpu_time
Definition: time.h:50
static u64 vlib_node_runtime_perf_counter(vlib_main_t *vm)
Definition: main.c:664
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:326
#define ELOG_TRACK_DATA(em, f, track)
Definition: elog.h:478
vlib_frame_t * frame
Definition: node.h:429
uword event_ring_size
Power of 2 number of elements in ring.
Definition: elog.h:145
u16 flags
Definition: node.h:411
u32 main_loop_nodes_processed
Definition: main.h:81
u64 cpu
CPU cycle counter.
Definition: elog.h:126
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:130
#define clib_error_report(e)
Definition: error.h:113
vlib_trace_main_t trace_main
Definition: main.h:135
u8 * format_vnet_buffer_opaque(u8 *s, va_list *args)
Definition: main.c:953
u8 * vnet_trace_dummy
Definition: trace.c:43
u8 * format_vnet_buffer_opaque2(u8 *s, va_list *args)
Definition: main.c:962
static uword pointer_to_uword(const void *p)
Definition: types.h:131
u8 n_add_refs
Number of additional references to this buffer.
Definition: buffer.h:142
#define A(x)
Definition: main.c:989
void(* queue_signal_callback)(struct vlib_main_t *)
Definition: main.h:192
void vlib_gdb_show_event_log(void)
Definition: main.c:891
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static_always_inline uword vlib_process_resume(vlib_process_t *p)
Definition: main.c:1462
#define VLIB_FRAME_OWNER
Definition: node.h:446
void vlib_node_sync_stats(vlib_main_t *vm, vlib_node_t *n)
Definition: main.c:577
#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:1901
#define unformat_parse_error(input)
Definition: format.h:268
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:156
pcap_packet_type_t packet_type
Packet type.
Definition: pcap.h:168
void vlib_worker_loop(vlib_main_t *vm)
Definition: main.c:1845
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, uword n_ticks)
Definition: main.c:538
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:72
static clib_error_t * pcap_dispatch_trace_command_internal(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd, int rx_tx)
Definition: main.c:2052
void vl_api_send_pending_rpc_requests(vlib_main_t *)
Definition: main.c:1634
#define clib_mem_alloc_aligned_no_fail(size, align)
Definition: mem.h:166
CJ_GLOBAL_LOG_PROTOTYPE
Definition: main.c:49
u32 * data_from_advancing_timing_wheel
Definition: node.h:755
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:774
vlib_pending_frame_t * suspended_process_frames
Definition: node.h:768
vlib_node_main_t node_main
Definition: main.h:129
static u32 * vlib_frame_find_magic(vlib_frame_t *f, vlib_node_t *node)
Definition: main.c:83
u64 uword
Definition: types.h:112
u32 owner_next_index
Definition: node.h:378
u8 vector_size
Definition: node.h:417
vlib_next_frame_t * next_frames
Definition: node.h:744
static clib_error_t * elog_stop(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:762
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:94
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define VLIB_FRAME_TRACE
Definition: node.h:458
u32 stop_timer_handle
Definition: node.h:629
clib_error_t * vlib_call_all_init_functions(vlib_main_t *vm)
Definition: init.c:67
#define VLIB_FRAME_SIZE_EXTRA
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:1147
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:1557
vlib_frame_size_t * frame_sizes
Definition: node.h:780
u64 resume_clock_interval
Definition: node.h:626
static void add_trajectory_trace(vlib_buffer_t *b, u32 node_index)
Definition: main.c:933
u16 flags
Definition: node.h:589
elog_event_type_t * node_call_elog_event_types
Definition: main.h:164
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:140
vlib_node_type_t type
Definition: node.h:301
static vlib_process_t * vlib_get_process_from_node(vlib_main_t *vm, vlib_node_t *node)
Definition: node_funcs.h:208
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:291
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1470
vlib_node_state_t
Definition: node.h:274
pcap_main_t dispatch_pcap_main
Definition: main.h:138
u64 init_cpu_time
Definition: time.h:62
u32 TW() tw_timer_start(TWT(tw_timer_wheel) *tw, u32 user_id, u32 timer_id, u64 interval)
Start a Tw Timer.
u32 suspended_process_frame_index
Definition: node.h:601
static void validate_frame_magic(vlib_main_t *vm, vlib_frame_t *f, vlib_node_t *n, uword next_index)
Definition: main.c:342
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
vlib_buffer_main_t buffer_main
Definition: buffer.c:56
static clib_error_t * vlib_main_configure(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:1853
u8 data[0]
Packet data.
Definition: buffer.h:176
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:59
static clib_error_t * vlib_cli_elog_clear(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:682
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT
Definition: node.h:591
#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:579
u16 flags
Copy of main node flags.
Definition: node.h:531
u32 node_runtime_index
Definition: node.h:432
u32 n_total_events
Total number of events in buffer.
Definition: elog.h:135
u8 scalar_size
Definition: node.h:414
clib_longjmp_t main_loop_exit
Definition: main.h:101
clib_longjmp_t resume_longjmp
Definition: node.h:585
void clib_mem_trace(int enable)
Definition: mem_dlmalloc.c:405
static clib_error_t * elog_resize(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:802
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:145
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:326
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
#define TW(a)
clib_error_t * vlib_map_stat_segment_init(void)
Definition: stat_segment.c:228
static u32 vlib_timing_wheel_data_set_suspended_process(u32 i)
Definition: node.h:701
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:117
volatile void(* worker_thread_main_loop_callback)(struct vlib_main_t *)
Definition: main.h:196
void vlib_start_process(vlib_main_t *vm, uword process_index)
Definition: main.c:1549
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:762
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:82
void * timing_wheel
Definition: node.h:750
u8 * format_vnet_buffer_flags(u8 *s, va_list *args)
Definition: main.c:945
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:62
u32 trace_index
Specifies index into trace buffer if VLIB_PACKET_IS_TRACED flag is set.
Definition: buffer.h:151
clib_random_buffer_t random_buffer
Definition: main.h:173
static clib_error_t * elog_restart(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:782
#define VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE
Definition: node.h:329
vlib_buffer_free_list_index_t vlib_buffer_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
Definition: buffer.c:426
u8 *(* validate_frame)(struct vlib_main_t *vm, struct vlib_node_runtime_t *, struct vlib_frame_t *f)
Definition: node.h:388
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
Definition: defs.h:46
clib_error_t * main_loop_error
Definition: main.h:108
vlib_process_t * process
Definition: main.c:1411
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:537
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:71
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
#define VLIB_FRAME_FREE_AFTER_DISPATCH
Definition: node.h:455
clib_error_t * vlib_thread_init(vlib_main_t *vm)
Definition: threads.c:237
u32 vectors_since_last_overflow
Definition: node.h:461
u32 max_clock_n
Number of vectors in the recorded max_clock.
Definition: node.h:504
#define VLIB_PROCESS_RETURN_LONGJMP_SUSPEND
Definition: node.h:582
vlib_buffer_free_list_index_t free_list_index
Definition: buffer.h:160