FD.io VPP  v21.06
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  ASSERT (vm == vlib_get_main ());
126 
127  to_node = vlib_get_node (vm, to_node_index);
128 
129  scalar_size = to_node->scalar_size;
130  vector_size = to_node->vector_size;
131 
132  fs = get_frame_size_info (nm, scalar_size, vector_size);
133  n = vlib_frame_bytes (scalar_size, vector_size);
134  if ((l = vec_len (fs->free_frames)) > 0)
135  {
136  /* Allocate from end of free list. */
137  f = fs->free_frames[l - 1];
138  _vec_len (fs->free_frames) = l - 1;
139  }
140  else
141  {
143  }
144 
145  /* Poison frame when debugging. */
146  if (CLIB_DEBUG > 0)
147  clib_memset (f, 0xfe, n);
148 
149  /* Insert magic number. */
150  {
151  u32 *magic;
152 
153  magic = vlib_frame_find_magic (f, to_node);
154  *magic = VLIB_FRAME_MAGIC;
155  }
156 
157  f->frame_flags = VLIB_FRAME_IS_ALLOCATED | frame_flags;
158  f->n_vectors = 0;
159  f->scalar_size = scalar_size;
160  f->vector_size = vector_size;
161  f->flags = 0;
162 
163  fs->n_alloc_frames += 1;
164 
165  return f;
166 }
167 
168 /* Allocate a frame for from FROM_NODE to TO_NODE via TO_NEXT_INDEX.
169  Returns frame index. */
170 static vlib_frame_t *
172  u32 to_next_index)
173 {
174  vlib_node_t *from_node;
175 
176  from_node = vlib_get_node (vm, from_node_runtime->node_index);
177  ASSERT (to_next_index < vec_len (from_node->next_nodes));
178 
179  return vlib_frame_alloc_to_node (vm, from_node->next_nodes[to_next_index],
180  /* frame_flags */ 0);
181 }
182 
183 vlib_frame_t *
185 {
186  vlib_frame_t *f = vlib_frame_alloc_to_node (vm, to_node_index,
187  /* frame_flags */
189  return vlib_get_frame (vm, f);
190 }
191 
192 static inline void
194 {
195  if (CLIB_DEBUG > 0)
196  {
197  int i;
199 
200  /* Check for bad buffer index values */
201  for (i = 0; i < f->n_vectors; i++)
202  {
203  if (from[i] == 0)
204  {
205  clib_warning ("BUG: buffer index 0 at index %d", i);
206  ASSERT (0);
207  }
208  else if (from[i] == 0xfefefefe)
209  {
210  clib_warning ("BUG: frame poison pattern at index %d", i);
211  ASSERT (0);
212  }
213  }
214  }
215 }
216 
217 void
219 {
221  vlib_node_t *to_node;
222 
223  if (f->n_vectors == 0)
224  return;
225 
226  ASSERT (vm == vlib_get_main ());
227 
229 
230  to_node = vlib_get_node (vm, to_node_index);
231 
232  vec_add2 (vm->node_main.pending_frames, p, 1);
233 
235  p->frame = vlib_get_frame (vm, f);
236  p->node_runtime_index = to_node->runtime_index;
238 }
239 
240 /* Free given frame. */
241 void
243 {
244  vlib_node_main_t *nm = &vm->node_main;
245  vlib_node_t *node;
246  vlib_frame_size_t *fs;
247 
248  ASSERT (vm == vlib_get_main ());
250 
251  node = vlib_get_node (vm, r->node_index);
252  fs = get_frame_size_info (nm, node->scalar_size, node->vector_size);
253 
255 
256  /* No next frames may point to freed frame. */
257  if (CLIB_DEBUG > 0)
258  {
259  vlib_next_frame_t *nf;
260  vec_foreach (nf, vm->node_main.next_frames) ASSERT (nf->frame != f);
261  }
262 
264 
265  vec_add1 (fs->free_frames, f);
266  ASSERT (fs->n_alloc_frames > 0);
267  fs->n_alloc_frames -= 1;
268 }
269 
270 static clib_error_t *
272  unformat_input_t * input, vlib_cli_command_t * cmd)
273 {
274  vlib_node_main_t *nm = &vm->node_main;
275  vlib_frame_size_t *fs;
276 
277  vlib_cli_output (vm, "%=6s%=12s%=12s", "Size", "# Alloc", "# Free");
278  vec_foreach (fs, nm->frame_sizes)
279  {
280  u32 n_alloc = fs->n_alloc_frames;
281  u32 n_free = vec_len (fs->free_frames);
282 
283  if (n_alloc + n_free > 0)
284  vlib_cli_output (vm, "%=6d%=12d%=12d",
285  fs - nm->frame_sizes, n_alloc, n_free);
286  }
287 
288  return 0;
289 }
290 
291 /* *INDENT-OFF* */
292 VLIB_CLI_COMMAND (show_frame_stats_cli, static) = {
293  .path = "show vlib frame-allocation",
294  .short_help = "Show node dispatch frame statistics",
295  .function = show_frame_stats,
296 };
297 /* *INDENT-ON* */
298 
299 /* Change ownership of enqueue rights to given next node. */
300 static void
302  vlib_node_runtime_t * node_runtime,
303  u32 next_index)
304 {
305  vlib_node_main_t *nm = &vm->node_main;
306  vlib_next_frame_t *next_frame;
307  vlib_node_t *node, *next_node;
308 
309  node = vec_elt (nm->nodes, node_runtime->node_index);
310 
311  /* Only internal & input nodes are allowed to call other nodes. */
313  || node->type == VLIB_NODE_TYPE_INPUT
314  || node->type == VLIB_NODE_TYPE_PROCESS);
315 
316  ASSERT (vec_len (node->next_nodes) == node_runtime->n_next_nodes);
317 
318  next_frame =
319  vlib_node_runtime_get_next_frame (vm, node_runtime, next_index);
320  next_node = vec_elt (nm->nodes, node->next_nodes[next_index]);
321 
322  if (next_node->owner_node_index != VLIB_INVALID_NODE_INDEX)
323  {
324  /* Get frame from previous owner. */
325  vlib_next_frame_t *owner_next_frame;
327 
328  owner_next_frame =
330  next_node->owner_node_index,
331  next_node->owner_next_index);
332 
333  /* Swap target next frame with owner's. */
334  tmp = owner_next_frame[0];
335  owner_next_frame[0] = next_frame[0];
336  next_frame[0] = tmp;
337 
338  /*
339  * If next_frame is already pending, we have to track down
340  * all pending frames and fix their next_frame_index fields.
341  */
342  if (next_frame->flags & VLIB_FRAME_PENDING)
343  {
345  if (next_frame->frame != NULL)
346  {
347  vec_foreach (p, nm->pending_frames)
348  {
349  if (p->frame == next_frame->frame)
350  {
351  p->next_frame_index =
352  next_frame - vm->node_main.next_frames;
353  }
354  }
355  }
356  }
357  }
358  else
359  {
360  /* No previous owner. Take ownership. */
361  next_frame->flags |= VLIB_FRAME_OWNER;
362  }
363 
364  /* Record new owner. */
365  next_node->owner_node_index = node->index;
366  next_node->owner_next_index = next_index;
367 
368  /* Now we should be owner. */
369  ASSERT (next_frame->flags & VLIB_FRAME_OWNER);
370 }
371 
372 /* Make sure that magic number is still there.
373  Otherwise, it is likely that caller has overrun frame arguments. */
374 always_inline void
377 {
378  vlib_node_t *next_node = vlib_get_node (vm, n->next_nodes[next_index]);
379  u32 *magic = vlib_frame_find_magic (f, next_node);
380  ASSERT (VLIB_FRAME_MAGIC == magic[0]);
381 }
382 
383 vlib_frame_t *
386  u32 next_index, u32 allocate_new_next_frame)
387 {
388  vlib_frame_t *f;
389  vlib_next_frame_t *nf;
390  u32 n_used;
391 
392  nf = vlib_node_runtime_get_next_frame (vm, node, next_index);
393 
394  /* Make sure this next frame owns right to enqueue to destination frame. */
395  if (PREDICT_FALSE (!(nf->flags & VLIB_FRAME_OWNER)))
396  vlib_next_frame_change_ownership (vm, node, next_index);
397 
398  /* ??? Don't need valid flag: can use frame_index == ~0 */
400  {
401  nf->frame = vlib_frame_alloc (vm, node, next_index);
403  }
404 
405  f = nf->frame;
406 
407  /* Has frame been removed from pending vector (e.g. finished dispatching)?
408  If so we can reuse frame. */
409  if ((nf->flags & VLIB_FRAME_PENDING)
410  && !(f->frame_flags & VLIB_FRAME_PENDING))
411  {
412  nf->flags &= ~VLIB_FRAME_PENDING;
413  f->n_vectors = 0;
414  f->flags = 0;
415  }
416 
417  /* Allocate new frame if current one is marked as no-append or
418  it is already full. */
419  n_used = f->n_vectors;
420  if (n_used >= VLIB_FRAME_SIZE || (allocate_new_next_frame && n_used > 0) ||
422  {
423  /* Old frame may need to be freed after dispatch, since we'll have
424  two redundant frames from node -> next node. */
426  {
427  vlib_frame_t *f_old = vlib_get_frame (vm, nf->frame);
429  }
430 
431  /* Allocate new frame to replace full one. */
432  f = nf->frame = vlib_frame_alloc (vm, node, next_index);
433  n_used = f->n_vectors;
434  }
435 
436  /* Should have free vectors in frame now. */
437  ASSERT (n_used < VLIB_FRAME_SIZE);
438 
439  if (CLIB_DEBUG > 0)
440  {
441  validate_frame_magic (vm, f,
442  vlib_get_node (vm, node->node_index), next_index);
443  }
444 
445  return f;
446 }
447 
448 static void
450  vlib_node_runtime_t * rt,
451  u32 next_index, u32 n_vectors_left)
452 {
453  vlib_node_main_t *nm = &vm->node_main;
454  vlib_next_frame_t *nf;
455  vlib_frame_t *f;
456  vlib_node_runtime_t *next_rt;
457  vlib_node_t *next_node;
458  u32 n_before, n_after;
459 
460  nf = vlib_node_runtime_get_next_frame (vm, rt, next_index);
461  f = vlib_get_frame (vm, nf->frame);
462 
463  ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
464 
466 
467  n_after = VLIB_FRAME_SIZE - n_vectors_left;
468  n_before = f->n_vectors;
469 
470  ASSERT (n_after >= n_before);
471 
473  nf->node_runtime_index);
474  next_node = vlib_get_node (vm, next_rt->node_index);
475  if (n_after > 0 && next_node->validate_frame)
476  {
477  u8 *msg = next_node->validate_frame (vm, rt, f);
478  if (msg)
479  {
480  clib_warning ("%v", msg);
481  ASSERT (0);
482  }
483  vec_free (msg);
484  }
485 }
486 
487 void
490  u32 next_index, u32 n_vectors_left)
491 {
492  vlib_node_main_t *nm = &vm->node_main;
493  vlib_next_frame_t *nf;
494  vlib_frame_t *f;
495  u32 n_vectors_in_frame;
496 
497  if (CLIB_DEBUG > 0)
498  vlib_put_next_frame_validate (vm, r, next_index, n_vectors_left);
499 
500  nf = vlib_node_runtime_get_next_frame (vm, r, next_index);
501  f = vlib_get_frame (vm, nf->frame);
502 
503  /* Make sure that magic number is still there. Otherwise, caller
504  has overrun frame meta data. */
505  if (CLIB_DEBUG > 0)
506  {
508  validate_frame_magic (vm, f, node, next_index);
509  }
510 
511  /* Convert # of vectors left -> number of vectors there. */
512  ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
513  n_vectors_in_frame = VLIB_FRAME_SIZE - n_vectors_left;
514 
515  f->n_vectors = n_vectors_in_frame;
516 
517  /* If vectors were added to frame, add to pending vector. */
518  if (PREDICT_TRUE (n_vectors_in_frame > 0))
519  {
521  u32 v0, v1;
522 
524 
525  if (!(f->frame_flags & VLIB_FRAME_PENDING))
526  {
527  __attribute__ ((unused)) vlib_node_t *node;
528  vlib_node_t *next_node;
529  vlib_node_runtime_t *next_runtime;
530 
531  node = vlib_get_node (vm, r->node_index);
532  next_node = vlib_get_next_node (vm, r->node_index, next_index);
533  next_runtime = vlib_node_get_runtime (vm, next_node->index);
534 
535  vec_add2 (nm->pending_frames, p, 1);
536 
537  p->frame = nf->frame;
539  p->next_frame_index = nf - nm->next_frames;
540  nf->flags |= VLIB_FRAME_PENDING;
542 
543  /*
544  * If we're going to dispatch this frame on another thread,
545  * force allocation of a new frame. Otherwise, we create
546  * a dangling frame reference. Each thread has its own copy of
547  * the next_frames vector.
548  */
549  if (0 && r->thread_index != next_runtime->thread_index)
550  {
551  nf->frame = NULL;
553  }
554  }
555 
556  /* Copy trace flag from next_frame and from runtime. */
557  nf->flags |=
558  (nf->flags & VLIB_NODE_FLAG_TRACE) | (r->
560 
562  v1 = v0 + n_vectors_in_frame;
564  if (PREDICT_FALSE (v1 < v0))
565  {
567  vec_elt (node->n_vectors_by_next_node, next_index) += v0;
568  }
569  }
570 }
571 
572 /* Sync up runtime (32 bit counters) and main node stats (64 bit counters). */
573 void
575  uword n_calls, uword n_vectors,
576  uword n_clocks)
577 {
578  n->stats_total.calls += n_calls + r->calls_since_last_overflow;
579  n->stats_total.vectors += n_vectors + r->vectors_since_last_overflow;
580  n->stats_total.clocks += n_clocks + r->clocks_since_last_overflow;
583 
587 }
588 
589 void
591  uword n_calls, uword n_vectors, uword n_clocks)
592 {
593  vlib_node_t *n = vlib_get_node (vm, r->node_index);
594  vlib_node_runtime_sync_stats_node (n, r, n_calls, n_vectors, n_clocks);
595 }
596 
597 always_inline void __attribute__ ((unused))
599  vlib_process_t * p,
600  uword n_calls, uword n_vectors, uword n_clocks)
601 {
602  vlib_node_runtime_t *rt = &p->node_runtime;
603  vlib_node_t *n = vlib_get_node (vm, rt->node_index);
604  vlib_node_runtime_sync_stats (vm, rt, n_calls, n_vectors, n_clocks);
605  n->stats_total.suspends += p->n_suspends;
606  p->n_suspends = 0;
607 }
608 
609 void
611 {
613 
614  if (n->type == VLIB_NODE_TYPE_PROCESS)
615  {
616  /* Nothing to do for PROCESS nodes except in main thread */
617  if (vm != vlib_get_first_main ())
618  return;
619 
622  p->n_suspends = 0;
623  rt = &p->node_runtime;
624  }
625  else
626  rt =
628  n->runtime_index);
629 
630  vlib_node_runtime_sync_stats (vm, rt, 0, 0, 0);
631 
632  /* Sync up runtime next frame vector counters with main node structure. */
633  {
634  vlib_next_frame_t *nf;
635  uword i;
636  for (i = 0; i < rt->n_next_nodes; i++)
637  {
638  nf = vlib_node_runtime_get_next_frame (vm, rt, i);
642  }
643  }
644 }
645 
649  uword n_calls,
650  uword n_vectors, uword n_clocks)
651 {
652  u32 ca0, ca1, v0, v1, cl0, cl1, r;
653 
654  cl0 = cl1 = node->clocks_since_last_overflow;
655  ca0 = ca1 = node->calls_since_last_overflow;
656  v0 = v1 = node->vectors_since_last_overflow;
657 
658  ca1 = ca0 + n_calls;
659  v1 = v0 + n_vectors;
660  cl1 = cl0 + n_clocks;
661 
662  node->calls_since_last_overflow = ca1;
663  node->clocks_since_last_overflow = cl1;
664  node->vectors_since_last_overflow = v1;
665 
666  node->max_clock_n = node->max_clock > n_clocks ?
667  node->max_clock_n : n_vectors;
668  node->max_clock = node->max_clock > n_clocks ? node->max_clock : n_clocks;
669 
670  r = vlib_node_runtime_update_main_loop_vector_stats (vm, node, n_vectors);
671 
672  if (PREDICT_FALSE (ca1 < ca0 || v1 < v0 || cl1 < cl0))
673  {
674  node->calls_since_last_overflow = ca0;
675  node->clocks_since_last_overflow = cl0;
676  node->vectors_since_last_overflow = v0;
677 
678  vlib_node_runtime_sync_stats (vm, node, n_calls, n_vectors, n_clocks);
679  }
680 
681  return r;
682 }
683 
684 always_inline void
686  vlib_process_t * p,
687  uword n_calls, uword n_vectors, uword n_clocks)
688 {
690  n_calls, n_vectors, n_clocks);
691 }
692 
693 static clib_error_t *
695  unformat_input_t * input, vlib_cli_command_t * cmd)
696 {
697  elog_reset_buffer (&vlib_global_main.elog_main);
698  return 0;
699 }
700 
701 /* *INDENT-OFF* */
702 VLIB_CLI_COMMAND (elog_clear_cli, static) = {
703  .path = "event-logger clear",
704  .short_help = "Clear the event log",
705  .function = vlib_cli_elog_clear,
706 };
707 /* *INDENT-ON* */
708 
709 #ifdef CLIB_UNIX
710 static clib_error_t *
712  unformat_input_t * input, vlib_cli_command_t * cmd)
713 {
714  elog_main_t *em = &vlib_global_main.elog_main;
715  char *file, *chroot_file;
716  clib_error_t *error = 0;
717 
718  if (!unformat (input, "%s", &file))
719  {
720  vlib_cli_output (vm, "expected file name, got `%U'",
721  format_unformat_error, input);
722  return 0;
723  }
724 
725  /* It's fairly hard to get "../oopsie" through unformat; just in case */
726  if (strstr (file, "..") || index (file, '/'))
727  {
728  vlib_cli_output (vm, "illegal characters in filename '%s'", file);
729  return 0;
730  }
731 
732  chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
733 
734  vec_free (file);
735 
736  vlib_cli_output (vm, "Saving %wd of %wd events to %s",
738  elog_buffer_capacity (em), chroot_file);
739 
741  error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
743  vec_free (chroot_file);
744  return error;
745 }
746 
747 void
749 {
751 
752  for (int i = 0; i < vec_len (vgm->post_mortem_callbacks); i++)
753  (vgm->post_mortem_callbacks[i]) ();
754 }
755 
756 /* *INDENT-OFF* */
757 VLIB_CLI_COMMAND (elog_save_cli, static) = {
758  .path = "event-logger save",
759  .short_help = "event-logger save <filename> (saves log in /tmp/<filename>)",
760  .function = elog_save_buffer,
761 };
762 /* *INDENT-ON* */
763 
764 static clib_error_t *
766  unformat_input_t * input, vlib_cli_command_t * cmd)
767 {
768  elog_main_t *em = &vlib_global_main.elog_main;
769 
771 
772  vlib_cli_output (vm, "Stopped the event logger...");
773  return 0;
774 }
775 
776 /* *INDENT-OFF* */
777 VLIB_CLI_COMMAND (elog_stop_cli, static) = {
778  .path = "event-logger stop",
779  .short_help = "Stop the event-logger",
780  .function = elog_stop,
781 };
782 /* *INDENT-ON* */
783 
784 static clib_error_t *
786  unformat_input_t * input, vlib_cli_command_t * cmd)
787 {
788  elog_main_t *em = &vlib_global_main.elog_main;
789 
791 
792  vlib_cli_output (vm, "Restarted the event logger...");
793  return 0;
794 }
795 
796 /* *INDENT-OFF* */
797 VLIB_CLI_COMMAND (elog_restart_cli, static) = {
798  .path = "event-logger restart",
799  .short_help = "Restart the event-logger",
800  .function = elog_restart,
801 };
802 /* *INDENT-ON* */
803 
804 static clib_error_t *
806  unformat_input_t * input, vlib_cli_command_t * cmd)
807 {
808  elog_main_t *em = &vlib_global_main.elog_main;
809  u32 tmp;
810 
811  /* Stop the parade */
812  elog_reset_buffer (em);
813 
814  if (unformat (input, "%d", &tmp))
815  {
816  elog_alloc (em, tmp);
818  }
819  else
820  return clib_error_return (0, "Must specify how many events in the ring");
821 
822  vlib_cli_output (vm, "Resized ring and restarted the event logger...");
823  return 0;
824 }
825 
826 /* *INDENT-OFF* */
827 VLIB_CLI_COMMAND (elog_resize_cli, static) = {
828  .path = "event-logger resize",
829  .short_help = "event-logger resize <nnn>",
830  .function = elog_resize_command_fn,
831 };
832 /* *INDENT-ON* */
833 
834 #endif /* CLIB_UNIX */
835 
836 static void
838 {
839  elog_main_t *em = &vlib_global_main.elog_main;
840  elog_event_t *e, *es;
841  f64 dt;
842 
843  /* Show events in VLIB time since log clock starts after VLIB clock. */
844  dt = (em->init_time.cpu - vm->clib_time.init_cpu_time)
846 
847  es = elog_peek_events (em);
848  vlib_cli_output (vm, "%d of %d events in buffer, logger %s", vec_len (es),
849  em->event_ring_size,
851  "running" : "stopped");
852  vec_foreach (e, es)
853  {
854  vlib_cli_output (vm, "%18.9f: %U",
855  e->time + dt, format_elog_event, em, e);
856  n_events_to_show--;
857  if (n_events_to_show == 0)
858  break;
859  }
860  vec_free (es);
861 
862 }
863 
864 static clib_error_t *
866  unformat_input_t * input, vlib_cli_command_t * cmd)
867 {
868  u32 n_events_to_show;
869  clib_error_t *error = 0;
870 
871  n_events_to_show = 250;
873  {
874  if (unformat (input, "%d", &n_events_to_show))
875  ;
876  else if (unformat (input, "all"))
877  n_events_to_show = ~0;
878  else
879  return unformat_parse_error (input);
880  }
881  elog_show_buffer_internal (vm, n_events_to_show);
882  return error;
883 }
884 
885 /* *INDENT-OFF* */
886 VLIB_CLI_COMMAND (elog_show_cli, static) = {
887  .path = "show event-logger",
888  .short_help = "Show event logger info",
889  .function = elog_show_buffer,
890 };
891 /* *INDENT-ON* */
892 
893 void
895 {
897 }
898 
899 static inline void
901  u32 node_index,
902  u64 time, u32 n_vectors, u32 is_return)
903 {
906  int enabled = evm->elog_trace_graph_dispatch |
908 
909  if (PREDICT_FALSE (enabled && n_vectors))
910  {
911  if (PREDICT_FALSE (!elog_is_enabled (em)))
912  {
913  evm->elog_trace_graph_dispatch = 0;
914  evm->elog_trace_graph_circuit = 0;
915  return;
916  }
917  if (PREDICT_TRUE
919  (evm->elog_trace_graph_circuit &&
920  node_index == evm->elog_trace_graph_circuit_node_index)))
921  {
922  elog_track (em,
923  /* event type */
924  vec_elt_at_index (is_return
927  node_index),
928  /* track */
929  (vm->thread_index ?
931  : &em->default_track),
932  /* data to log */ n_vectors);
933  }
934  }
935 }
936 
937 static inline void
939 {
940 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0
941  if (PREDICT_FALSE (b->trajectory_nb >= VLIB_BUFFER_TRACE_TRAJECTORY_MAX))
942  return;
943  b->trajectory_trace[b->trajectory_nb] = node_index;
944  b->trajectory_nb++;
945 #endif
946 }
947 
952  vlib_node_state_t dispatch_state,
953  vlib_frame_t * frame, u64 last_time_stamp)
954 {
955  uword n, v;
956  u64 t;
957  vlib_node_main_t *nm = &vm->node_main;
958  vlib_next_frame_t *nf;
959 
960  if (CLIB_DEBUG > 0)
961  {
962  vlib_node_t *n = vlib_get_node (vm, node->node_index);
963  ASSERT (n->type == type);
964  }
965 
966  /* Only non-internal nodes may be disabled. */
967  if (type != VLIB_NODE_TYPE_INTERNAL && node->state != dispatch_state)
968  {
970  return last_time_stamp;
971  }
972 
973  if ((type == VLIB_NODE_TYPE_PRE_INPUT || type == VLIB_NODE_TYPE_INPUT)
974  && dispatch_state != VLIB_NODE_STATE_INTERRUPT)
975  {
977  /* Only call node when count reaches zero. */
978  if (c)
979  {
980  node->input_main_loops_per_call = c - 1;
981  return last_time_stamp;
982  }
983  }
984 
985  /* Speculatively prefetch next frames. */
986  if (node->n_next_nodes > 0)
987  {
989  CLIB_PREFETCH (nf, 4 * sizeof (nf[0]), WRITE);
990  }
991 
992  vm->cpu_time_last_node_dispatch = last_time_stamp;
993 
995  last_time_stamp, frame ? frame->n_vectors : 0,
996  /* is_after */ 0);
997 
998  vlib_node_runtime_perf_counter (vm, node, frame, 0, last_time_stamp,
1000 
1001  /*
1002  * Turn this on if you run into
1003  * "bad monkey" contexts, and you want to know exactly
1004  * which nodes they've visited... See ixge.c...
1005  */
1006  if (VLIB_BUFFER_TRACE_TRAJECTORY && frame)
1007  {
1008  int i;
1009  u32 *from;
1010  from = vlib_frame_vector_args (frame);
1011  for (i = 0; i < frame->n_vectors; i++)
1012  {
1013  vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
1014  add_trajectory_trace (b, node->node_index);
1015  }
1016  if (PREDICT_TRUE (vm->dispatch_wrapper_fn == 0))
1017  n = node->function (vm, node, frame);
1018  else
1019  n = vm->dispatch_wrapper_fn (vm, node, frame);
1020  }
1021  else
1022  {
1023  if (PREDICT_TRUE (vm->dispatch_wrapper_fn == 0))
1024  n = node->function (vm, node, frame);
1025  else
1026  n = vm->dispatch_wrapper_fn (vm, node, frame);
1027  }
1028 
1029  t = clib_cpu_time_now ();
1030 
1031  vlib_node_runtime_perf_counter (vm, node, frame, n, t,
1033 
1034  vlib_elog_main_loop_event (vm, node->node_index, t, n, 1 /* is_after */ );
1035 
1036  vm->main_loop_vectors_processed += n;
1037  vm->main_loop_nodes_processed += n > 0;
1038 
1039  v = vlib_node_runtime_update_stats (vm, node,
1040  /* n_calls */ 1,
1041  /* n_vectors */ n,
1042  /* n_clocks */ t - last_time_stamp);
1043 
1044  /* When in adaptive mode and vector rate crosses threshold switch to
1045  polling mode and vice versa. */
1047  {
1048  /* *INDENT-OFF* */
1049  ELOG_TYPE_DECLARE (e) =
1050  {
1051  .function = (char *) __FUNCTION__,
1052  .format = "%s vector length %d, switching to %s",
1053  .format_args = "T4i4t4",
1054  .n_enum_strings = 2,
1055  .enum_strings = {
1056  "interrupt", "polling",
1057  },
1058  };
1059  /* *INDENT-ON* */
1060  struct
1061  {
1062  u32 node_name, vector_length, is_polling;
1063  } *ed;
1064 
1065  if ((dispatch_state == VLIB_NODE_STATE_INTERRUPT
1066  && v >= nm->polling_threshold_vector_length) &&
1067  !(node->flags &
1069  {
1070  vlib_node_t *n = vlib_get_node (vm, node->node_index);
1071  n->state = VLIB_NODE_STATE_POLLING;
1072  node->state = VLIB_NODE_STATE_POLLING;
1073  node->flags &=
1076  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] -= 1;
1077  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] += 1;
1078 
1079  if (PREDICT_FALSE (
1080  vlib_get_first_main ()->elog_trace_graph_dispatch))
1081  {
1083  + vm->thread_index;
1084 
1085  ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
1086  w->elog_track);
1087  ed->node_name = n->name_elog_string;
1088  ed->vector_length = v;
1089  ed->is_polling = 1;
1090  }
1091  }
1092  else if (dispatch_state == VLIB_NODE_STATE_POLLING
1093  && v <= nm->interrupt_threshold_vector_length)
1094  {
1095  vlib_node_t *n = vlib_get_node (vm, node->node_index);
1096  if (node->flags &
1098  {
1099  /* Switch to interrupt mode after dispatch in polling one more time.
1100  This allows driver to re-enable interrupts. */
1101  n->state = VLIB_NODE_STATE_INTERRUPT;
1102  node->state = VLIB_NODE_STATE_INTERRUPT;
1103  node->flags &=
1105  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] -= 1;
1106  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] += 1;
1107 
1108  }
1109  else
1110  {
1112  + vm->thread_index;
1113  node->flags |=
1115  if (PREDICT_FALSE (
1116  vlib_get_first_main ()->elog_trace_graph_dispatch))
1117  {
1118  ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
1119  w->elog_track);
1120  ed->node_name = n->name_elog_string;
1121  ed->vector_length = v;
1122  ed->is_polling = 0;
1123  }
1124  }
1125  }
1126  }
1127 
1128  return t;
1129 }
1130 
1131 static u64
1132 dispatch_pending_node (vlib_main_t * vm, uword pending_frame_index,
1133  u64 last_time_stamp)
1134 {
1135  vlib_node_main_t *nm = &vm->node_main;
1136  vlib_frame_t *f;
1137  vlib_next_frame_t *nf, nf_placeholder;
1139  vlib_frame_t *restore_frame;
1141 
1142  /* See comment below about dangling references to nm->pending_frames */
1143  p = nm->pending_frames + pending_frame_index;
1144 
1146  p->node_runtime_index);
1147 
1148  f = vlib_get_frame (vm, p->frame);
1150  {
1151  /* No next frame: so use placeholder on stack. */
1152  nf = &nf_placeholder;
1154  nf->frame = NULL;
1155  }
1156  else
1158 
1160 
1161  /* Force allocation of new frame while current frame is being
1162  dispatched. */
1163  restore_frame = NULL;
1164  if (nf->frame == p->frame)
1165  {
1166  nf->frame = NULL;
1169  restore_frame = p->frame;
1170  }
1171 
1172  /* Frame must be pending. */
1174  ASSERT (f->n_vectors > 0);
1175 
1176  /* Copy trace flag from next frame to node.
1177  Trace flag indicates that at least one vector in the dispatched
1178  frame is traced. */
1179  n->flags &= ~VLIB_NODE_FLAG_TRACE;
1180  n->flags |= (nf->flags & VLIB_FRAME_TRACE) ? VLIB_NODE_FLAG_TRACE : 0;
1181  nf->flags &= ~VLIB_FRAME_TRACE;
1182 
1183  last_time_stamp = dispatch_node (vm, n,
1185  VLIB_NODE_STATE_POLLING,
1186  f, last_time_stamp);
1187  /* Internal node vector-rate accounting, for summary stats */
1188  vm->internal_node_vectors += f->n_vectors;
1189  vm->internal_node_calls++;
1193 
1195 
1196  /* Frame is ready to be used again, so restore it. */
1197  if (restore_frame != NULL)
1198  {
1199  /*
1200  * We musn't restore a frame that is flagged to be freed. This
1201  * shouldn't happen since frames to be freed post dispatch are
1202  * those used when the to-node frame becomes full i.e. they form a
1203  * sort of queue of frames to a single node. If we get here then
1204  * the to-node frame and the pending frame *were* the same, and so
1205  * we removed the to-node frame. Therefore this frame is no
1206  * longer part of the queue for that node and hence it cannot be
1207  * it's overspill.
1208  */
1210 
1211  /*
1212  * NB: dispatching node n can result in the creation and scheduling
1213  * of new frames, and hence in the reallocation of nm->pending_frames.
1214  * Recompute p, or no supper. This was broken for more than 10 years.
1215  */
1216  p = nm->pending_frames + pending_frame_index;
1217 
1218  /*
1219  * p->next_frame_index can change during node dispatch if node
1220  * function decides to change graph hook up.
1221  */
1224 
1225  if (NULL == nf->frame)
1226  {
1227  /* no new frame has been assigned to this node, use the saved one */
1228  nf->frame = restore_frame;
1229  f->n_vectors = 0;
1230  }
1231  else
1232  {
1233  /* The node has gained a frame, implying packets from the current frame
1234  were re-queued to this same node. we don't need the saved one
1235  anymore */
1236  vlib_frame_free (vm, n, f);
1237  }
1238  }
1239  else
1240  {
1242  {
1244  vlib_frame_free (vm, n, f);
1245  }
1246  }
1247 
1248  return last_time_stamp;
1249 }
1250 
1253 {
1254  return p->stack[0] == VLIB_PROCESS_STACK_MAGIC;
1255 }
1256 
1257 typedef struct
1258 {
1263 
1264 /* Called in process stack. */
1265 static uword
1267 {
1269  vlib_main_t *vm;
1271  vlib_frame_t *f;
1272  vlib_process_t *p;
1273  uword n;
1274 
1276 
1277  vm = a->vm;
1278  p = a->process;
1280 
1281  f = a->frame;
1282  node = &p->node_runtime;
1283 
1284  n = node->function (vm, node, f);
1285 
1287 
1289  clib_longjmp (&p->return_longjmp, n);
1290 
1291  return n;
1292 }
1293 
1294 /* Called in main stack. */
1297 {
1299  uword r;
1300 
1301  a.vm = vm;
1302  a.process = p;
1303  a.frame = f;
1304 
1307  {
1310  (void *) p->stack + (1 << p->log2_n_stack_bytes));
1311  }
1312  else
1314 
1315  return r;
1316 }
1317 
1320 {
1321  uword r;
1327  {
1330  }
1331  else
1333  return r;
1334 }
1335 
1336 static u64
1338  vlib_process_t * p, vlib_frame_t * f, u64 last_time_stamp)
1339 {
1340  vlib_node_main_t *nm = &vm->node_main;
1341  vlib_node_runtime_t *node_runtime = &p->node_runtime;
1342  vlib_node_t *node = vlib_get_node (vm, node_runtime->node_index);
1343  u32 old_process_index;
1344  u64 t;
1345  uword n_vectors, is_suspend;
1346 
1347  if (node->state != VLIB_NODE_STATE_POLLING
1350  return last_time_stamp;
1351 
1353 
1354  t = last_time_stamp;
1355  vlib_elog_main_loop_event (vm, node_runtime->node_index, t,
1356  f ? f->n_vectors : 0, /* is_after */ 0);
1357 
1358  /* Save away current process for suspend. */
1359  old_process_index = nm->current_process_index;
1361 
1362  vlib_node_runtime_perf_counter (vm, node_runtime, f, 0, last_time_stamp,
1364 
1365  n_vectors = vlib_process_startup (vm, p, f);
1366 
1367  nm->current_process_index = old_process_index;
1368 
1370  is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
1371  if (is_suspend)
1372  {
1374 
1375  n_vectors = 0;
1377  pf->node_runtime_index = node->runtime_index;
1378  pf->frame = f;
1379  pf->next_frame_index = ~0;
1380 
1381  p->n_suspends += 1;
1383 
1385  {
1386  TWT (tw_timer_wheel) * tw =
1387  (TWT (tw_timer_wheel) *) nm->timing_wheel;
1388  p->stop_timer_handle =
1389  TW (tw_timer_start) (tw,
1391  (node->runtime_index) /* [sic] pool idex */ ,
1392  0 /* timer_id */ ,
1394  }
1395  }
1396  else
1398 
1399  t = clib_cpu_time_now ();
1400 
1401  vlib_elog_main_loop_event (vm, node_runtime->node_index, t, is_suspend,
1402  /* is_after */ 1);
1403 
1404  vlib_node_runtime_perf_counter (vm, node_runtime, f, n_vectors, t,
1406 
1408  /* n_calls */ !is_suspend,
1409  /* n_vectors */ n_vectors,
1410  /* n_clocks */ t - last_time_stamp);
1411 
1412  return t;
1413 }
1414 
1415 void
1417 {
1418  vlib_node_main_t *nm = &vm->node_main;
1419  vlib_process_t *p = vec_elt (nm->processes, process_index);
1420  dispatch_process (vm, p, /* frame */ 0, /* cpu_time_now */ 0);
1421 }
1422 
1423 static u64
1425  uword process_index, u64 last_time_stamp)
1426 {
1427  vlib_node_main_t *nm = &vm->node_main;
1428  vlib_node_runtime_t *node_runtime;
1429  vlib_node_t *node;
1430  vlib_frame_t *f;
1431  vlib_process_t *p;
1433  u64 t, n_vectors, is_suspend;
1434 
1435  t = last_time_stamp;
1436 
1437  p = vec_elt (nm->processes, process_index);
1439  return last_time_stamp;
1440 
1443 
1446 
1447  node_runtime = &p->node_runtime;
1448  node = vlib_get_node (vm, node_runtime->node_index);
1449  f = pf->frame;
1450 
1451  vlib_elog_main_loop_event (vm, node_runtime->node_index, t,
1452  f ? f->n_vectors : 0, /* is_after */ 0);
1453 
1454  /* Save away current process for suspend. */
1456 
1457  vlib_node_runtime_perf_counter (vm, node_runtime, f, 0, last_time_stamp,
1459 
1460  n_vectors = vlib_process_resume (vm, p);
1461  t = clib_cpu_time_now ();
1462 
1463  nm->current_process_index = ~0;
1464 
1465  is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
1466  if (is_suspend)
1467  {
1468  /* Suspend it again. */
1469  n_vectors = 0;
1470  p->n_suspends += 1;
1472  {
1473  p->stop_timer_handle =
1474  TW (tw_timer_start) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
1476  (node->runtime_index) /* [sic] pool idex */ ,
1477  0 /* timer_id */ ,
1479  }
1480  }
1481  else
1482  {
1487  }
1488 
1489  t = clib_cpu_time_now ();
1490  vlib_elog_main_loop_event (vm, node_runtime->node_index, t, !is_suspend,
1491  /* is_after */ 1);
1492 
1493  vlib_node_runtime_perf_counter (vm, node_runtime, f, n_vectors, t,
1495 
1497  /* n_calls */ !is_suspend,
1498  /* n_vectors */ n_vectors,
1499  /* n_clocks */ t - last_time_stamp);
1500 
1501  return t;
1502 }
1503 
1504 void vl_api_send_pending_rpc_requests (vlib_main_t *) __attribute__ ((weak));
1505 void
1507 {
1508 }
1509 
1512 {
1513  vlib_node_main_t *nm = &vm->node_main;
1515  uword i;
1516  u64 cpu_time_now;
1517  f64 now;
1519  u32 frame_queue_check_counter = 0;
1520 
1521  /* Initialize pending node vector. */
1522  if (is_main)
1523  {
1524  vec_resize (nm->pending_frames, 32);
1525  _vec_len (nm->pending_frames) = 0;
1526  }
1527 
1528  /* Mark time of main loop start. */
1529  if (is_main)
1530  {
1531  cpu_time_now = vm->clib_time.last_cpu_time;
1532  vm->cpu_time_main_loop_start = cpu_time_now;
1533  }
1534  else
1535  cpu_time_now = clib_cpu_time_now ();
1536 
1537  /* Pre-allocate interupt runtime indices and lock. */
1539 
1540  /* Pre-allocate expired nodes. */
1545 
1549 
1550  /* Start all processes. */
1551  if (is_main)
1552  {
1553  uword i;
1554 
1555  /*
1556  * Perform an initial barrier sync. Pays no attention to
1557  * the barrier sync hold-down timer scheme, which won't work
1558  * at this point in time.
1559  */
1561 
1562  nm->current_process_index = ~0;
1563  for (i = 0; i < vec_len (nm->processes); i++)
1564  cpu_time_now = dispatch_process (vm, nm->processes[i], /* frame */ 0,
1565  cpu_time_now);
1566  }
1567 
1568  while (1)
1569  {
1571 
1572  if (PREDICT_FALSE (_vec_len (vm->pending_rpc_requests) > 0))
1573  {
1574  if (!is_main)
1576  }
1577 
1578  if (!is_main)
1580 
1581  if (PREDICT_FALSE (vm->check_frame_queues + frame_queue_check_counter))
1582  {
1583  u32 processed = 0;
1586 
1587  if (vm->check_frame_queues)
1588  {
1589  frame_queue_check_counter = 100;
1590  vm->check_frame_queues = 0;
1591  }
1592 
1593  vec_foreach (fqm, tm->frame_queue_mains)
1594  processed += (fn) (vm, fqm);
1595 
1596  /* No handoff queue work found? */
1597  if (processed)
1598  frame_queue_check_counter = 100;
1599  else
1600  frame_queue_check_counter--;
1601  }
1602 
1605  cpu_time_now);
1606 
1607  /* Process pre-input nodes. */
1608  cpu_time_now = clib_cpu_time_now ();
1610  cpu_time_now = dispatch_node (vm, n,
1612  VLIB_NODE_STATE_POLLING,
1613  /* frame */ 0,
1614  cpu_time_now);
1615 
1616  /* Next process input nodes. */
1618  cpu_time_now = dispatch_node (vm, n,
1620  VLIB_NODE_STATE_POLLING,
1621  /* frame */ 0,
1622  cpu_time_now);
1623 
1624  if (PREDICT_TRUE (is_main && vm->queue_signal_pending == 0))
1625  vm->queue_signal_callback (vm);
1626 
1627  if (__atomic_load_n (nm->pending_interrupts, __ATOMIC_ACQUIRE))
1628  {
1629  int int_num = -1;
1630  *nm->pending_interrupts = 0;
1631 
1632  while ((int_num =
1633  clib_interrupt_get_next (nm->interrupts, int_num)) != -1)
1634  {
1636  clib_interrupt_clear (nm->interrupts, int_num);
1638  int_num);
1639  cpu_time_now = dispatch_node (vm, n, VLIB_NODE_TYPE_INPUT,
1640  VLIB_NODE_STATE_INTERRUPT,
1641  /* frame */ 0, cpu_time_now);
1642  }
1643  }
1644 
1645  /* Input nodes may have added work to the pending vector.
1646  Process pending vector until there is nothing left.
1647  All pending vectors will be processed from input -> output. */
1648  for (i = 0; i < _vec_len (nm->pending_frames); i++)
1649  cpu_time_now = dispatch_pending_node (vm, i, cpu_time_now);
1650  /* Reset pending vector for next iteration. */
1651  _vec_len (nm->pending_frames) = 0;
1652 
1653  if (is_main)
1654  {
1655  /* *INDENT-OFF* */
1656  ELOG_TYPE_DECLARE (es) =
1657  {
1658  .format = "process tw start",
1659  .format_args = "",
1660  };
1661  ELOG_TYPE_DECLARE (ee) =
1662  {
1663  .format = "process tw end: %d",
1664  .format_args = "i4",
1665  };
1666  /* *INDENT-ON* */
1667 
1668  struct
1669  {
1670  int nready_procs;
1671  } *ed;
1672 
1673  /* Check if process nodes have expired from timing wheel. */
1675 
1677  ed = ELOG_DATA (&vlib_global_main.elog_main, es);
1678 
1681  ((TWT (tw_timer_wheel) *) nm->timing_wheel, vlib_time_now (vm),
1683 
1685 
1687  {
1688  ed = ELOG_DATA (&vlib_global_main.elog_main, ee);
1689  ed->nready_procs =
1690  _vec_len (nm->data_from_advancing_timing_wheel);
1691  }
1692 
1693  if (PREDICT_FALSE
1694  (_vec_len (nm->data_from_advancing_timing_wheel) > 0))
1695  {
1696  uword i;
1697 
1698  for (i = 0; i < _vec_len (nm->data_from_advancing_timing_wheel);
1699  i++)
1700  {
1703 
1705  {
1708  di);
1709  vlib_node_t *n =
1711  vlib_process_t *p =
1712  vec_elt (nm->processes, n->runtime_index);
1713  void *data;
1714  data =
1716  te->event_type_index,
1717  te->n_data_elts,
1718  te->n_data_elt_bytes);
1719  if (te->n_data_bytes < sizeof (te->inline_event_data))
1721  te->n_data_bytes);
1722  else
1723  {
1725  te->n_data_bytes);
1727  }
1729  }
1730  else
1731  {
1732  cpu_time_now = clib_cpu_time_now ();
1733  cpu_time_now =
1734  dispatch_suspended_process (vm, di, cpu_time_now);
1735  }
1736  }
1737  _vec_len (nm->data_from_advancing_timing_wheel) = 0;
1738  }
1739  }
1741  /* Record time stamp in case there are no enabled nodes and above
1742  calls do not update time stamp. */
1743  cpu_time_now = clib_cpu_time_now ();
1745  now = clib_time_now_internal (&vm->clib_time, cpu_time_now);
1746  /* Time to update loops_per_second? */
1747  if (PREDICT_FALSE (now >= vm->loop_interval_end))
1748  {
1749  /* Next sample ends in 20ms */
1750  if (vm->loop_interval_start)
1751  {
1752  f64 this_loops_per_second;
1753 
1754  this_loops_per_second =
1755  ((f64) vm->loops_this_reporting_interval) / (now -
1756  vm->loop_interval_start);
1757 
1758  vm->loops_per_second =
1760  (1.0 - vm->damping_constant) * this_loops_per_second;
1761  if (vm->loops_per_second != 0.0)
1762  vm->seconds_per_loop = 1.0 / vm->loops_per_second;
1763  else
1764  vm->seconds_per_loop = 0.0;
1765  }
1766  /* New interval starts now, and ends in 20ms */
1767  vm->loop_interval_start = now;
1768  vm->loop_interval_end = now + 2e-4;
1770  }
1771  }
1772 }
1773 
1774 static void
1776 {
1777  vlib_main_or_worker_loop (vm, /* is_main */ 1);
1778 }
1779 
1780 void
1782 {
1783  vlib_main_or_worker_loop (vm, /* is_main */ 0);
1784 }
1785 
1787 
1788 void
1790 {
1792  int i;
1793 
1794  if (is_add == 0)
1795  {
1796  for (i = vec_len (vgm->post_mortem_callbacks) - 1; i >= 0; i--)
1797  if (vgm->post_mortem_callbacks[i] == cb)
1798  vec_del1 (vgm->post_mortem_callbacks, i);
1799  return;
1800  }
1801 
1802  for (i = 0; i < vec_len (vgm->post_mortem_callbacks); i++)
1803  if (vgm->post_mortem_callbacks[i] == cb)
1804  return;
1805  vec_add1 (vgm->post_mortem_callbacks, cb);
1806 }
1807 
1808 static void
1810 {
1812 
1813  u8 *filename;
1815 
1816  filename = format (0, "/tmp/elog_post_mortem.%d%c", getpid (), 0);
1817  error = elog_write_file (em, (char *) filename, 1 /* flush ring */);
1818  if (error)
1819  clib_error_report (error);
1820  /*
1821  * We're in the middle of crashing. Don't try to free the filename.
1822  */
1823 }
1824 
1825 static clib_error_t *
1827 {
1829  int turn_on_mem_trace = 0;
1830 
1831  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1832  {
1833  if (unformat (input, "memory-trace"))
1834  turn_on_mem_trace = 1;
1835 
1836  else if (unformat (input, "elog-events %d",
1839  1 << max_log2 (vgm->configured_elog_ring_size);
1840  else if (unformat (input, "elog-post-mortem-dump"))
1842  /* is_add */ 1);
1843  else if (unformat (input, "buffer-alloc-success-rate %f",
1845  {
1846  if (VLIB_BUFFER_ALLOC_FAULT_INJECTOR == 0)
1847  return clib_error_return
1848  (0, "Buffer fault injection not configured");
1849  }
1850  else if (unformat (input, "buffer-alloc-success-seed %u",
1852  {
1853  if (VLIB_BUFFER_ALLOC_FAULT_INJECTOR == 0)
1854  return clib_error_return
1855  (0, "Buffer fault injection not configured");
1856  }
1857  else
1858  return unformat_parse_error (input);
1859  }
1860 
1861  unformat_free (input);
1862 
1863  /* Enable memory trace as early as possible. */
1864  if (turn_on_mem_trace)
1865  clib_mem_trace (1);
1866 
1867  return 0;
1868 }
1869 
1871 
1872 static void
1874 {
1875 }
1876 
1877 #define foreach_weak_reference_stub \
1878 _(vlib_map_stat_segment_init) \
1879 _(vpe_api_init) \
1880 _(vlibmemory_init) \
1881 _(map_api_segment_init)
1882 
1883 #define _(name) \
1884 clib_error_t *name (vlib_main_t *vm) __attribute__((weak)); \
1885 clib_error_t *name (vlib_main_t *vm) { return 0; }
1887 #undef _
1888 
1889 void vl_api_set_elog_main (elog_main_t * m) __attribute__ ((weak));
1890 void
1892 {
1893  clib_warning ("STUB");
1894 }
1895 
1896 int vl_api_set_elog_trace_api_messages (int enable) __attribute__ ((weak));
1897 int
1899 {
1900  clib_warning ("STUB");
1901  return 0;
1902 }
1903 
1904 int vl_api_get_elog_trace_api_messages (void) __attribute__ ((weak));
1905 int
1907 {
1908  clib_warning ("STUB");
1909  return 0;
1910 }
1911 
1912 /* Main function. */
1913 int
1915 {
1917  clib_error_t *volatile error;
1918  vlib_node_main_t *nm = &vm->node_main;
1919 
1921 
1922  /* Reconfigure event log which is enabled very early */
1923  if (vgm->configured_elog_ring_size &&
1928 
1929  /* Default name. */
1930  if (!vgm->name)
1931  vgm->name = "VLIB";
1932 
1933  if ((error = vlib_physmem_init (vm)))
1934  {
1935  clib_error_report (error);
1936  goto done;
1937  }
1938 
1939  if ((error = vlib_map_stat_segment_init (vm)))
1940  {
1941  clib_error_report (error);
1942  goto done;
1943  }
1944 
1945  if ((error = vlib_buffer_main_init (vm)))
1946  {
1947  clib_error_report (error);
1948  goto done;
1949  }
1950 
1951  if ((error = vlib_thread_init (vm)))
1952  {
1953  clib_error_report (error);
1954  goto done;
1955  }
1956 
1957  /* Register node ifunction variants */
1959 
1960  /* Register static nodes so that init functions may use them. */
1962 
1963  /* Set seed for random number generator.
1964  Allow user to specify seed to make random sequence deterministic. */
1965  if (!unformat (input, "seed %wd", &vm->random_seed))
1966  vm->random_seed = clib_cpu_time_now ();
1968 
1969  /* Initialize node graph. */
1970  if ((error = vlib_node_main_init (vm)))
1971  {
1972  /* Arrange for graph hook up error to not be fatal when debugging. */
1973  if (CLIB_DEBUG > 0)
1974  clib_error_report (error);
1975  else
1976  goto done;
1977  }
1978 
1979  /* Direct call / weak reference, for vlib standalone use-cases */
1980  if ((error = vpe_api_init (vm)))
1981  {
1982  clib_error_report (error);
1983  goto done;
1984  }
1985 
1986  if ((error = vlibmemory_init (vm)))
1987  {
1988  clib_error_report (error);
1989  goto done;
1990  }
1991 
1992  if ((error = map_api_segment_init (vm)))
1993  {
1994  clib_error_report (error);
1995  goto done;
1996  }
1997 
1998  /* See unix/main.c; most likely already set up */
1999  if (vgm->init_functions_called == 0)
2000  vgm->init_functions_called = hash_create (0, /* value bytes */ 0);
2001  if ((error = vlib_call_all_init_functions (vm)))
2002  goto done;
2003 
2004  nm->timing_wheel = clib_mem_alloc_aligned (sizeof (TWT (tw_timer_wheel)),
2006 
2008  _vec_len (nm->data_from_advancing_timing_wheel) = 0;
2009 
2010  /* Create the process timing wheel */
2011  TW (tw_timer_wheel_init) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
2012  0 /* no callback */ ,
2013  10e-6 /* timer period 10us */ ,
2014  ~0 /* max expirations per call */ );
2015 
2017  _vec_len (vm->pending_rpc_requests) = 0;
2019  _vec_len (vm->processing_rpc_requests) = 0;
2020 
2021  /* Default params for the buffer allocator fault injector, if configured */
2022  if (VLIB_BUFFER_ALLOC_FAULT_INJECTOR > 0)
2023  {
2024  vm->buffer_alloc_success_seed = 0xdeaddabe;
2025  vm->buffer_alloc_success_rate = 0.80;
2026  }
2027 
2028  if ((error = vlib_call_all_config_functions (vm, input, 0 /* is_early */ )))
2029  goto done;
2030 
2031  /*
2032  * Use exponential smoothing, with a half-life of 1 second
2033  * reported_rate(t) = reported_rate(t-1) * K + rate(t)*(1-K)
2034  *
2035  * Sample every 20ms, aka 50 samples per second
2036  * K = exp (-1.0/20.0);
2037  * K = 0.95
2038  */
2039  vm->damping_constant = exp (-1.0 / 20.0);
2040 
2041  /* Sort per-thread init functions before we start threads */
2043 
2044  /* Call all main loop enter functions. */
2045  {
2046  clib_error_t *sub_error;
2047  sub_error = vlib_call_all_main_loop_enter_functions (vm);
2048  if (sub_error)
2049  clib_error_report (sub_error);
2050  }
2051 
2053  {
2055  vm->main_loop_exit_set = 1;
2056  break;
2057 
2059  goto done;
2060 
2061  default:
2062  error = vm->main_loop_error;
2063  goto done;
2064  }
2065 
2066  vlib_main_loop (vm);
2067 
2068 done:
2070  /* Call all exit functions. */
2071  {
2072  clib_error_t *sub_error;
2073  sub_error = vlib_call_all_main_loop_exit_functions (vm);
2074  if (sub_error)
2075  clib_error_report (sub_error);
2076  }
2078 
2079  if (error)
2080  clib_error_report (error);
2081 
2082  return 0;
2083 }
2084 
2085 vlib_main_t *
2087 {
2088  return vlib_get_main ();
2089 }
2090 
2091 elog_main_t *
2093 {
2094  return &vlib_global_main.elog_main;
2095 }
2096 
2097 /*
2098  * fd.io coding-style-patch-verification: ON
2099  *
2100  * Local Variables:
2101  * eval: (c-set-style "gnu")
2102  * End:
2103  */
u32 * next_nodes
Definition: node.h:326
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:524
void(** post_mortem_callbacks)(void)
Definition: main.h:285
volatile u32 * pending_interrupts
Definition: node.h:683
clib_error_t * vlib_call_all_main_loop_exit_functions(vlib_main_t *vm)
Definition: init.c:414
__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:171
uword * pending_rpc_requests
Definition: main.h:260
u64 internal_node_vectors
Definition: main.h:125
vlib_main_t * vlib_get_main_not_inline(void)
Definition: main.c:2086
f64 time
Absolute time as floating point number in seconds.
Definition: elog.h:67
u16 vector_size
Definition: node.h:312
u32 max_clock
Maximum clock cycle for an invocation.
Definition: node.h:465
u32 next_frame_index
Start of next frames for this node.
Definition: node.h:476
static clib_error_t * show_frame_stats(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:271
#define hash_set(h, key, value)
Definition: hash.h:255
vnet_interface_output_runtime_t * rt
vlib_node_type_t
Definition: node.h:69
clib_error_t * vlib_call_all_main_loop_enter_functions(vlib_main_t *vm)
Definition: init.c:405
static void vlib_next_frame_change_ownership(vlib_main_t *vm, vlib_node_runtime_t *node_runtime, u32 next_index)
Definition: main.c:301
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:356
u32 interrupt_threshold_vector_length
Definition: node.h:689
vlib_process_t ** processes
Definition: node.h:710
u32 n_free
int vl_api_get_elog_trace_api_messages(void)
Definition: main.c:1906
static uword vlib_process_bootstrap(uword _a)
Definition: main.c:1266
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
vlib_node_runtime_t node_runtime
Definition: node.h:538
a
Definition: bitmap.h:544
static void placeholder_queue_signal_callback(vlib_main_t *vm)
Definition: main.c:1873
u32 n_suspends
Definition: node.h:566
#define VLIB_PENDING_FRAME_NO_NEXT_FRAME
Definition: node.h:452
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:384
uword * processing_rpc_requests
Definition: main.h:261
vnet_hw_if_output_node_runtime_t * r
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:900
static clib_error_t * elog_save_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:711
u32 n_bytes
#define PREDICT_TRUE(x)
Definition: clib.h:125
uword random_seed
Definition: main.h:207
unsigned long u64
Definition: types.h:89
static void vlib_increment_main_loop_counter(vlib_main_t *vm)
Definition: main.h:417
f64 loop_interval_start
Definition: main.h:236
elog_time_stamp_t init_time
Timestamps.
Definition: elog.h:172
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 index
Definition: node.h:270
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:325
f64 buffer_alloc_success_rate
Definition: main.h:266
u32 current_process_index
Definition: node.h:713
void vlib_register_all_static_nodes(vlib_main_t *vm)
Definition: node.c:573
u32 thread_index
Definition: main.h:213
static_always_inline uword vlib_process_startup(vlib_main_t *vm, vlib_process_t *p, vlib_frame_t *f)
Definition: main.c:1296
u32 main_loop_exit_set
Definition: main.h:143
static u64 dispatch_pending_node(vlib_main_t *vm, uword pending_frame_index, u64 last_time_stamp)
Definition: main.c:1132
static vlib_frame_t * vlib_get_frame(vlib_main_t *vm, vlib_frame_t *f)
Definition: node_funcs.h:273
static void vlib_validate_frame_indices(vlib_frame_t *f)
Definition: main.c:193
f64 loops_per_second
Definition: main.h:237
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:607
static u64 clib_cpu_time_now(void)
Definition: time.h:81
elog_track_t elog_track
Definition: threads.h:99
u32 clocks_since_last_overflow
Number of clock cycles.
Definition: node.h:463
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:645
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:685
static void elog_show_buffer_internal(vlib_main_t *vm, u32 n_events_to_show)
Definition: main.c:837
#define VLIB_MAIN_LOOP_EXIT_CLI
Definition: main.h:150
void vlib_post_mortem_dump(void)
Definition: main.c:748
void clib_longjmp(clib_longjmp_t *save, uword return_value)
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:865
clib_time_t clib_time
Definition: main.h:106
u32 numa_node
Definition: main.h:215
__clib_export void elog_resize(elog_main_t *em, u32 n_events)
Definition: elog.c:507
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
uword clib_setjmp(clib_longjmp_t *save, uword return_value_not_taken)
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
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:1252
u8 data[128]
Definition: ipsec_types.api:92
double f64
Definition: types.h:142
u16 scalar_size
Definition: node.h:312
u8 state
Definition: node.h:300
u16 thread_index
thread this node runs on
Definition: node.h:504
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:194
u64 internal_node_calls
Definition: main.h:126
unsigned int u32
Definition: types.h:88
volatile uword check_frame_queues
Definition: main.h:257
static void vlib_worker_thread_barrier_check(void)
Definition: threads.h:378
vlib_frame_t * f
u32 input_main_loops_per_call
For input nodes: decremented on each main loop interation until it reaches zero and function is calle...
Definition: node.h:481
static void vlib_main_loop(vlib_main_t *vm)
Definition: main.c:1775
#define foreach_weak_reference_stub
Definition: main.c:1877
static void elog_post_mortem_dump(void)
Definition: main.c:1809
#define static_always_inline
Definition: clib.h:112
#define VLIB_FRAME_NO_APPEND
Definition: node.h:410
vlib_node_function_t * function
Node function to call.
Definition: node.h:459
#define VLIB_FRAME_MAGIC
void vl_api_set_elog_main(elog_main_t *m)
Definition: main.c:1891
return frame n_vectors
uword * init_functions_called
Definition: main.h:315
u32 main_loop_vectors_processed
Definition: main.h:121
#define VLIB_INVALID_NODE_INDEX
Definition: node.h:366
static vlib_global_main_t * vlib_get_global_main(void)
Definition: global_funcs.h:50
u16 log2_n_stack_bytes
Definition: node.h:561
vlib_buffer_func_main_t vlib_buffer_func_main
Definition: buffer_funcs.c:390
vlib_node_t ** nodes
Definition: node.h:669
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:473
vlib_frame_t * frame
Definition: main.c:1261
#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:184
__clib_export void elog_alloc(elog_main_t *em, u32 n_events)
Definition: elog.c:501
#define clib_error_return(e, args...)
Definition: error.h:99
#define VLIB_FRAME_ALIGN
Definition: node.h:370
u32 cpu_id
Definition: main.h:214
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:598
static uword vlib_timing_wheel_data_is_timed_event(u32 d)
Definition: node.h:635
#define VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE
Definition: node.h:294
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
Definition: node.h:552
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:296
static_always_inline void vlib_process_start_switch_stack(vlib_main_t *vm, vlib_process_t *p)
Definition: node_funcs.h:57
static_always_inline uword vlib_process_resume(vlib_main_t *vm, vlib_process_t *p)
Definition: main.c:1319
u64 cpu_time_main_loop_start
Definition: main.h:115
vlib_node_runtime_t * nodes_by_type[VLIB_N_NODE_TYPE]
Definition: node.h:679
__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:147
#define VLIB_FRAME_SIZE
Definition: node.h:369
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:321
#define VLIB_PROCESS_IS_RUNNING
Definition: node.h:558
#define VLIB_PROCESS_RETURN_LONGJMP_RETURN
Definition: node.h:543
f64 seconds_per_loop
Definition: main.h:238
u64 max_clock_n
Definition: node.h:228
vl_api_fib_path_type_t type
Definition: fib_types.api:123
u32 calls_since_last_overflow
Number of calls.
Definition: node.h:471
Definition: cJSON.c:88
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.c:35
#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:553
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:449
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:828
vlib_node_stats_t stats_total
Definition: node.h:260
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:449
u16 state
Input node state.
Definition: node.h:494
static elog_main_t * vlib_get_elog_main()
Definition: global_funcs.h:62
vlib_signal_timed_event_data_t * signal_timed_event_data_pool
Definition: node.h:700
u16 frame_flags
Definition: node.h:376
__clib_export u8 * format_elog_event(u8 *s, va_list *va)
Definition: elog.c:296
#define VLIB_FRAME_IS_ALLOCATED
Definition: node.h:417
__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
#define VLIB_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:406
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:949
u32 n_alloc_frames
Definition: node.h:522
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:218
static uword vlib_timing_wheel_data_get_index(u32 d)
Definition: node.h:653
#define vec_alloc_aligned(V, N, A)
Allocate space for N more elements (no header, given alignment)
Definition: vec.h:343
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:305
__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:202
#define TWT(a)
u32 * tmp
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
Definition: main.c:242
u32 polling_threshold_vector_length
Definition: node.h:688
#define ELOG_DATA(em, f)
Definition: elog.h:484
u64 * n_vectors_by_next_node
Definition: node.h:335
#define PREDICT_FALSE(x)
Definition: clib.h:124
_vlib_init_function_list_elt_t * worker_init_function_registrations
Definition: main.h:310
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:897
f64 seconds_per_clock
Definition: time.h:58
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
vlib_frame_t * frame
Definition: node.h:443
u32 node_index
Node index.
Definition: node.h:479
vlib_node_function_t * dispatch_wrapper_fn
Definition: main.h:137
#define VLIB_PROCESS_STACK_MAGIC
Definition: node.h:599
#define VLIB_PROCESS_RESUME_LONGJMP_RESUME
Definition: node.h:549
uword * frame_size_hash
Definition: node.h:725
clib_error_t * vlibmemory_init(vlib_main_t *vm)
Definition: memory_api.c:931
#define VLIB_NODE_FLAG_ADAPTIVE_MODE
Definition: node.h:297
volatile u32 queue_signal_pending
Definition: main.h:218
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:239
static u64 dispatch_process(vlib_main_t *vm, vlib_process_t *p, vlib_frame_t *f, u64 last_time_stamp)
Definition: main.c:1337
static_always_inline void os_set_numa_index(uword numa_index)
Definition: os.h:81
u32 owner_node_index
Definition: node.h:346
#define VLIB_EARLY_CONFIG_FUNCTION(x, n,...)
Definition: init.h:220
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:1114
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
u8 inline_event_data[64 - 3 *sizeof(u32) - 2 *sizeof(u16)]
Definition: node.h:626
svmdb_client_t * c
u16 n_vectors
Definition: node.h:388
u32 runtime_index
Definition: node.h:273
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
int elog_trace_graph_dispatch
Definition: main.h:196
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:1511
u32 node_runtime_index
Definition: node.h:446
vlib_pending_frame_t * pending_frames
Definition: node.h:695
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
clib_error_t * vpe_api_init(vlib_main_t *vm)
Definition: api.c:656
u32 index
Definition: flow_types.api:221
#define VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:283
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:647
u32 configured_elog_ring_size
Definition: main.h:301
#define clib_warning(format, args...)
Definition: error.h:59
#define VLIB_PROCESS_RESUME_PENDING
Definition: node.h:555
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:116
#define VLIB_BUFFER_TRACE_TRAJECTORY
Compile time buffer trajectory tracing option Turn this on if you run into "bad monkey" contexts...
Definition: buffer.h:107
static_always_inline void clib_interrupt_clear(void *in, int int_num)
Definition: interrupt.h:90
void(**volatile worker_thread_main_loop_callbacks)(struct vlib_main_t *, u64 t)
Definition: main.h:225
clib_error_t * vlib_buffer_main_init(struct vlib_main_t *vm)
Definition: buffer.c:829
#define VLIB_FRAME_PENDING
Definition: node.h:420
static u32 vlib_frame_vector_byte_offset(u32 scalar_size)
Definition: node_funcs.h:290
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:488
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:442
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:279
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:525
u8 exp
Definition: fib_types.api:27
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
static vlib_main_t * vlib_get_first_main(void)
Definition: global_funcs.h:44
#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:805
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:498
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:433
clib_error_t * vlib_node_main_init(vlib_main_t *vm)
Definition: node.c:665
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:337
#define ASSERT(truth)
u64 last_cpu_time
Definition: time.h:51
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
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:310
#define ELOG_TRACK_DATA(em, f, track)
Definition: elog.h:478
vlib_frame_t * frame
Definition: node.h:397
__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
#define always_inline
Definition: rdma_mlx5dv.h:23
void * interrupts
Definition: node.h:682
u16 flags
Definition: node.h:379
u32 main_loop_nodes_processed
Definition: main.h:122
u64 cpu
CPU cycle counter.
Definition: elog.h:126
u64 loops_this_reporting_interval
Definition: main.h:234
void vlib_worker_thread_initial_barrier_sync_and_release(vlib_main_t *vm)
Definition: threads.c:1253
static_always_inline void vlib_process_finish_switch_stack(vlib_main_t *vm)
Definition: node_funcs.h:67
#define clib_error_report(e)
Definition: error.h:113
__clib_export u32 clib_get_current_cpu_id()
Definition: cpu.c:226
u32 elog_trace_graph_circuit_node_index
Definition: main.h:198
static_always_inline int clib_interrupt_get_next(void *in, int last)
Definition: interrupt.h:104
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
nat44_ei_hairpin_src_next_t next_index
int vl_api_set_elog_trace_api_messages(int enable)
Definition: main.c:1898
static uword pointer_to_uword(const void *p)
Definition: types.h:131
void(* queue_signal_callback)(struct vlib_main_t *)
Definition: main.h:220
void vlib_gdb_show_event_log(void)
Definition: main.c:894
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
#define VLIB_FRAME_OWNER
Definition: node.h:414
void vlib_node_sync_stats(vlib_main_t *vm, vlib_node_t *n)
Definition: main.c:610
#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:1914
#define unformat_parse_error(input)
Definition: format.h:261
typedef key
Definition: ipsec_types.api:88
vlib_frame_queue_dequeue_fn_t * frame_queue_dequeue_fn
Definition: buffer_funcs.h:75
void vlib_worker_loop(vlib_main_t *vm)
Definition: main.c:1781
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:99
void vl_api_send_pending_rpc_requests(vlib_main_t *)
Definition: main.c:1506
elog_main_t * vlib_get_elog_main_not_inline()
Definition: main.c:2092
void vlib_add_del_post_mortem_callback(void *cb, int is_add)
Definition: main.c:1789
#define clib_mem_alloc_aligned_no_fail(size, align)
Definition: mem.h:287
u32 buffer_alloc_success_seed
Definition: main.h:265
u32 * data_from_advancing_timing_wheel
Definition: node.h:703
clib_error_t * vlib_physmem_init(vlib_main_t *vm)
Definition: physmem.c:93
#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:722
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
vlib_pending_frame_t * suspended_process_frames
Definition: node.h:716
vlib_node_main_t node_main
Definition: main.h:171
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:223
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:590
VLIB buffer representation.
Definition: buffer.h:111
u64 uword
Definition: types.h:112
u32 owner_next_index
Definition: node.h:346
u8 vector_size
Definition: node.h:385
vlib_next_frame_t * next_frames
Definition: node.h:692
static clib_error_t * elog_stop(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:765
static void unformat_free(unformat_input_t *i)
Definition: format.h:155
clib_error_t * vlib_call_all_config_functions(vlib_main_t *vm, unformat_input_t *input, int is_early)
Definition: init.c:423
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
static uword elog_is_enabled(elog_main_t *em)
event logging enabled predicate
Definition: elog.h:276
u32() vlib_frame_queue_dequeue_fn_t(vlib_main_t *vm, vlib_frame_queue_main_t *fqm)
Definition: buffer_funcs.h:67
static f64 clib_time_now_internal(clib_time_t *c, u64 n)
Definition: time.h:210
#define VLIB_FRAME_TRACE
Definition: node.h:426
node node_index
u32 stop_timer_handle
Definition: node.h:591
clib_error_t * vlib_call_all_init_functions(vlib_main_t *vm)
Definition: init.c:391
#define VLIB_FRAME_SIZE_EXTRA
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:1424
vlib_frame_size_t * frame_sizes
Definition: node.h:728
u64 resume_clock_interval
Definition: node.h:588
static void add_trajectory_trace(vlib_buffer_t *b, u32 node_index)
Definition: main.c:938
u16 flags
Definition: node.h:551
void vlib_node_runtime_sync_stats_node(vlib_node_t *n, vlib_node_runtime_t *r, uword n_calls, uword n_vectors, uword n_clocks)
Definition: main.c:574
elog_event_type_t * node_call_elog_event_types
Definition: main.h:201
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:261
vlib_node_type_t type
Definition: node.h:267
static vlib_process_t * vlib_get_process_from_node(vlib_main_t *vm, vlib_node_t *node)
Definition: node_funcs.h:265
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:257
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1386
#define clib_call_callbacks(h,...)
call the specified callback set
Definition: callback.h:67
vlib_node_state_t
Definition: node.h:240
u64 init_cpu_time
Definition: time.h:61
nat44_ei_main_t * nm
u32 * stack
Definition: node.h:600
u32 suspended_process_frame_index
Definition: node.h:563
static void validate_frame_magic(vlib_main_t *vm, vlib_frame_t *f, vlib_node_t *n, uword next_index)
Definition: main.c:375
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:56
f64 loop_interval_end
Definition: main.h:235
static clib_error_t * vlib_main_configure(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:1826
f64 now
u32 internal_node_last_vectors_per_main_loop
Definition: main.h:131
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:86
static clib_error_t * vlib_cli_elog_clear(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:694
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT
Definition: node.h:553
#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:541
u16 flags
Copy of main node flags.
Definition: node.h:492
u32 node_runtime_index
Definition: node.h:400
u32 n_total_events
Total number of events in buffer.
Definition: elog.h:135
u8 scalar_size
Definition: node.h:382
clib_longjmp_t main_loop_exit
Definition: main.h:146
clib_longjmp_t resume_longjmp
Definition: node.h:547
void clib_mem_trace(int enable)
Definition: mem_dlmalloc.c:503
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:292
elog_main_t elog_main
Definition: main.h:300
#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:423
static u32 vlib_timing_wheel_data_set_suspended_process(u32 i)
Definition: node.h:641
void vlib_start_process(vlib_main_t *vm, uword process_index)
Definition: main.c:1416
char * name
Definition: main.h:282
__clib_export u32 clib_get_current_numa_node()
Definition: cpu.c:234
void * timing_wheel
Definition: node.h:698
int elog_trace_graph_circuit
Definition: main.h:197
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
vlib_global_main_t vlib_global_main
Definition: main.c:1786
clib_random_buffer_t random_buffer
Definition: main.h:210
static clib_error_t * elog_restart(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:785
void vlib_register_all_node_march_variants(vlib_main_t *vm)
Definition: node.c:539
#define VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE
Definition: node.h:295
u8 *(* validate_frame)(struct vlib_main_t *vm, struct vlib_node_runtime_t *, struct vlib_frame_t *f)
Definition: node.h:356
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
clib_error_t * main_loop_error
Definition: main.h:153
vlib_process_t * process
Definition: main.c:1260
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:112
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
#define VLIB_FRAME_FREE_AFTER_DISPATCH
Definition: node.h:423
clib_error_t * vlib_thread_init(vlib_main_t *vm)
Definition: threads.c:173
u32 vectors_since_last_overflow
Definition: node.h:429
u32 max_clock_n
Number of vectors in the recorded max_clock.
Definition: node.h:468
#define VLIB_PROCESS_RETURN_LONGJMP_SUSPEND
Definition: node.h:544