FD.io VPP  v16.06
Vector Packet Processing
node_cli.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  * node_cli.c: node CLI
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 <vlib/vlib.h>
41 #include <vlib/threads.h>
42 
43 static int
44 node_cmp (void * a1, void *a2)
45 {
46  vlib_node_t ** n1 = a1;
47  vlib_node_t ** n2 = a2;
48 
49  return vec_cmp (n1[0]->name, n2[0]->name);
50 }
51 
52 static clib_error_t *
54  unformat_input_t * input,
55  vlib_cli_command_t * cmd)
56 {
57  vlib_node_main_t * nm = &vm->node_main;
58  vlib_node_t * n;
59  u32 node_index;
60 
61  vlib_cli_output (vm, "%U\n", format_vlib_node_graph, nm, 0);
62 
63  if (unformat (input, "%U", unformat_vlib_node, vm, &node_index))
64  {
65  n = vlib_get_node (vm, node_index);
66  vlib_cli_output (vm, "%U\n", format_vlib_node_graph, nm, n);
67  }
68  else
69  {
70  vlib_node_t ** nodes = vec_dup (nm->nodes);
71  uword i;
72 
74 
75  for (i = 0; i < vec_len (nodes); i++)
76  vlib_cli_output (vm, "%U\n\n", format_vlib_node_graph, nm, nodes[i]);
77 
78  vec_free (nodes);
79  }
80 
81  return 0;
82 }
83 
84 VLIB_CLI_COMMAND (show_node_graph_command, static) = {
85  .path = "show vlib graph",
86  .short_help = "Show packet processing node graph",
87  .function = show_node_graph,
88 };
89 
90 static u8 * format_vlib_node_stats (u8 * s, va_list * va)
91 {
92  vlib_main_t * vm = va_arg (*va, vlib_main_t *);
93  vlib_node_t * n = va_arg (*va, vlib_node_t *);
94  int max = va_arg (*va, int);
95  f64 v;
96  char * state;
97  u8 * ns;
98  u8 * misc_info = 0;
99  u64 c, p, l, d;
100  f64 x;
101  f64 maxc, maxcn;
102  u32 maxn;
103  uword indent;
104 
105  if (! n)
106  {
107  if (max)
108  return format (s,
109  "%=30s%=17s%=16s%=16s%=16s%=16s",
110  "Name", "Max Node Clocks", "Vectors at Max", "Max Clocks", "Avg Clocks", "Avg Vectors/Call");
111  else
112  return format (s,
113  "%=30s%=12s%=16s%=16s%=16s%=16s%=16s",
114  "Name", "State", "Calls", "Vectors", "Suspends", "Clocks", "Vectors/Call");
115  }
116 
117  indent = format_get_indent (s);
118 
123  maxc = (f64)n->stats_total.max_clock;
124  maxn = n->stats_total.max_clock_n;
125  if (n->stats_total.max_clock_n)
126  maxcn = (f64)n->stats_total.max_clock / (f64)maxn;
127  else
128  maxcn = 0.0;
129 
130  /* Clocks per packet, per call or per suspend. */
131  x = 0;
132  if (p > 0)
133  x = (f64) l / (f64) p;
134  else if (c > 0)
135  x = (f64) l / (f64) c;
136  else if (d > 0)
137  x = (f64) l / (f64) d;
138 
139  if (c > 0)
140  v = (double)p / (double)c;
141  else
142  v = 0;
143 
144  state = "active";
145  if (n->type == VLIB_NODE_TYPE_PROCESS)
146  {
148 
149  /* Show processes with events pending. This helps spot bugs where events are not
150  being handled. */
152  misc_info = format (misc_info, "events pending, ");
153 
156  {
157  default:
158  if (! (p->flags & VLIB_PROCESS_IS_RUNNING))
159  state = "done";
160  break;
161 
163  state = "time wait";
164  break;
165 
167  state = "event wait";
168  break;
169 
172  state = "any wait";
173  break;
174  }
175  }
176  else if (n->type != VLIB_NODE_TYPE_INTERNAL)
177  {
178  state = "polling";
179  if (n->state == VLIB_NODE_STATE_DISABLED)
180  state = "disabled";
181  else if (n->state == VLIB_NODE_STATE_INTERRUPT)
182  state = "interrupt wait";
183  }
184 
185  ns = n->name;
186 
187  if (max)
188  s = format (s, "%-30v%=17.2e%=16d%=16.2e%=16.2e%=16.2e",
189  ns, maxc, maxn, maxcn, x, v);
190  else
191  s = format (s, "%-30v%=12s%16Ld%16Ld%16Ld%16.2e%16.2f", ns, state,
192  c, p, d, x, v);
193 
194  if (ns != n->name)
195  vec_free (ns);
196 
197  if (misc_info)
198  {
199  s = format (s, "\n%U%v", format_white_space, indent + 4, misc_info);
200  vec_free (misc_info);
201  }
202 
203  return s;
204 }
205 
206 static clib_error_t *
208  unformat_input_t * input,
209  vlib_cli_command_t * cmd)
210 {
211  vlib_node_main_t * nm = &vm->node_main;
212  vlib_node_t * n;
213  f64 time_now;
214  u32 node_index;
215  vlib_node_t *** node_dups = 0;
216  f64 * vectors_per_main_loop = 0;
217  f64 * last_vector_length_per_node = 0;
218 
219  time_now = vlib_time_now (vm);
220 
221  if (unformat (input, "%U", unformat_vlib_node, vm, &node_index))
222  {
223  n = vlib_get_node (vm, node_index);
224  vlib_node_sync_stats (vm, n);
225  vlib_cli_output (vm, "%U\n", format_vlib_node_stats, vm, 0, 0);
226  vlib_cli_output (vm, "%U\n", format_vlib_node_stats, vm, n, 0);
227  }
228  else
229  {
230  vlib_node_t ** nodes;
231  uword i, j;
232  f64 dt;
233  u64 n_input, n_output, n_drop, n_punt;
234  u64 n_internal_vectors, n_internal_calls;
235  u64 n_clocks, l, v, c, d;
236  int brief = 1;
237  int max = 0;
238  vlib_main_t ** stat_vms = 0, *stat_vm;
239 
240  /* Suppress nodes with zero calls since last clear */
241  if (unformat (input, "brief") || unformat (input, "b"))
242  brief = 1;
243  if (unformat (input, "verbose") || unformat(input, "v"))
244  brief = 0;
245  if (unformat (input, "max") || unformat(input, "m"))
246  max = 1;
247 
248  if (vec_len(vlib_mains) == 0)
249  vec_add1 (stat_vms, vm);
250  else
251  {
252  for (i = 0; i < vec_len (vlib_mains); i++)
253  {
254  stat_vm = vlib_mains[i];
255  if (stat_vm)
256  vec_add1 (stat_vms, stat_vm);
257  }
258  }
259 
260  /*
261  * Barrier sync across stats scraping.
262  * Otherwise, the counts will be grossly inaccurate.
263  */
265 
266  for (j = 0; j < vec_len (stat_vms); j++)
267  {
268  stat_vm = stat_vms[j];
269  nm = &stat_vm->node_main;
270 
271  for (i = 0; i < vec_len (nm->nodes); i++)
272  {
273  n = nm->nodes[i];
274  vlib_node_sync_stats (stat_vm, n);
275  }
276 
277  nodes = vec_dup (nm->nodes);
278 
279  vec_add1(node_dups, nodes);
280  vec_add1 (vectors_per_main_loop,
282  vec_add1 (last_vector_length_per_node,
284  }
286 
287 
288  for (j = 0; j < vec_len (stat_vms); j++)
289  {
290  stat_vm = stat_vms[j];
291  nodes = node_dups[j];
292 
294 
295  n_input = n_output = n_drop = n_punt = n_clocks = 0;
296  n_internal_vectors = n_internal_calls = 0;
297  for (i = 0; i < vec_len (nodes); i++)
298  {
299  n = nodes[i];
300 
302  n_clocks += l;
303 
306 
307  switch (n->type)
308  {
309  default:
310  continue;
311 
313  n_output += (n->flags & VLIB_NODE_FLAG_IS_OUTPUT) ? v : 0;
314  n_drop += (n->flags & VLIB_NODE_FLAG_IS_DROP) ? v : 0;
315  n_punt += (n->flags & VLIB_NODE_FLAG_IS_PUNT) ? v : 0;
316  if (! (n->flags & VLIB_NODE_FLAG_IS_OUTPUT))
317  {
318  n_internal_vectors += v;
319  n_internal_calls += c;
320  }
322  n_input += v;
323  break;
324 
326  n_input += v;
327  break;
328  }
329  }
330 
331  if (vec_len (vlib_mains))
332  {
334  if (j > 0)
335  vlib_cli_output (vm, "---------------");
336 
337  if ( w->dpdk_lcore_id > -1)
338  vlib_cli_output (vm, "Thread %d %s (lcore %u)", j, w->name,
339  w->dpdk_lcore_id);
340  else
341  vlib_cli_output (vm, "Thread %d %s", j,
342  w->name);
343  }
344 
345  dt = time_now - nm->time_last_runtime_stats_clear;
347  (vm,
348  "Time %.1f, average vectors/node %.2f, last %d main loops %.2f per node %.2f"
349  "\n vector rates in %.4e, out %.4e, drop %.4e, punt %.4e",
350  dt,
351  (n_internal_calls > 0
352  ? (f64) n_internal_vectors / (f64) n_internal_calls
353  : 0),
355  vectors_per_main_loop [j],
356  last_vector_length_per_node [j],
357  (f64) n_input / dt,
358  (f64) n_output / dt,
359  (f64) n_drop / dt,
360  (f64) n_punt / dt);
361 
362  vlib_cli_output (vm, "%U", format_vlib_node_stats, stat_vm, 0, max);
363  for (i = 0; i < vec_len (nodes); i++)
364  {
365  c = nodes[i]->stats_total.calls - nodes[i]->stats_last_clear.calls;
366  d = nodes[i]->stats_total.suspends - nodes[i]->stats_last_clear.suspends;
367  if (c || d || ! brief)
368  {
369  vlib_cli_output (vm, "%U", format_vlib_node_stats, stat_vm,
370  nodes[i], max);
371  }
372  }
373  vec_free (nodes);
374  }
375  vec_free (stat_vms);
376  vec_free (node_dups);
377  vec_free (vectors_per_main_loop);
378  vec_free (last_vector_length_per_node);
379  }
380 
381  return 0;
382 }
383 
384 VLIB_CLI_COMMAND (show_node_runtime_command, static) = {
385  .path = "show runtime",
386  .short_help = "Show packet processing runtime",
387  .function = show_node_runtime,
388  .is_mp_safe = 1,
389 };
390 
391 static clib_error_t *
393  unformat_input_t * input,
394  vlib_cli_command_t * cmd)
395 {
396  vlib_node_main_t * nm;
397  vlib_node_t * n;
398  int i, j;
399  vlib_main_t ** stat_vms = 0, *stat_vm;
401 
402  if (vec_len(vlib_mains) == 0)
403  vec_add1 (stat_vms, vm);
404  else
405  {
406  for (i = 0; i < vec_len (vlib_mains); i++)
407  {
408  stat_vm = vlib_mains[i];
409  if (stat_vm)
410  vec_add1 (stat_vms, stat_vm);
411  }
412  }
413 
415 
416  for (j = 0; j < vec_len (stat_vms); j++)
417  {
418  stat_vm = stat_vms[j];
419  nm = &stat_vm->node_main;
420 
421  for (i = 0; i < vec_len (nm->nodes); i++)
422  {
423  n = nm->nodes[i];
424  vlib_node_sync_stats (stat_vm, n);
426 
427  r = vlib_node_get_runtime (stat_vm, n->index);
428  r->max_clock = 0;
429  }
430  /* Note: input/output rates computed using vlib_global_main */
432  }
433 
435 
436  vec_free (stat_vms);
437 
438  return 0;
439 }
440 
441 VLIB_CLI_COMMAND (clear_node_runtime_command, static) = {
442  .path = "clear runtime",
443  .short_help = "Clear packet processing runtime statistics",
444  .function = clear_node_runtime,
445 };
446 
447 /* Dummy function to get us linked in. */
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
always_inline vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Definition: node_funcs.h:46
u32 index
Definition: node.h:203
always_inline f64 vlib_last_vectors_per_main_loop_as_f64(vlib_main_t *vm)
Definition: main.h:258
u16 flags
Definition: node.h:212
static int node_cmp(void *a1, void *a2)
Definition: node_cli.c:44
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
u8 state
Definition: node.h:231
vlib_node_stats_t stats_last_clear
Definition: node.h:197
static clib_error_t * show_node_runtime(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: node_cli.c:207
#define VLIB_NODE_FLAG_IS_DROP
Definition: node.h:220
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:107
vlib_node_t ** nodes
Definition: node.h:570
#define VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE
Definition: main.h:83
unsigned long u64
Definition: types.h:89
u64 max_clock_n
Definition: node.h:163
static u8 * format_vlib_node_stats(u8 *s, va_list *va)
Definition: node_cli.c:90
vlib_node_stats_t stats_total
Definition: node.h:193
#define VLIB_NODE_FLAG_IS_HANDOFF
Definition: node.h:222
f64 time_last_runtime_stats_clear
Definition: node.h:631
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:332
always_inline f64 vlib_last_vector_length_per_node(vlib_main_t *vm)
Definition: main.h:267
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
u8 * name
Definition: node.h:187
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.h:106
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT
Definition: node.h:465
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
#define VLIB_NODE_FLAG_IS_PUNT
Definition: node.h:221
static clib_error_t * clear_node_runtime(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: node_cli.c:392
void vlib_node_cli_reference(void)
Definition: node_cli.c:448
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
vhost_vring_state_t state
Definition: vhost-user.h:77
#define vec_cmp(v1, v2)
Compare two vectors (only applicable to vectors of signed numbers).
Definition: vec.h:878
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1131
always_inline uword format_get_indent(u8 *s)
Definition: format.h:72
u64 uword
Definition: types.h:112
always_inline uword clib_bitmap_is_zero(uword *ai)
Definition: bitmap.h:50
#define VLIB_NODE_FLAG_IS_OUTPUT
Definition: node.h:219
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:140
unsigned char u8
Definition: types.h:56
vlib_node_main_t node_main
Definition: main.h:115
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:898
static clib_error_t * show_node_graph(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: node_cli.c:53
#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
Definition: node.h:464
unformat_function_t unformat_vlib_node
Definition: node_funcs.h:967
void vlib_node_sync_stats(vlib_main_t *vm, vlib_node_t *n)
Definition: main.c:577
u16 flags
Definition: node.h:463
vlib_node_type_t type
Definition: node.h:200
always_inline vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:61
always_inline f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
struct _unformat_input_t unformat_input_t
format_function_t format_vlib_node_graph
Definition: node_funcs.h:960
vlib_main_t ** vlib_mains
Definition: buffer.c:244
#define VLIB_PROCESS_IS_RUNNING
Definition: node.h:470
uword * non_empty_event_type_bitmap
Definition: node.h:484