FD.io VPP  v16.09
Vector Packet Processing
threads_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 #include <vppinfra/format.h>
17 #include <vlib/vlib.h>
18 
19 #include <vlib/threads.h>
20 
21 static clib_error_t *
23  unformat_input_t * input, vlib_cli_command_t * cmd)
24 {
26  int i;
27 
28  vlib_cli_output (vm, "%-7s%-20s%-12s%-8s%-7s%-7s%-7s%-10s",
29  "ID", "Name", "Type", "LWP",
30  "lcore", "Core", "Socket", "State");
31 
32 #if !defined(__powerpc64__)
33  for (i = 0; i < vec_len (vlib_worker_threads); i++)
34  {
35  w = vlib_worker_threads + i;
36  u8 *line = NULL;
37 
38  line = format (line, "%-7d%-20s%-12s%-8d",
39  i,
40  w->name ? w->name : (u8 *) "",
41  w->registration ? w->registration->name : "", w->lwp);
42 
43 #if DPDK==1
44  int lcore = w->dpdk_lcore_id;
45  if (lcore > -1)
46  {
47  line = format (line, "%-7u%-7u%-7u",
48  lcore,
49  lcore_config[lcore].core_id,
50  lcore_config[lcore].socket_id);
51 
52  switch (lcore_config[lcore].state)
53  {
54  case WAIT:
55  line = format (line, "wait");
56  break;
57  case RUNNING:
58  line = format (line, "running");
59  break;
60  case FINISHED:
61  line = format (line, "finished");
62  break;
63  default:
64  line = format (line, "unknown");
65  }
66  }
67 #endif
68  vlib_cli_output (vm, "%v", line);
69  vec_free (line);
70  }
71 #endif
72 
73  return 0;
74 }
75 
76 
77 /* *INDENT-OFF* */
78 VLIB_CLI_COMMAND (show_threads_command, static) = {
79  .path = "show threads",
80  .short_help = "Show threads",
81  .function = show_threads_fn,
82 };
83 /* *INDENT-ON* */
84 
85 /*
86  * Trigger threads to grab frame queue trace data
87  */
88 static clib_error_t *
90  vlib_cli_command_t * cmd)
91 {
92  clib_error_t *error = NULL;
96  u32 num_fq;
97  u32 fqix;
98  u32 enable = 0;
99 
100  if (unformat (input, "on"))
101  {
102  enable = 1;
103  }
104  else if (unformat (input, "off"))
105  {
106  enable = 0;
107  }
108  else
109  {
110  return clib_error_return (0, "expecting on or off");
111  }
112 
113  num_fq = vec_len (vlib_frame_queues);
114  if (num_fq == 0)
115  {
116  vlib_cli_output (vm, "No frame queues exist\n");
117  return error;
118  }
119 
120  // Allocate storage for trace if necessary
121  vec_validate_aligned (tm->frame_queue_traces, num_fq - 1,
125 
126  for (fqix = 0; fqix < num_fq; fqix++)
127  {
128  fqt = &tm->frame_queue_traces[fqix];
129  fqh = &tm->frame_queue_histogram[fqix];
130 
131  memset (fqt->n_vectors, 0xff, sizeof (fqt->n_vectors));
132  fqt->written = 0;
133  memset (fqh, 0, sizeof (*fqh));
134  vlib_frame_queues[fqix]->trace = enable;
135  }
136  return error;
137 }
138 
139 /* *INDENT-OFF* */
140 VLIB_CLI_COMMAND (cmd_trace_frame_queue,static) = {
141  .path = "trace frame-queue",
142  .short_help = "trace frame-queue (on|off)",
143  .function = trace_frame_queue,
144  .is_mp_safe = 1,
145 };
146 /* *INDENT-ON* */
147 
148 
149 /*
150  * Adding two counters and compute percent of total
151  * Round up, e.g. 0.000001 => 1%
152  */
153 static u32
154 compute_percent (u64 * two_counters, u64 total)
155 {
156  if (total == 0)
157  {
158  return 0;
159  }
160  else
161  {
162  return (((two_counters[0] + two_counters[1]) * 100) +
163  (total - 1)) / total;
164  }
165 }
166 
167 /*
168  * Display frame queue trace data gathered by threads.
169  */
170 static clib_error_t *
172 {
174  clib_error_t *error = NULL;
175  frame_queue_trace_t *fqt;
177  u32 num_fq;
178  u32 fqix;
179 
180  num_fq = vec_len (tm->frame_queue_traces);
181  if (num_fq == 0)
182  {
183  vlib_cli_output (vm, "No trace data for frame queues\n");
184  return error;
185  }
186 
187  if (histogram)
188  {
189  vlib_cli_output (vm, "0-1 2-3 4-5 6-7 8-9 10-11 12-13 14-15 "
190  "16-17 18-19 20-21 22-23 24-25 26-27 28-29 30-31\n");
191  }
192 
193  for (fqix = 0; fqix < num_fq; fqix++)
194  {
195  fqt = &(tm->frame_queue_traces[fqix]);
196 
197  vlib_cli_output (vm, "Thread %d %v\n", fqix,
198  vlib_worker_threads[fqix].name);
199 
200  if (fqt->written == 0)
201  {
202  vlib_cli_output (vm, " no trace data\n");
203  continue;
204  }
205 
206  if (histogram)
207  {
208  fqh = &(tm->frame_queue_histogram[fqix]);
209  u32 nelt;
210  u64 total = 0;
211 
212  for (nelt = 0; nelt < FRAME_QUEUE_MAX_NELTS; nelt++)
213  {
214  total += fqh->count[nelt];
215  }
216 
217  /*
218  * Print in pairs to condense the output.
219  * Allow entries with 0 counts to be clearly identified, by rounding up.
220  * Any non-zero value will be displayed as at least one percent. This
221  * also means the sum of percentages can be > 100, but that is fine. The
222  * histogram is counted from the last time "trace frame on" was issued.
223  */
224  vlib_cli_output (vm,
225  "%3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%% "
226  "%3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%%\n",
227  compute_percent (&fqh->count[0], total),
228  compute_percent (&fqh->count[2], total),
229  compute_percent (&fqh->count[4], total),
230  compute_percent (&fqh->count[6], total),
231  compute_percent (&fqh->count[8], total),
232  compute_percent (&fqh->count[10], total),
233  compute_percent (&fqh->count[12], total),
234  compute_percent (&fqh->count[14], total),
235  compute_percent (&fqh->count[16], total),
236  compute_percent (&fqh->count[18], total),
237  compute_percent (&fqh->count[20], total),
238  compute_percent (&fqh->count[22], total),
239  compute_percent (&fqh->count[24], total),
240  compute_percent (&fqh->count[26], total),
241  compute_percent (&fqh->count[28], total),
242  compute_percent (&fqh->count[30], total));
243  }
244  else
245  {
246  vlib_cli_output (vm,
247  " vector-threshold %d ring size %d in use %d\n",
248  fqt->threshold, fqt->nelts, fqt->n_in_use);
249  vlib_cli_output (vm, " head %12d head_hint %12d tail %12d\n",
250  fqt->head, fqt->head_hint, fqt->tail);
251  vlib_cli_output (vm,
252  " %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
253  fqt->n_vectors[0], fqt->n_vectors[1],
254  fqt->n_vectors[2], fqt->n_vectors[3],
255  fqt->n_vectors[4], fqt->n_vectors[5],
256  fqt->n_vectors[6], fqt->n_vectors[7],
257  fqt->n_vectors[8], fqt->n_vectors[9],
258  fqt->n_vectors[10], fqt->n_vectors[11],
259  fqt->n_vectors[12], fqt->n_vectors[13],
260  fqt->n_vectors[14], fqt->n_vectors[15]);
261 
262  if (fqt->nelts > 16)
263  {
264  vlib_cli_output (vm,
265  " %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
266  fqt->n_vectors[16], fqt->n_vectors[17],
267  fqt->n_vectors[18], fqt->n_vectors[19],
268  fqt->n_vectors[20], fqt->n_vectors[21],
269  fqt->n_vectors[22], fqt->n_vectors[23],
270  fqt->n_vectors[24], fqt->n_vectors[25],
271  fqt->n_vectors[26], fqt->n_vectors[27],
272  fqt->n_vectors[28], fqt->n_vectors[29],
273  fqt->n_vectors[30], fqt->n_vectors[31]);
274  }
275  }
276 
277  }
278  return error;
279 }
280 
281 static clib_error_t *
283  vlib_cli_command_t * cmd)
284 {
285  return show_frame_queue_internal (vm, 0);
286 }
287 
288 static clib_error_t *
290  vlib_cli_command_t * cmd)
291 {
292  return show_frame_queue_internal (vm, 1);
293 }
294 
295 /* *INDENT-OFF* */
296 VLIB_CLI_COMMAND (cmd_show_frame_queue_trace,static) = {
297  .path = "show frame-queue",
298  .short_help = "show frame-queue trace",
299  .function = show_frame_queue_trace,
300 };
301 /* *INDENT-ON* */
302 
303 /* *INDENT-OFF* */
304 VLIB_CLI_COMMAND (cmd_show_frame_queue_histogram,static) = {
305  .path = "show frame-queue histogram",
306  .short_help = "show frame-queue histogram",
307  .function = show_frame_queue_histogram,
308 };
309 /* *INDENT-ON* */
310 
311 
312 /*
313  * Modify the number of elements on the frame_queues
314  */
315 static clib_error_t *
317  vlib_cli_command_t * cmd)
318 {
319  clib_error_t *error = NULL;
320  u32 num_fq;
321  u32 fqix;
322  u32 nelts = 0;
323 
324  if ((unformat (input, "%d", &nelts) != 1) ||
325  ((nelts != 4) && (nelts != 8) && (nelts != 16) && (nelts != 32)))
326  {
327  return clib_error_return (0, "expecting 4,8,16,32");
328  }
329 
330  num_fq = vec_len (vlib_frame_queues);
331  if (num_fq == 0)
332  {
333  vlib_cli_output (vm, "No frame queues exist\n");
334  return error;
335  }
336 
337  for (fqix = 0; fqix < num_fq; fqix++)
338  {
339  vlib_frame_queues[fqix]->nelts = nelts;
340  }
341 
342  return error;
343 }
344 
345 /* *INDENT-OFF* */
346 VLIB_CLI_COMMAND (cmd_test_frame_queue_nelts,static) = {
347  .path = "test frame-queue nelts",
348  .short_help = "test frame-queue nelts (4,8,16,32)",
349  .function = test_frame_queue_nelts,
350 };
351 /* *INDENT-ON* */
352 
353 
354 /*
355  * Modify the max number of packets pulled off the frame queues
356  */
357 static clib_error_t *
359  vlib_cli_command_t * cmd)
360 {
361  clib_error_t *error = NULL;
362  u32 num_fq;
363  u32 fqix;
364  u32 threshold = 0;
365 
366  if (unformat (input, "%d", &threshold))
367  {
368  }
369  else
370  {
371  vlib_cli_output (vm, "expecting threshold value\n");
372  return error;
373  }
374 
375  if (threshold == 0)
376  threshold = ~0;
377 
378  num_fq = vec_len (vlib_frame_queues);
379  if (num_fq == 0)
380  {
381  vlib_cli_output (vm, "No frame queues exist\n");
382  return error;
383  }
384 
385  for (fqix = 0; fqix < num_fq; fqix++)
386  {
387  vlib_frame_queues[fqix]->vector_threshold = threshold;
388  }
389 
390  return error;
391 }
392 
393 /* *INDENT-OFF* */
394 VLIB_CLI_COMMAND (cmd_test_frame_queue_threshold,static) = {
395  .path = "test frame-queue threshold",
396  .short_help = "test frame-queue threshold N (0=no limit)",
397  .function = test_frame_queue_threshold,
398 };
399 /* *INDENT-ON* */
400 
401 
402 /*
403  * fd.io coding-style-patch-verification: ON
404  *
405  * Local Variables:
406  * eval: (c-set-style "gnu")
407  * End:
408  */
static u32 compute_percent(u64 *two_counters, u64 total)
Definition: threads_cli.c:154
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
#define NULL
Definition: clib.h:55
frame_queue_trace_t * frame_queue_traces
Definition: threads.h:311
static clib_error_t * show_frame_queue_trace(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: threads_cli.c:282
vlib_worker_thread_t * vlib_worker_threads
Definition: threads.h:110
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:407
static clib_error_t * test_frame_queue_nelts(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: threads_cli.c:316
static clib_error_t * show_frame_queue_internal(vlib_main_t *vm, u32 histogram)
Definition: threads_cli.c:171
u64 count[FRAME_QUEUE_MAX_NELTS]
Definition: node.h:717
unsigned long u64
Definition: types.h:89
vlib_frame_queue_t ** vlib_frame_queues
Definition: threads.h:142
struct lcore_config lcore_config[]
Definition: threads.c:45
#define FRAME_QUEUE_MAX_NELTS
Definition: node.h:701
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
i32 n_vectors[FRAME_QUEUE_MAX_NELTS]
Definition: node.h:712
static clib_error_t * show_threads_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: threads_cli.c:22
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
static clib_error_t * show_frame_queue_histogram(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: threads_cli.c:289
static clib_error_t * trace_frame_queue(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: threads_cli.c:89
frame_queue_nelt_counter_t * frame_queue_histogram
Definition: threads.h:312
unsigned int u32
Definition: types.h:88
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
vhost_vring_state_t state
Definition: vhost-user.h:81
static clib_error_t * test_frame_queue_threshold(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: threads_cli.c:358
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
vlib_thread_registration_t * registration
Definition: threads.h:102