FD.io VPP  v16.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>
44 
45 #include <vlib/unix/cj.h>
46 
48 
49 /* Actually allocate a few extra slots of vector data to support
50  speculative vector enqueues which overflow vector data in next frame. */
51 #define VLIB_FRAME_SIZE_ALLOC (VLIB_FRAME_SIZE + 4)
52 
54 vlib_frame_bytes (u32 n_scalar_bytes, u32 n_vector_bytes)
55 {
56  u32 n_bytes;
57 
58  /* Make room for vlib_frame_t plus scalar arguments. */
59  n_bytes = vlib_frame_vector_byte_offset (n_scalar_bytes);
60 
61  /* Make room for vector arguments.
62  Allocate a few extra slots of vector data to support
63  speculative vector enqueues which overflow vector data in next frame. */
64 #define VLIB_FRAME_SIZE_EXTRA 4
65  n_bytes += (VLIB_FRAME_SIZE + VLIB_FRAME_SIZE_EXTRA) * n_vector_bytes;
66 
67  /* Magic number is first 32bit number after vector data.
68  Used to make sure that vector data is never overrun. */
69 #define VLIB_FRAME_MAGIC (0xabadc0ed)
70  n_bytes += sizeof (u32);
71 
72  /* Pad to cache line. */
73  n_bytes = round_pow2 (n_bytes, CLIB_CACHE_LINE_BYTES);
74 
75  return n_bytes;
76 }
77 
80 {
81  void * p = f;
82 
84 
86 
87  return p;
88 }
89 
90 static vlib_frame_size_t *
92  u32 n_scalar_bytes, u32 n_vector_bytes)
93 {
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 }
109 
110 static u32
111 vlib_frame_alloc_to_node (vlib_main_t * vm, u32 to_node_index, u32 frame_flags)
112 {
113  vlib_node_main_t * nm = &vm->node_main;
114  vlib_frame_size_t * fs;
115  vlib_node_t * to_node;
116  vlib_frame_t * f;
117  u32 fi, l, n, scalar_size, vector_size;
118 
119  to_node = vlib_get_node (vm, to_node_index);
120 
121  scalar_size = to_node->scalar_size;
122  vector_size = to_node->vector_size;
123 
124  fs = get_frame_size_info (nm, scalar_size, vector_size);
125  n = vlib_frame_bytes (scalar_size, vector_size);
126  if ((l = vec_len (fs->free_frame_indices)) > 0)
127  {
128  /* Allocate from end of free list. */
129  fi = fs->free_frame_indices[l - 1];
130  f = vlib_get_frame_no_check (vm, fi);
131  _vec_len (fs->free_frame_indices) = l - 1;
132  }
133  else
134  {
136  f->cpu_index = vm->cpu_index;
137  fi = vlib_frame_index_no_check (vm, f);
138  }
139 
140  /* Poison frame when debugging. */
141  if (CLIB_DEBUG > 0)
142  {
143  u32 save_cpu_index = f->cpu_index;
144 
145  memset (f, 0xfe, n);
146 
147  f->cpu_index = save_cpu_index;
148  }
149 
150  /* Insert magic number. */
151  {
152  u32 * magic;
153 
154  magic = vlib_frame_find_magic (f, to_node);
155  *magic = VLIB_FRAME_MAGIC;
156  }
157 
158  f->flags = VLIB_FRAME_IS_ALLOCATED | frame_flags;
159  f->n_vectors = 0;
160  f->scalar_size = scalar_size;
161  f->vector_size = vector_size;
162 
163  fs->n_alloc_frames += 1;
164 
165  return fi;
166 }
167 
168 /* Allocate a frame for from FROM_NODE to TO_NODE via TO_NEXT_INDEX.
169  Returns frame index. */
170 static u32
171 vlib_frame_alloc (vlib_main_t * vm, vlib_node_runtime_t * from_node_runtime, u32 to_next_index)
172 {
173  vlib_node_t * from_node;
174 
175  from_node = vlib_get_node (vm, from_node_runtime->node_index);
176  ASSERT (to_next_index < vec_len (from_node->next_nodes));
177 
178  return vlib_frame_alloc_to_node (vm,
179  from_node->next_nodes[to_next_index],
180  /* frame_flags */ 0);
181 }
182 
183 vlib_frame_t *
185 {
186  u32 fi = vlib_frame_alloc_to_node (vm, to_node_index,
187  /* frame_flags */ VLIB_FRAME_FREE_AFTER_DISPATCH);
188  return vlib_get_frame (vm, fi);
189 }
190 
191 void vlib_put_frame_to_node (vlib_main_t * vm, u32 to_node_index, vlib_frame_t * f)
192 {
194  vlib_node_t * to_node;
195 
196  if (f->n_vectors == 0)
197  return;
198 
199  to_node = vlib_get_node (vm, to_node_index);
200 
201  vec_add2 (vm->node_main.pending_frames, p, 1);
202 
204  p->frame_index = vlib_frame_index (vm, f);
205  p->node_runtime_index = to_node->runtime_index;
207 }
208 
209 /* Free given frame. */
210 void
213  vlib_frame_t * f)
214 {
215  vlib_node_main_t * nm = &vm->node_main;
216  vlib_node_t * node;
217  vlib_frame_size_t * fs;
218  u32 frame_index;
219 
221 
222  node = vlib_get_node (vm, r->node_index);
223  fs = get_frame_size_info (nm, node->scalar_size, node->vector_size);
224 
225  frame_index = vlib_frame_index (vm, f);
226 
228 
229  /* No next frames may point to freed frame. */
230  if (CLIB_DEBUG > 0)
231  {
232  vlib_next_frame_t * nf;
234  ASSERT (nf->frame_index != frame_index);
235  }
236 
238 
239  vec_add1 (fs->free_frame_indices, frame_index);
240  ASSERT (fs->n_alloc_frames > 0);
241  fs->n_alloc_frames -= 1;
242 }
243 
244 static clib_error_t *
246  unformat_input_t * input,
247  vlib_cli_command_t * cmd)
248 {
249  vlib_node_main_t * nm = &vm->node_main;
250  vlib_frame_size_t * fs;
251 
252  vlib_cli_output (vm, "%=6s%=12s%=12s", "Size", "# Alloc", "# Free");
253  vec_foreach (fs, nm->frame_sizes)
254  {
255  u32 n_alloc = fs->n_alloc_frames;
256  u32 n_free = vec_len (fs->free_frame_indices);
257 
258  if (n_alloc + n_free > 0)
259  vlib_cli_output (vm, "%=6d%=12d%=12d",
260  fs - nm->frame_sizes, n_alloc, n_free);
261  }
262 
263  return 0;
264 }
265 
266 VLIB_CLI_COMMAND (show_frame_stats_cli, static) = {
267  .path = "show vlib frame-allocation",
268  .short_help = "Show node dispatch frame statistics",
269  .function = show_frame_stats,
270 };
271 
272 /* Change ownership of enqueue rights to given next node. */
273 static void
275  vlib_node_runtime_t * node_runtime,
276  u32 next_index)
277 {
278  vlib_node_main_t * nm = &vm->node_main;
279  vlib_next_frame_t * next_frame;
280  vlib_node_t * node, * next_node;
281 
282  node = vec_elt (nm->nodes, node_runtime->node_index);
283 
284  /* Only internal & input nodes are allowed to call other nodes. */
286  || node->type == VLIB_NODE_TYPE_INPUT
287  || node->type == VLIB_NODE_TYPE_PROCESS);
288 
289  ASSERT (vec_len (node->next_nodes) == node_runtime->n_next_nodes);
290 
291  next_frame = vlib_node_runtime_get_next_frame (vm, node_runtime, next_index);
292  next_node = vec_elt (nm->nodes, node->next_nodes[next_index]);
293 
294  if (next_node->owner_node_index != VLIB_INVALID_NODE_INDEX)
295  {
296  /* Get frame from previous owner. */
297  vlib_next_frame_t * owner_next_frame;
298  vlib_next_frame_t tmp;
299 
300  owner_next_frame =
302  next_node->owner_node_index,
303  next_node->owner_next_index);
304 
305  /* Swap target next frame with owner's. */
306  tmp = owner_next_frame[0];
307  owner_next_frame[0] = next_frame[0];
308  next_frame[0] = tmp;
309 
310  /*
311  * If next_frame is already pending, we have to track down
312  * all pending frames and fix their next_frame_index fields.
313  */
314  if (next_frame->flags & VLIB_FRAME_PENDING)
315  {
317  if (next_frame->frame_index != ~0)
318  {
319  vec_foreach (p, nm->pending_frames)
320  {
321  if (p->frame_index == next_frame->frame_index)
322  {
323  p->next_frame_index =
324  next_frame - vm->node_main.next_frames;
325  }
326  }
327  }
328  }
329  }
330  else
331  {
332  /* No previous owner. Take ownership. */
333  next_frame->flags |= VLIB_FRAME_OWNER;
334  }
335 
336  /* Record new owner. */
337  next_node->owner_node_index = node->index;
338  next_node->owner_next_index = next_index;
339 
340  /* Now we should be owner. */
341  ASSERT (next_frame->flags & VLIB_FRAME_OWNER);
342 }
343 
344 /* Make sure that magic number is still there.
345  Otherwise, it is likely that caller has overrun frame arguments. */
346 always_inline void
348  vlib_frame_t * f,
349  vlib_node_t * n,
350  uword next_index)
351 {
352  vlib_node_t * next_node = vlib_get_node (vm, n->next_nodes[next_index]);
353  u32 * magic = vlib_frame_find_magic (f, next_node);
354  ASSERT (VLIB_FRAME_MAGIC == magic[0]);
355 }
356 
357 vlib_frame_t *
359  vlib_node_runtime_t * node,
360  u32 next_index,
361  u32 allocate_new_next_frame)
362 {
363  vlib_frame_t * f;
364  vlib_next_frame_t * nf;
365  u32 n_used;
366 
367  nf = vlib_node_runtime_get_next_frame (vm, node, next_index);
368 
369  /* Make sure this next frame owns right to enqueue to destination frame. */
370  if (PREDICT_FALSE (! (nf->flags & VLIB_FRAME_OWNER)))
371  vlib_next_frame_change_ownership (vm, node, next_index);
372 
373  /* ??? Don't need valid flag: can use frame_index == ~0 */
375  {
376  nf->frame_index = vlib_frame_alloc (vm, node, next_index);
378  }
379 
380  f = vlib_get_frame (vm, nf->frame_index);
381 
382  /* Has frame been removed from pending vector (e.g. finished dispatching)?
383  If so we can reuse frame. */
384  if ((nf->flags & VLIB_FRAME_PENDING) && ! (f->flags & VLIB_FRAME_PENDING))
385  {
386  nf->flags &= ~VLIB_FRAME_PENDING;
387  f->n_vectors = 0;
388  }
389 
390  /* Allocate new frame if current one is already full. */
391  n_used = f->n_vectors;
392  if (n_used >= VLIB_FRAME_SIZE || (allocate_new_next_frame && n_used > 0))
393  {
394  /* Old frame may need to be freed after dispatch, since we'll have
395  two redundant frames from node -> next node. */
397  {
398  vlib_frame_t * f_old = vlib_get_frame (vm, nf->frame_index);
400  }
401 
402  /* Allocate new frame to replace full one. */
403  nf->frame_index = vlib_frame_alloc (vm, node, next_index);
404  f = vlib_get_frame (vm, nf->frame_index);
405  n_used = f->n_vectors;
406  }
407 
408  /* Should have free vectors in frame now. */
409  ASSERT (n_used < VLIB_FRAME_SIZE);
410 
411  if (CLIB_DEBUG > 0)
412  {
413  validate_frame_magic (vm, f,
414  vlib_get_node (vm, node->node_index),
415  next_index);
416  }
417 
418  return f;
419 }
420 
421 static void
423  vlib_node_runtime_t * rt,
424  u32 next_index,
425  u32 n_vectors_left)
426 {
427  vlib_node_main_t * nm = &vm->node_main;
428  vlib_next_frame_t * nf;
429  vlib_frame_t * f;
430  vlib_node_runtime_t * next_rt;
431  vlib_node_t * next_node;
432  u32 n_before, n_after;
433 
434  nf = vlib_node_runtime_get_next_frame (vm, rt, next_index);
435  f = vlib_get_frame (vm, nf->frame_index);
436 
437  ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
438  n_after = VLIB_FRAME_SIZE - n_vectors_left;
439  n_before = f->n_vectors;
440 
441  ASSERT (n_after >= n_before);
442 
444  nf->node_runtime_index);
445  next_node = vlib_get_node (vm, next_rt->node_index);
446  if (n_after > 0 && next_node->validate_frame)
447  {
448  u8 * msg = next_node->validate_frame (vm, rt, f);
449  if (msg)
450  {
451  clib_warning ("%v", msg);
452  ASSERT (0);
453  }
454  vec_free (msg);
455  }
456 }
457 
458 void
461  u32 next_index,
462  u32 n_vectors_left)
463 {
464  vlib_node_main_t * nm = &vm->node_main;
465  vlib_next_frame_t * nf;
466  vlib_frame_t * f;
467  u32 n_vectors_in_frame;
468 
469  if (DPDK == 0 && CLIB_DEBUG > 0)
470  vlib_put_next_frame_validate (vm, r, next_index, n_vectors_left);
471 
472  nf = vlib_node_runtime_get_next_frame (vm, r, next_index);
473  f = vlib_get_frame (vm, nf->frame_index);
474 
475  /* Make sure that magic number is still there. Otherwise, caller
476  has overrun frame meta data. */
477  if (CLIB_DEBUG > 0)
478  {
479  vlib_node_t * node = vlib_get_node (vm, r->node_index);
480  validate_frame_magic (vm, f, node, next_index);
481  }
482 
483  /* Convert # of vectors left -> number of vectors there. */
484  ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
485  n_vectors_in_frame = VLIB_FRAME_SIZE - n_vectors_left;
486 
487  f->n_vectors = n_vectors_in_frame;
488 
489  /* If vectors were added to frame, add to pending vector. */
490  if (PREDICT_TRUE (n_vectors_in_frame > 0))
491  {
493  u32 v0, v1;
494 
495  r->cached_next_index = next_index;
496 
497  if (!(f->flags & VLIB_FRAME_PENDING))
498  {
499  __attribute__((unused)) vlib_node_t *node;
500  vlib_node_t *next_node;
501  vlib_node_runtime_t *next_runtime;
502 
503  node = vlib_get_node (vm, r->node_index);
504  next_node = vlib_get_next_node (vm, r->node_index, next_index);
505  next_runtime = vlib_node_get_runtime (vm, next_node->index);
506 
507  vec_add2 (nm->pending_frames, p, 1);
508 
509  p->frame_index = nf->frame_index;
511  p->next_frame_index = nf - nm->next_frames;
512  nf->flags |= VLIB_FRAME_PENDING;
514 
515  /*
516  * If we're going to dispatch this frame on another thread,
517  * force allocation of a new frame. Otherwise, we create
518  * a dangling frame reference. Each thread has its own copy of
519  * the next_frames vector.
520  */
521  if (0 && r->cpu_index != next_runtime->cpu_index)
522  {
523  nf->frame_index = ~0;
525  }
526  }
527 
528  /* Copy trace flag from next_frame and from runtime. */
530 
532  v1 = v0 + n_vectors_in_frame;
534  if (PREDICT_FALSE (v1 < v0))
535  {
536  vlib_node_t * node = vlib_get_node (vm, r->node_index);
537  vec_elt (node->n_vectors_by_next_node, next_index) += v0;
538  }
539  }
540 }
541 
542 /* Sync up runtime (32 bit counters) and main node stats (64 bit counters). */
543 never_inline void
546  uword n_calls,
547  uword n_vectors,
548  uword n_clocks)
549 {
550  vlib_node_t * n = vlib_get_node (vm, r->node_index);
551 
552  n->stats_total.calls += n_calls + r->calls_since_last_overflow;
553  n->stats_total.vectors += n_vectors + r->vectors_since_last_overflow;
554  n->stats_total.clocks += n_clocks + r->clocks_since_last_overflow;
557 
561 }
562 
563 always_inline void __attribute__((unused))
565  vlib_process_t * p,
566  uword n_calls,
567  uword n_vectors,
568  uword n_clocks)
569 {
570  vlib_node_runtime_t * rt = &p->node_runtime;
571  vlib_node_t * n = vlib_get_node (vm, rt->node_index);
572  vlib_node_runtime_sync_stats (vm, rt, n_calls, n_vectors, n_clocks);
573  n->stats_total.suspends += p->n_suspends;
574  p->n_suspends = 0;
575 }
576 
578 {
579  vlib_node_runtime_t * rt;
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) return;
585 
588  p->n_suspends = 0;
589  rt = &p->node_runtime;
590  }
591  else
593 
594  vlib_node_runtime_sync_stats (vm, rt, 0, 0, 0);
595 
596  /* Sync up runtime next frame vector counters with main node structure. */
597  {
598  vlib_next_frame_t * nf;
599  uword i;
600  for (i = 0; i < rt->n_next_nodes; i++)
601  {
602  nf = vlib_node_runtime_get_next_frame (vm, rt, i);
605  }
606  }
607 }
608 
611  vlib_node_runtime_t * node,
612  uword n_calls,
613  uword n_vectors,
614  uword n_clocks)
615 {
616  u32 ca0, ca1, v0, v1, cl0, cl1, r;
617 
618  cl0 = cl1 = node->clocks_since_last_overflow;
619  ca0 = ca1 = node->calls_since_last_overflow;
620  v0 = v1 = node->vectors_since_last_overflow;
621 
622  ca1 = ca0 + n_calls;
623  v1 = v0 + n_vectors;
624  cl1 = cl0 + n_clocks;
625 
626  node->calls_since_last_overflow = ca1;
627  node->clocks_since_last_overflow = cl1;
628  node->vectors_since_last_overflow = v1;
629  node->max_clock_n = node->max_clock > n_clocks ?
630  node->max_clock_n : n_vectors;
631  node->max_clock = node->max_clock > n_clocks ?
632  node->max_clock : n_clocks;
633 
634  r = vlib_node_runtime_update_main_loop_vector_stats (vm, node, n_vectors);
635 
636  if (PREDICT_FALSE (ca1 < ca0 || v1 < v0 || cl1 < cl0))
637  {
638  node->calls_since_last_overflow = ca0;
639  node->clocks_since_last_overflow = cl0;
640  node->vectors_since_last_overflow = v0;
641  vlib_node_runtime_sync_stats (vm, node, n_calls, n_vectors, n_clocks);
642  }
643 
644  return r;
645 }
646 
647 always_inline void
649  vlib_process_t * p,
650  uword n_calls,
651  uword n_vectors,
652  uword n_clocks)
653 {
655  n_calls, n_vectors, n_clocks);
656 }
657 
658 static clib_error_t *
660  unformat_input_t * input,
661  vlib_cli_command_t * cmd)
662 {
664  return 0;
665 }
666 
667 VLIB_CLI_COMMAND (elog_clear_cli, static) = {
668  .path = "event-logger clear",
669  .short_help = "Clear the event log",
670  .function = vlib_cli_elog_clear,
671 };
672 
673 #ifdef CLIB_UNIX
674 static clib_error_t *
676  unformat_input_t * input,
677  vlib_cli_command_t * cmd)
678 {
679  elog_main_t * em = &vm->elog_main;
680  char * file, * chroot_file;
681  clib_error_t * error = 0;
682 
683  if (! unformat (input, "%s", &file))
684  {
685  vlib_cli_output (vm, "expected file name, got `%U'",
686  format_unformat_error, input);
687  return 0;
688  }
689 
690  /* It's fairly hard to get "../oopsie" through unformat; just in case */
691  if (strstr(file, "..") || index(file, '/'))
692  {
693  vlib_cli_output (vm, "illegal characters in filename '%s'", file);
694  return 0;
695  }
696 
697  chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
698 
699  vec_free(file);
700 
701  vlib_cli_output (vm, "Saving %wd of %wd events to %s",
704  chroot_file);
705 
707  error = elog_write_file (em, chroot_file);
709  vec_free (chroot_file);
710  return error;
711 }
712 
713 VLIB_CLI_COMMAND (elog_save_cli, static) = {
714  .path = "event-logger save",
715  .short_help = "event-logger save <filename> (saves log in /tmp/<filename>)",
716  .function = elog_save_buffer,
717 };
718 
719 static clib_error_t *
721  unformat_input_t * input,
722  vlib_cli_command_t * cmd)
723 {
724  elog_main_t * em = &vm->elog_main;
725 
727 
728  vlib_cli_output (vm, "Stopped the event logger...");
729  return 0;
730 }
731 
732 VLIB_CLI_COMMAND (elog_stop_cli, static) = {
733  .path = "event-logger stop",
734  .short_help = "Stop the event-logger",
735  .function = elog_stop,
736 };
737 
738 static clib_error_t *
740  unformat_input_t * input,
741  vlib_cli_command_t * cmd)
742 {
743  elog_main_t * em = &vm->elog_main;
744 
746 
747  vlib_cli_output (vm, "Restarted the event logger...");
748  return 0;
749 }
750 
751 VLIB_CLI_COMMAND (elog_restart_cli, static) = {
752  .path = "event-logger restart",
753  .short_help = "Restart the event-logger",
754  .function = elog_restart,
755 };
756 
757 static clib_error_t *
759  unformat_input_t * input,
760  vlib_cli_command_t * cmd)
761 {
762  elog_main_t * em = &vm->elog_main;
763  u32 tmp;
764 
765  /* Stop the parade */
767 
768  if (unformat (input, "%d", &tmp))
769  {
770  elog_alloc (em, tmp);
772  }
773  else
774  return clib_error_return (0, "Must specify how many events in the ring");
775 
776  vlib_cli_output (vm, "Resized ring and restarted the event logger...");
777  return 0;
778 }
779 
780 VLIB_CLI_COMMAND (elog_resize_cli, static) = {
781  .path = "event-logger resize",
782  .short_help = "event-logger resize <nnn>",
783  .function = elog_resize,
784 };
785 
786 #endif /* CLIB_UNIX */
787 
788 static void elog_show_buffer_internal (vlib_main_t * vm, u32 n_events_to_show)
789 {
790  elog_main_t * em = &vm->elog_main;
791  elog_event_t * e, * es;
792  f64 dt;
793 
794  /* Show events in VLIB time since log clock starts after VLIB clock. */
795  dt = (em->init_time.cpu - vm->clib_time.init_cpu_time)
797 
798  es = elog_peek_events (em);
799  vlib_cli_output (vm, "%d of %d events in buffer, logger %s", vec_len (es),
800  em->event_ring_size,
802  "running" : "stopped");
803  vec_foreach (e, es)
804  {
805  vlib_cli_output (vm, "%18.9f: %U",
806  e->time + dt,
807  format_elog_event, em, e);
808  n_events_to_show--;
809  if (n_events_to_show == 0)
810  break;
811  }
812  vec_free (es);
813 
814 }
815 
816 static clib_error_t *
818  unformat_input_t * input,
819  vlib_cli_command_t * cmd)
820 {
821  u32 n_events_to_show;
822  clib_error_t * error = 0;
823 
824  n_events_to_show = 250;
826  {
827  if (unformat (input, "%d", &n_events_to_show))
828  ;
829  else if (unformat (input, "all"))
830  n_events_to_show = ~0;
831  else
832  return unformat_parse_error (input);
833  }
834  elog_show_buffer_internal (vm, n_events_to_show);
835  return error;
836 }
837 
838 VLIB_CLI_COMMAND (elog_show_cli, static) = {
839  .path = "show event-logger",
840  .short_help = "Show event logger info",
841  .function = elog_show_buffer,
842 };
843 
845 {
847 }
848 
849 static inline void
851  u32 node_index,
852  u64 time,
853  u32 n_vectors,
854  u32 is_return)
855 {
856  vlib_main_t * evm = &vlib_global_main;
857  elog_main_t * em = &evm->elog_main;
858 
859  if (VLIB_ELOG_MAIN_LOOP && n_vectors)
860  elog_track (em,
861  /* event type */
862  vec_elt_at_index (is_return
865  node_index),
866  /* track */
868  &em->default_track),
869  /* data to log */ n_vectors);
870 }
871 
873 {
874  vlib_node_main_t * vnm = &vm->node_main;
875  vlib_buffer_t * b;
876  u8 i, n;
877 
879  {
880  b = vlib_get_buffer (vm, bi);
881  n = b->pre_data[0];
882 
883  fformat(stderr, "Context trace for bi %d b 0x%llx, visited %d\n",
884  bi, b, n);
885 
886  if (n == 0 || n > 20)
887  {
888  fformat(stderr, "n is unreasonable\n");
889  return;
890  }
891 
892 
893  for (i = 0; i < n; i++)
894  {
895  u32 node_index;
896 
897  node_index = b->pre_data[i+1];
898 
899  if (node_index > vec_len (vnm->nodes))
900  {
901  fformat(stderr, "Skip bogus node index %d\n", node_index);
902  continue;
903  }
904 
905  fformat(stderr, "%v (%d)\n", vnm->nodes[node_index]->name,
906  node_index);
907  }
908  }
909  else
910  {
911  fformat(stderr,
912  "in vlib/buffers.h, #define VLIB_BUFFER_TRACE_TRAJECTORY 1\n");
913  }
914 }
915 
916 
917 /* static_always_inline */ u64
919  vlib_node_runtime_t * node,
921  vlib_node_state_t dispatch_state,
922  vlib_frame_t * frame,
923  u64 last_time_stamp)
924 {
925  uword n, v;
926  u64 t;
927  vlib_node_main_t * nm = &vm->node_main;
928  vlib_next_frame_t * nf;
929 
930  if (CLIB_DEBUG > 0)
931  {
932  vlib_node_t * n = vlib_get_node (vm, node->node_index);
933  ASSERT (n->type == type);
934  }
935 
936  /* Only non-internal nodes may be disabled. */
937  if (type != VLIB_NODE_TYPE_INTERNAL && node->state != dispatch_state)
938  {
940  return last_time_stamp;
941  }
942 
943  if ((type == VLIB_NODE_TYPE_PRE_INPUT || type == VLIB_NODE_TYPE_INPUT)
944  && dispatch_state != VLIB_NODE_STATE_INTERRUPT)
945  {
946  u32 c = node->input_main_loops_per_call;
947  /* Only call node when count reaches zero. */
948  if (c)
949  {
950  node->input_main_loops_per_call = c - 1;
951  return last_time_stamp;
952  }
953  }
954 
955  /* Speculatively prefetch next frames. */
956  if (node->n_next_nodes > 0)
957  {
959  CLIB_PREFETCH (nf, 4 * sizeof (nf[0]), WRITE);
960  }
961 
962  vm->cpu_time_last_node_dispatch = last_time_stamp;
963 
964  if (1 /* || vm->cpu_index == node->cpu_index */)
965  {
966  vlib_main_t *stat_vm;
967 
968  stat_vm = /* vlib_mains ? vlib_mains[0] : */ vm;
969 
971  last_time_stamp,
972  frame ? frame->n_vectors : 0,
973  /* is_after */ 0);
974 
975  /*
976  * Turn this on if you run into
977  * "bad monkey" contexts, and you want to know exactly
978  * which nodes they've visited... See ixge.c...
979  */
980  if (VLIB_BUFFER_TRACE_TRAJECTORY && frame)
981  {
982  int i;
983  int log_index;
984  u32 * from;
985  from = vlib_frame_vector_args (frame);
986  for (i = 0; i < frame->n_vectors; i++)
987  {
988  vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
989  ASSERT (b->pre_data[0] < 32);
990  log_index = b->pre_data[0]++ + 1;
991  b->pre_data[log_index] = node->node_index;
992  }
993  n = node->function (vm, node, frame);
994  }
995  else
996  n = node->function (vm, node, frame);
997 
998  t = clib_cpu_time_now ();
999 
1000  vlib_elog_main_loop_event (vm, node->node_index, t, n, /* is_after */ 1);
1001 
1002  vm->main_loop_vectors_processed += n;
1003  vm->main_loop_nodes_processed += n > 0;
1004 
1005  v = vlib_node_runtime_update_stats (stat_vm, node,
1006  /* n_calls */ 1,
1007  /* n_vectors */ n,
1008  /* n_clocks */ t - last_time_stamp);
1009 
1010  /* When in interrupt mode and vector rate crosses threshold switch to
1011  polling mode. */
1012  if ((DPDK == 0 && dispatch_state == VLIB_NODE_STATE_INTERRUPT)
1013  || (DPDK == 0 && dispatch_state == VLIB_NODE_STATE_POLLING
1014  && (node->flags
1016  {
1017  ELOG_TYPE_DECLARE (e) = {
1018  .function = (char *) __FUNCTION__,
1019  .format = "%s vector length %d, switching to %s",
1020  .format_args = "T4i4t4",
1021  .n_enum_strings = 2,
1022  .enum_strings = {
1023  "interrupt", "polling",
1024  },
1025  };
1026  struct { u32 node_name, vector_length, is_polling; } * ed;
1027 
1028  if (dispatch_state == VLIB_NODE_STATE_INTERRUPT
1029  && v >= nm->polling_threshold_vector_length)
1030  {
1031  vlib_node_t * n = vlib_get_node (vm, node->node_index);
1032  n->state = VLIB_NODE_STATE_POLLING;
1033  node->state = VLIB_NODE_STATE_POLLING;
1037  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] -= 1;
1038  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] += 1;
1039 
1040  ed = ELOG_DATA (&vm->elog_main, e);
1041  ed->node_name = n->name_elog_string;
1042  ed->vector_length = v;
1043  ed->is_polling = 1;
1044  }
1045  else if (dispatch_state == VLIB_NODE_STATE_POLLING
1046  && v <= nm->interrupt_threshold_vector_length)
1047  {
1048  vlib_node_t * n = vlib_get_node (vm, node->node_index);
1050  {
1051  /* Switch to interrupt mode after dispatch in polling one more time.
1052  This allows driver to re-enable interrupts. */
1053  n->state = VLIB_NODE_STATE_INTERRUPT;
1054  node->state = VLIB_NODE_STATE_INTERRUPT;
1056  nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] -= 1;
1057  nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] += 1;
1058 
1059  }
1060  else
1061  {
1063  ed = ELOG_DATA (&vm->elog_main, e);
1064  ed->node_name = n->name_elog_string;
1065  ed->vector_length = v;
1066  ed->is_polling = 0;
1067  }
1068  }
1069  }
1070  }
1071 
1072  return t;
1073 }
1074 
1075 /* static */ u64
1078  u64 last_time_stamp)
1079 {
1080  vlib_node_main_t * nm = &vm->node_main;
1081  vlib_frame_t * f;
1082  vlib_next_frame_t * nf, nf_dummy;
1083  vlib_node_runtime_t * n;
1084  u32 restore_frame_index;
1085 
1087  p->node_runtime_index);
1088 
1089  f = vlib_get_frame (vm, p->frame_index);
1091  {
1092  /* No next frame: so use dummy on stack. */
1093  nf = &nf_dummy;
1094  nf->flags = f->flags & VLIB_NODE_FLAG_TRACE;
1095  nf->frame_index = ~p->frame_index;
1096  }
1097  else
1099 
1101 
1102  /* Force allocation of new frame while current frame is being
1103  dispatched. */
1104  restore_frame_index = ~0;
1105  if (nf->frame_index == p->frame_index)
1106  {
1107  nf->frame_index = ~0;
1110  restore_frame_index = p->frame_index;
1111  }
1112 
1113  /* Frame must be pending. */
1115  ASSERT (f->n_vectors > 0);
1116 
1117  /* Copy trace flag from next frame to node.
1118  Trace flag indicates that at least one vector in the dispatched
1119  frame is traced. */
1120  n->flags &= ~VLIB_NODE_FLAG_TRACE;
1121  n->flags |= (nf->flags & VLIB_FRAME_TRACE) ? VLIB_NODE_FLAG_TRACE : 0;
1122  nf->flags &= ~VLIB_FRAME_TRACE;
1123 
1124  last_time_stamp = dispatch_node (vm, n,
1126  VLIB_NODE_STATE_POLLING,
1127  f, last_time_stamp);
1128 
1129  f->flags &= ~VLIB_FRAME_PENDING;
1130 
1131  /* Frame is ready to be used again, so restore it. */
1132  if (restore_frame_index != ~0)
1133  {
1134  /* p->next_frame_index can change during node dispatch if node
1135  function decides to change graph hook up. */
1137  nf->frame_index = restore_frame_index;
1139  }
1140 
1142  {
1144  vlib_frame_free (vm, n, f);
1145  }
1146 
1147  return last_time_stamp;
1148 }
1149 
1152 { return p->stack[0] == VLIB_PROCESS_STACK_MAGIC; }
1153 
1154 typedef struct {
1159 
1160 /* Called in process stack. */
1162 {
1164  vlib_main_t * vm;
1165  vlib_node_runtime_t * node;
1166  vlib_frame_t * f;
1167  vlib_process_t * p;
1168  uword n;
1169 
1171 
1172  vm = a->vm;
1173  p = a->process;
1174  f = a->frame;
1175  node = &p->node_runtime;
1176 
1177  n = node->function (vm, node, f);
1178 
1180 
1181  clib_longjmp (&p->return_longjmp, n);
1182 
1183  return n;
1184 }
1185 
1186 /* Called in main stack. */
1189  vlib_process_t * p,
1190  vlib_frame_t * f)
1191 {
1193  uword r;
1194 
1195  a.vm = vm;
1196  a.process = p;
1197  a.frame = f;
1198 
1202  (void *) p->stack + (1 << p->log2_n_stack_bytes));
1203 
1204  return r;
1205 }
1206 
1209 {
1210  uword r;
1217  return r;
1218 }
1219 
1220 static u64
1222  vlib_process_t * p,
1223  vlib_frame_t * f,
1224  u64 last_time_stamp)
1225 {
1226  vlib_node_main_t * nm = &vm->node_main;
1227  vlib_node_runtime_t * node_runtime = &p->node_runtime;
1228  vlib_node_t * node = vlib_get_node (vm, node_runtime->node_index);
1229  u64 t;
1230  uword n_vectors, is_suspend;
1231 
1232  if (node->state != VLIB_NODE_STATE_POLLING
1235  return last_time_stamp;
1236 
1238 
1239  t = last_time_stamp;
1240  vlib_elog_main_loop_event (vm, node_runtime->node_index, t,
1241  f ? f->n_vectors : 0, /* is_after */ 0);
1242 
1243  /* Save away current process for suspend. */
1245 
1246  n_vectors = vlib_process_startup (vm, p, f);
1247 
1248  nm->current_process_index = ~0;
1249 
1251  is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
1252  if (is_suspend)
1253  {
1254  vlib_pending_frame_t * pf;
1255 
1256  n_vectors = 0;
1258  pf->node_runtime_index = node->runtime_index;
1259  pf->frame_index = f ? vlib_frame_index (vm, f) : ~0;
1260  pf->next_frame_index = ~0;
1261 
1262  p->n_suspends += 1;
1264 
1268  }
1269  else
1271 
1272  t = clib_cpu_time_now ();
1273 
1274  vlib_elog_main_loop_event (vm, node_runtime->node_index, t, is_suspend, /* is_after */ 1);
1275 
1277  /* n_calls */ ! is_suspend,
1278  /* n_vectors */ n_vectors,
1279  /* n_clocks */ t - last_time_stamp);
1280 
1281  return t;
1282 }
1283 
1284 void vlib_start_process (vlib_main_t * vm, uword process_index)
1285 {
1286  vlib_node_main_t * nm = &vm->node_main;
1287  vlib_process_t * p = vec_elt (nm->processes, process_index);
1288  dispatch_process (vm, p, /* frame */ 0, /* cpu_time_now */ 0);
1289 }
1290 
1291 static u64
1293  uword process_index,
1294  u64 last_time_stamp)
1295 {
1296  vlib_node_main_t * nm = &vm->node_main;
1297  vlib_node_runtime_t * node_runtime;
1298  vlib_node_t * node;
1299  vlib_frame_t * f;
1300  vlib_process_t * p;
1301  vlib_pending_frame_t * pf;
1302  u64 t, n_vectors, is_suspend;
1303 
1304  t = last_time_stamp;
1305 
1306  p = vec_elt (nm->processes, process_index);
1308  return last_time_stamp;
1309 
1312 
1314 
1315  node_runtime = &p->node_runtime;
1316  node = vlib_get_node (vm, node_runtime->node_index);
1317  f = pf->frame_index != ~0 ? vlib_get_frame (vm, pf->frame_index) : 0;
1318 
1319  vlib_elog_main_loop_event (vm, node_runtime->node_index, t, f ? f->n_vectors : 0, /* is_after */ 0);
1320 
1321  /* Save away current process for suspend. */
1323 
1324  n_vectors = vlib_process_resume (p);
1325  t = clib_cpu_time_now ();
1326 
1327  nm->current_process_index = ~0;
1328 
1329  is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
1330  if (is_suspend)
1331  {
1332  /* Suspend it again. */
1333  n_vectors = 0;
1334  p->n_suspends += 1;
1338  }
1339  else
1340  {
1344  }
1345 
1346  t = clib_cpu_time_now ();
1347  vlib_elog_main_loop_event (vm, node_runtime->node_index, t, ! is_suspend, /* is_after */ 1);
1348 
1350  /* n_calls */ ! is_suspend,
1351  /* n_vectors */ n_vectors,
1352  /* n_clocks */ t - last_time_stamp);
1353 
1354  return t;
1355 }
1356 
1357 static void vlib_main_loop (vlib_main_t * vm)
1358 {
1359  vlib_node_main_t * nm = &vm->node_main;
1360  uword i;
1361  u64 cpu_time_now;
1362 
1363  /* Initialize pending node vector. */
1364  vec_resize (nm->pending_frames, 32);
1365  _vec_len (nm->pending_frames) = 0;
1366 
1367  /* Mark time of main loop start. */
1368  cpu_time_now = vm->clib_time.last_cpu_time;
1369  vm->cpu_time_main_loop_start = cpu_time_now;
1370 
1371  /* Arrange for first level of timing wheel to cover times we care
1372  most about. */
1373  nm->timing_wheel.min_sched_time = 10e-6;
1374  nm->timing_wheel.max_sched_time = 10e-3;
1376  cpu_time_now,
1378 
1379  /* Pre-allocate expired nodes. */
1382 
1387 
1388  nm->current_process_index = ~0;
1389 
1390  /* Start all processes. */
1391  {
1392  uword i;
1393  for (i = 0; i < vec_len (nm->processes); i++)
1394  cpu_time_now = dispatch_process (vm, nm->processes[i], /* frame */ 0, cpu_time_now);
1395  }
1396 
1397  while (1)
1398  {
1399  vlib_node_runtime_t * n;
1400 
1401  /* Process pre-input nodes. */
1403  cpu_time_now = dispatch_node (vm, n,
1405  VLIB_NODE_STATE_POLLING,
1406  /* frame */ 0,
1407  cpu_time_now);
1408 
1409  /* Next process input nodes. */
1411  cpu_time_now = dispatch_node (vm, n,
1413  VLIB_NODE_STATE_POLLING,
1414  /* frame */ 0,
1415  cpu_time_now);
1416 
1417  if (PREDICT_TRUE (vm->queue_signal_pending == 0))
1418  vm->queue_signal_callback (vm);
1419 
1420  /* Next handle interrupts. */
1421  {
1422  uword l = _vec_len (nm->pending_interrupt_node_runtime_indices);
1423  uword i;
1424  if (l > 0)
1425  {
1426  _vec_len (nm->pending_interrupt_node_runtime_indices) = 0;
1427  for (i = 0; i < l; i++)
1428  {
1431  cpu_time_now = dispatch_node (vm, n,
1433  VLIB_NODE_STATE_INTERRUPT,
1434  /* frame */ 0,
1435  cpu_time_now);
1436  }
1437  }
1438  }
1439 
1440  /* Check if process nodes have expired from timing wheel. */
1442  = timing_wheel_advance (&nm->timing_wheel, cpu_time_now,
1445 
1447  if (PREDICT_FALSE (_vec_len (nm->data_from_advancing_timing_wheel) > 0))
1448  {
1449  uword i;
1450 
1451  processes_timing_wheel_data:
1452  for (i = 0; i < _vec_len (nm->data_from_advancing_timing_wheel); i++)
1453  {
1456 
1458  {
1462  void * data;
1464  if (te->n_data_bytes < sizeof (te->inline_event_data))
1465  clib_memcpy (data, te->inline_event_data, te->n_data_bytes);
1466  else
1467  {
1470  }
1472  }
1473  else
1474  {
1475  cpu_time_now = clib_cpu_time_now();
1476  cpu_time_now = dispatch_suspended_process (vm, di, cpu_time_now);
1477  }
1478  }
1479 
1480  /* Reset vector. */
1481  _vec_len (nm->data_from_advancing_timing_wheel) = 0;
1482  }
1483 
1484  /* Input nodes may have added work to the pending vector.
1485  Process pending vector until there is nothing left.
1486  All pending vectors will be processed from input -> output. */
1487  for (i = 0; i < _vec_len (nm->pending_frames); i++)
1488  cpu_time_now = dispatch_pending_node (vm, nm->pending_frames + i,
1489  cpu_time_now);
1490  /* Reset pending vector for next iteration. */
1491  _vec_len (nm->pending_frames) = 0;
1492 
1493  /* Pending internal nodes may resume processes. */
1494  if (_vec_len (nm->data_from_advancing_timing_wheel) > 0)
1495  goto processes_timing_wheel_data;
1496 
1498 
1499  /* Record time stamp in case there are no enabled nodes and above
1500  calls do not update time stamp. */
1501  cpu_time_now = clib_cpu_time_now ();
1502  }
1503 }
1504 
1506 
1507 static clib_error_t *
1509 {
1510  int turn_on_mem_trace = 0;
1511 
1512  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1513  {
1514  if (unformat (input, "memory-trace"))
1515  turn_on_mem_trace = 1;
1516 
1517  else if (unformat (input, "elog-events %d",
1518  &vm->elog_main.event_ring_size))
1519  ;
1520  else
1521  return unformat_parse_error (input);
1522  }
1523 
1524  unformat_free (input);
1525 
1526  /* Enable memory trace as early as possible. */
1527  if (turn_on_mem_trace)
1528  clib_mem_trace (1);
1529 
1530  return 0;
1531 }
1532 
1534 
1536 
1537 /* Main function. */
1539 {
1540  clib_error_t * error;
1541 
1543 
1544  clib_time_init (&vm->clib_time);
1545 
1546  /* Turn on event log. */
1547  if (! vm->elog_main.event_ring_size)
1548  vm->elog_main.event_ring_size = 128 << 10;
1550  elog_enable_disable (&vm->elog_main, 1);
1551 
1552  /* Default name. */
1553  if (! vm->name)
1554  vm->name = "VLIB";
1555 
1556  vec_validate (vm->buffer_main, 0);
1557 
1558  if ((error = vlib_thread_init (vm)))
1559  {
1560  clib_error_report (error);
1561  goto done;
1562  }
1563 
1564  /* Register static nodes so that init functions may use them. */
1566 
1567  /* Set seed for random number generator.
1568  Allow user to specify seed to make random sequence deterministic. */
1569  if (! unformat (input, "seed %wd", &vm->random_seed))
1570  vm->random_seed = clib_cpu_time_now ();
1572 
1573  /* See unix/main.c; most likely already set up */
1574  if (vm->init_functions_called == 0)
1575  vm->init_functions_called = hash_create (0, /* value bytes */ 0);
1576  if ((error = vlib_call_all_init_functions (vm)))
1577  goto done;
1578 
1579  /* Initialize node graph. */
1580  if ((error = vlib_node_main_init (vm)))
1581  {
1582  /* Arrange for graph hook up error to not be fatal when debugging. */
1583  if (CLIB_DEBUG > 0)
1584  clib_error_report (error);
1585  else
1586  goto done;
1587  }
1588 
1589  /* Create default buffer free list. */
1591  "default");
1592 
1594  {
1596  vm->main_loop_exit_set = 1;
1597  break;
1598 
1600  goto done;
1601 
1602  default:
1603  error = vm->main_loop_error;
1604  goto done;
1605  }
1606 
1607  if ((error = vlib_call_all_config_functions (vm, input, 0 /* is_early */)))
1608  goto done;
1609 
1610  /* Call all main loop enter functions. */
1611  {
1612  clib_error_t * sub_error;
1613  sub_error = vlib_call_all_main_loop_enter_functions (vm);
1614  if (sub_error)
1615  clib_error_report (sub_error);
1616  }
1617 
1618  vlib_main_loop (vm);
1619 
1620  done:
1621  /* Call all exit functions. */
1622  {
1623  clib_error_t * sub_error;
1624  sub_error = vlib_call_all_main_loop_exit_functions (vm);
1625  if (sub_error)
1626  clib_error_report (sub_error);
1627  }
1628 
1629  if (error)
1630  clib_error_report (error);
1631 
1632  return 0;
1633 }
u32 * next_nodes
Definition: node.h:254
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Definition: main.c:459
always_inline u32 vlib_frame_index_no_check(vlib_main_t *vm, vlib_frame_t *f)
Definition: node_funcs.h:163
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:422
always_inline uword round_pow2(uword x, uword pow2)
Definition: clib.h:255
f64 time
Definition: elog.h:55
u16 vector_size
Definition: node.h:240
u32 next_frame_index
Definition: node.h:396
#define hash_set(h, key, value)
Definition: hash.h:237
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define VLIB_BUFFER_TRACE_TRAJECTORY
Compile time buffer trajectory tracing option Turn this on if you run into "bad monkey" contexts...
Definition: buffer.h:378
u32 interrupt_threshold_vector_length
Definition: node.h:589
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
vlib_process_t ** processes
Definition: node.h:610
clib_error_t * vlib_call_all_main_loop_enter_functions(vlib_main_t *vm)
Definition: init.c:78
vlib_node_runtime_t node_runtime
Definition: node.h:450
always_inline uword vlib_timing_wheel_data_is_timed_event(u32 d)
Definition: node.h:553
a
Definition: bitmap.h:393
u32 n_suspends
Definition: node.h:478
static void elog_show_buffer_internal(vlib_main_t *vm, u32 n_events_to_show)
Definition: main.c:788
always_inline vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Definition: node_funcs.h:46
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
always_inline uword elog_buffer_capacity(elog_main_t *em)
Definition: elog.h:171
u8 *(* validate_frame)(struct vlib_main_t *vm, struct vlib_node_runtime_t *, struct vlib_frame_t *f)
Definition: node.h:284
static clib_error_t * elog_show_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:817
static u32 vlib_frame_alloc(vlib_main_t *vm, vlib_node_runtime_t *from_node_runtime, u32 to_next_index)
Definition: main.c:171
always_inline 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:213
#define VLIB_FRAME_OWNER
Definition: node.h:332
#define PREDICT_TRUE(x)
Definition: clib.h:98
uword random_seed
Definition: main.h:150
#define VLIB_FRAME_IS_ALLOCATED
Definition: node.h:335
void timing_wheel_init(timing_wheel_t *w, u64 current_cpu_time, f64 cpu_clocks_per_second)
Definition: timing_wheel.c:21
elog_time_stamp_t init_time
Definition: elog.h:153
always_inline void unformat_free(unformat_input_t *i)
Definition: format.h:160
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
void clib_random_buffer_init(clib_random_buffer_t *b, uword seed)
Definition: random_buffer.c:58
u32 index
Definition: node.h:203
static void dummy_queue_signal_callback(vlib_main_t *vm)
Definition: main.c:1535
f64 clocks_per_second
Definition: time.h:52
#define VLIB_FRAME_MAGIC
u32 current_process_index
Definition: node.h:613
u32 main_loop_exit_set
Definition: main.h:86
u64 cpu_time_next_process_ready
Definition: node.h:606
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
elog_track_t elog_track
Definition: threads.h:96
always_inline void elog_reset_buffer(elog_main_t *em)
Definition: elog.h:175
clib_error_t * vlib_node_main_init(vlib_main_t *vm)
Definition: node.c:467
#define VLIB_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:327
u32 clocks_since_last_overflow
Definition: node.h:381
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
vlib_buffer_main_t * buffer_main
Definition: main.h:103
#define VLIB_MAIN_LOOP_EXIT_CLI
Definition: main.h:91
always_inline 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:619
void clib_longjmp(clib_longjmp_t *save, uword return_value)
u8 * format_elog_event(u8 *s, va_list *va)
Definition: elog.c:274
clib_time_t clib_time
Definition: main.h:61
static clib_error_t * elog_resize(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:758
#define clib_error_report(e)
Definition: error.h:126
void timing_wheel_insert(timing_wheel_t *w, u64 insert_cpu_time, u32 user_data)
Definition: timing_wheel.c:273
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:850
#define pool_get(P, E)
Definition: pool.h:186
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:237
always_inline vlib_frame_t * vlib_get_frame(vlib_main_t *vm, uword frame_index)
Definition: node_funcs.h:176
vlib_node_state_t
Definition: node.h:175
#define VLIB_PROCESS_RESUME_PENDING
Definition: node.h:467
always_inline vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u16 scalar_size
Definition: node.h:240
u8 state
Definition: node.h:231
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
u32 * pending_interrupt_node_runtime_indices
Definition: node.h:583
u32 input_main_loops_per_call
Definition: node.h:404
#define VLIB_FRAME_SIZE_EXTRA
#define static_always_inline
Definition: clib.h:85
always_inline uword vlib_timing_wheel_data_get_index(u32 d)
Definition: node.h:565
always_inline u32 vlib_frame_bytes(u32 n_scalar_bytes, u32 n_vector_bytes)
Definition: main.c:54
always_inline void elog_enable_disable(elog_main_t *em, int is_enabled)
Definition: elog.h:182
vlib_node_function_t * function
Definition: node.h:375
void elog_init(elog_main_t *em, u32 n_events)
Definition: elog.c:435
u64 dispatch_pending_node(vlib_main_t *vm, vlib_pending_frame_t *p, u64 last_time_stamp)
Definition: main.c:1076
#define always_inline
Definition: clib.h:84
u32 main_loop_vectors_processed
Definition: main.h:73
u16 log2_n_stack_bytes
Definition: node.h:473
static clib_error_t * elog_save_buffer(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:675
never_inline void vlib_node_runtime_sync_stats(vlib_main_t *vm, vlib_node_runtime_t *r, uword n_calls, uword n_vectors, uword n_clocks)
Definition: main.c:544
vlib_node_t ** nodes
Definition: node.h:570
u32 vectors_since_last_overflow
Definition: node.h:393
vlib_frame_t * frame
Definition: main.c:1157
void di(unformat_input_t *i)
Definition: unformat.c:150
clib_error_t * vlib_call_all_main_loop_exit_functions(vlib_main_t *vm)
Definition: init.c:84
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
always_inline void elog_track(elog_main_t *em, elog_event_type_t *type, elog_track_t *track, u32 data)
Definition: elog.h:301
#define VLIB_FRAME_ALIGN
Definition: node.h:293
always_inline 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:610
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
Definition: buffer.h:142
clib_error_t * vlib_call_all_init_functions(vlib_main_t *vm)
Definition: init.c:66
u32 cpu_index
Definition: main.h:159
#define clib_warning(format, args...)
Definition: error.h:59
unsigned long u64
Definition: types.h:89
int vlib_main(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:1538
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
Definition: vec.h:199
u64 cpu_time_main_loop_start
Definition: main.h:67
vlib_node_runtime_t * nodes_by_type[VLIB_N_NODE_TYPE]
Definition: node.h:580
u32 * free_frame_indices
Definition: node.h:440
#define VLIB_MAIN_LOOP_EXIT_NONE
Definition: main.h:88
static clib_error_t * elog_restart(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:739
#define VLIB_FRAME_TRACE
Definition: node.h:344
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
Definition: node_funcs.h:202
static uword pointer_to_uword(const void *p)
Definition: types.h:131
static_always_inline uword vlib_process_startup(vlib_main_t *vm, vlib_process_t *p, vlib_frame_t *f)
Definition: main.c:1188
u64 max_clock_n
Definition: node.h:163
static clib_error_t * vlib_main_configure(vlib_main_t *vm, unformat_input_t *input)
Definition: main.c:1508
static u64 dispatch_suspended_process(vlib_main_t *vm, uword process_index, u64 last_time_stamp)
Definition: main.c:1292
u32 calls_since_last_overflow
Definition: node.h:390
char * name
Definition: main.h:97
#define hash_get(h, key)
Definition: hash.h:231
#define pool_elt_at_index(p, i)
Definition: pool.h:346
u32 next_frame_index
Definition: node.h:367
vlib_node_stats_t stats_total
Definition: node.h:193
static u32 vlib_frame_alloc_to_node(vlib_main_t *vm, u32 to_node_index, u32 frame_flags)
Definition: main.c:111
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:91
u32 frame_index
Definition: node.h:318
#define VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES
Definition: buffer.h:297
always_inline void validate_frame_magic(vlib_main_t *vm, vlib_frame_t *f, vlib_node_t *n, uword next_index)
Definition: main.c:347
vlib_signal_timed_event_data_t * signal_timed_event_data_pool
Definition: node.h:600
vlib_node_type_t
Definition: node.h:57
void vlib_register_all_static_nodes(vlib_main_t *vm)
Definition: node.c:455
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
Definition: main.c:211
u32 n_alloc_frames
Definition: node.h:437
u8 inline_event_data[64-3 *sizeof(u32)-2 *sizeof(u16)]
Definition: node.h:545
#define pool_put(P, E)
Definition: pool.h:200
elog_event_type_t * node_return_elog_event_types
Definition: main.h:145
u32 polling_threshold_vector_length
Definition: node.h:588
#define ELOG_DATA(em, f)
Definition: elog.h:386
u64 * n_vectors_by_next_node
Definition: node.h:263
#define unformat_parse_error(input)
Definition: format.h:265
#define PREDICT_FALSE(x)
Definition: clib.h:97
always_inline u32 * vlib_frame_find_magic(vlib_frame_t *f, vlib_node_t *node)
Definition: main.c:79
#define VLIB_FRAME_PENDING
Definition: node.h:338
always_inline u32 vlib_frame_vector_byte_offset(u32 scalar_size)
Definition: node_funcs.h:195
#define VLIB_FRAME_SIZE
Definition: node.h:292
f64 seconds_per_clock
Definition: time.h:56
always_inline vlib_frame_t * vlib_get_frame_no_check(vlib_main_t *vm, uword frame_index)
Definition: node_funcs.h:152
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:191
uword * init_functions_called
Definition: main.h:156
#define VLIB_FRAME_FREE_AFTER_DISPATCH
Definition: node.h:341
#define VLIB_ELOG_MAIN_LOOP
Definition: main.h:56
always_inline 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:859
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
void clib_time_init(clib_time_t *c)
Definition: time.c:160
uword * frame_size_hash
Definition: node.h:625
void elog_alloc(elog_main_t *em, u32 n_events)
Definition: elog.c:422
volatile u32 queue_signal_pending
Definition: main.h:172
always_inline vlib_node_t * vlib_get_next_node(vlib_main_t *vm, u32 node_index, u32 next_index)
Definition: node_funcs.h:50
#define VLIB_PROCESS_RETURN_LONGJMP_SUSPEND
Definition: node.h:456
#define uword_to_pointer(u, type)
Definition: types.h:134
always_inline vlib_next_frame_t * vlib_node_get_next_frame(vlib_main_t *vm, u32 node_index, u32 next_index)
Definition: node_funcs.h:236
u8 * name
Definition: node.h:187
static clib_error_t * vlib_cli_elog_clear(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:659
timing_wheel_t timing_wheel
Definition: node.h:598
u32 owner_node_index
Definition: node.h:274
#define VLIB_EARLY_CONFIG_FUNCTION(x, n,...)
Definition: init.h:137
u16 n_vectors
Definition: node.h:307
u32 runtime_index
Definition: node.h:206
always_inline uword elog_n_events_in_buffer(elog_main_t *em)
Definition: elog.h:167
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
u32 node_runtime_index
Definition: node.h:361
vlib_pending_frame_t * pending_frames
Definition: node.h:595
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
#define clib_memcpy(a, b, c)
Definition: string.h:63
u32 * timing_wheel_advance(timing_wheel_t *w, u64 advance_cpu_time, u32 *expired_user_data, u64 *next_expiring_element_cpu_time)
Definition: timing_wheel.c:551
elog_main_t elog_main
Definition: main.h:141
always_inline 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:564
#define VLIB_PROCESS_RETURN_LONGJMP_RETURN
Definition: node.h:455
vlib_main_t vlib_global_main
Definition: main.c:1505
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:344
u32 n_total_events_disable_limit
Definition: elog.h:123
always_inline u32 vlib_frame_index(vlib_main_t *vm, vlib_frame_t *f)
Definition: node_funcs.h:184
always_inline u32 vlib_timing_wheel_data_set_suspended_process(u32 i)
Definition: node.h:557
void vlib_start_process(vlib_main_t *vm, uword process_index)
Definition: main.c:1284
static_always_inline uword vlib_process_resume(vlib_process_t *p)
Definition: main.c:1208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.h:106
#define never_inline
Definition: clib.h:81
#define hash_create(elts, value_bytes)
Definition: hash.h:615
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT
Definition: node.h:465
u16 cached_next_index
Definition: node.h:422
#define ASSERT(truth)
u64 last_cpu_time
Definition: time.h:49
always_inline vlib_process_t * vlib_get_process_from_node(vlib_main_t *vm, vlib_node_t *node)
Definition: node_funcs.h:143
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
Definition: threads.c:1100
unsigned int u32
Definition: types.h:88
static void vlib_main_loop(vlib_main_t *vm)
Definition: main.c:1357
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
u32 vlib_buffer_get_or_create_free_list(vlib_main_t *vm, u32 n_data_bytes, char *fmt,...)
Definition: buffer.c:511
always_inline uword vlib_process_stack_is_valid(vlib_process_t *p)
Definition: main.c:1151
static uword vlib_process_bootstrap(uword _a)
Definition: main.c:1161
uword event_ring_size
Definition: elog.h:129
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
always_inline 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:648
#define VLIB_PROCESS_STACK_MAGIC
Definition: node.h:515
u16 flags
Definition: node.h:298
u32 main_loop_nodes_processed
Definition: main.h:74
u16 cpu_index
Definition: node.h:310
#define VLIB_PROCESS_RESUME_LONGJMP_RESUME
Definition: node.h:461
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:225
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1131
void(* queue_signal_callback)(struct vlib_main_t *)
Definition: main.h:174
clib_error_t * vlib_thread_init(vlib_main_t *vm)
Definition: threads.c:132
u64 uword
Definition: types.h:112
#define vec_elt(v, i)
Get vector value at index i.
static void vlib_next_frame_change_ownership(vlib_main_t *vm, vlib_node_runtime_t *node_runtime, u32 next_index)
Definition: main.c:274
static clib_error_t * elog_stop(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:720
#define clib_mem_alloc_aligned_no_fail(size, align)
Definition: mem.h:118
u32 * data_from_advancing_timing_wheel
Definition: node.h:603
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:140
u32 input_node_counts_by_state[VLIB_N_NODE_STATE]
Definition: node.h:622
unsigned char u8
Definition: types.h:56
#define VLIB_PENDING_FRAME_NO_NEXT_FRAME
Definition: node.h:370
vlib_pending_frame_t * suspended_process_frames
Definition: node.h:616
vlib_node_main_t node_main
Definition: main.h:115
u32 owner_next_index
Definition: node.h:274
u8 vector_size
Definition: node.h:304
vlib_next_frame_t * next_frames
Definition: node.h:592
void vlib_dump_context_trace(vlib_main_t *vm, u32 bi)
Definition: main.c:872
#define VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE
Definition: node.h:228
always_inline void vlib_increment_main_loop_counter(vlib_main_t *vm)
Definition: main.h:278
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
Definition: node.h:464
word fformat(FILE *f, char *fmt,...)
Definition: format.c:437
vlib_frame_size_t * frame_sizes
Definition: node.h:628
void vlib_node_sync_stats(vlib_main_t *vm, vlib_node_t *n)
Definition: main.c:577
u16 flags
Definition: node.h:463
elog_event_type_t * node_call_elog_event_types
Definition: main.h:144
vlib_node_type_t type
Definition: node.h:200
uword clib_calljmp(uword(*func)(uword func_arg), uword func_arg, void *stack)
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:918
u32 name_elog_string
Definition: node.h:190
#define VLIB_INVALID_NODE_INDEX
Definition: node.h:289
u64 init_cpu_time
Definition: time.h:59
always_inline vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:61
u32 suspended_process_frame_index
Definition: node.h:475
#define VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE
Definition: node.h:227
u64 resume_cpu_time
Definition: node.h:497
#define vec_foreach(var, vec)
Vector iterator.
static u64 dispatch_process(vlib_main_t *vm, vlib_process_t *p, vlib_frame_t *f, u64 last_time_stamp)
Definition: main.c:1221
elog_track_t default_track
Definition: elog.h:148
clib_longjmp_t return_longjmp
Definition: node.h:453
u32 node_runtime_index
Definition: node.h:321
u32 n_total_events
Definition: elog.h:119
u8 scalar_size
Definition: node.h:301
#define clib_error_return(e, args...)
Definition: error.h:112
clib_longjmp_t main_loop_exit
Definition: main.h:87
CJ_GLOBAL_LOG_PROTOTYPE
Definition: main.c:47
struct _unformat_input_t unformat_input_t
clib_longjmp_t resume_longjmp
Definition: node.h:459
void clib_mem_trace(int enable)
Definition: mem_mheap.c:144
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:184
static clib_error_t * show_frame_stats(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: main.c:245
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
always_inline u64 clib_cpu_time_now(void)
Definition: time.h:71
#define VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
Definition: node.h:216
always_inline clib_error_t * elog_write_file(elog_main_t *em, char *unix_file)
Definition: elog.h:415
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
clib_error_t * vlib_call_all_config_functions(vlib_main_t *vm, unformat_input_t *input, int is_early)
Definition: init.c:90
clib_random_buffer_t random_buffer
Definition: main.h:153
clib_error_t * main_loop_error
Definition: main.h:94
vlib_process_t * process
Definition: main.c:1156
elog_event_t * elog_peek_events(elog_main_t *em)
Definition: elog.c:474
u64 cpu_time_last_node_dispatch
Definition: main.h:64
void vlib_gdb_show_event_log(void)
Definition: main.c:844
u32 vectors_since_last_overflow
Definition: node.h:347
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:358
#define VLIB_PROCESS_IS_RUNNING
Definition: node.h:470