FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
vlib_api_cli.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2018 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 
23 #include <vlibapi/api.h>
24 #include <vlibmemory/api.h>
25 
26 static clib_error_t *
28  unformat_input_t * input,
29  vlib_cli_command_t * cli_cmd)
30 {
31  u64 total_counts = 0;
32  int i;
33 
34  for (i = 0; i < SLEEP_N_BUCKETS; i++)
35  {
36  total_counts += vector_rate_histogram[i];
37  }
38 
39  if (total_counts == 0)
40  {
41  vlib_cli_output (vm, "No control-plane activity.");
42  return 0;
43  }
44 
45 #define _(n) \
46  do { \
47  f64 percent; \
48  percent = ((f64) vector_rate_histogram[SLEEP_##n##_US]) \
49  / (f64) total_counts; \
50  percent *= 100.0; \
51  vlib_cli_output (vm, "Sleep %3d us: %llu, %.2f%%",n, \
52  vector_rate_histogram[SLEEP_##n##_US], \
53  percent); \
54  } while (0);
56 #undef _
57 
58  return 0;
59 }
60 
61 /*?
62  * Display the binary api sleep-time histogram
63 ?*/
64 /* *INDENT-OFF* */
66 {
67  .path = "show api histogram",
68  .short_help = "show api histogram",
70 };
71 /* *INDENT-ON* */
72 
73 static clib_error_t *
75  unformat_input_t * input,
76  vlib_cli_command_t * cli_cmd)
77 {
78  int i;
79 
80  for (i = 0; i < SLEEP_N_BUCKETS; i++)
82  return 0;
83 }
84 
85 /*?
86  * Clear the binary api sleep-time histogram
87 ?*/
88 /* *INDENT-OFF* */
90 {
91  .path = "clear api histogram",
92  .short_help = "clear api histogram",
94 };
95 /* *INDENT-ON* */
96 
97 static clib_error_t *
99  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
100 {
101  vl_api_registration_t **regpp, *regp;
102  svm_queue_t *q;
103  char *health;
105  u32 *confused_indices = 0;
106 
107  if (!pool_elts (am->vl_clients))
108  goto socket_clients;
109  vlib_cli_output (vm, "Shared memory clients");
110  vlib_cli_output (vm, "%20s %8s %14s %18s %s",
111  "Name", "PID", "Queue Length", "Queue VA", "Health");
112 
113  /* *INDENT-OFF* */
114  pool_foreach (regpp, am->vl_clients)
115  {
116  regp = *regpp;
117 
118  if (regp)
119  {
120  if (regp->unanswered_pings > 0)
121  health = "questionable";
122  else
123  health = "OK";
124 
125  q = regp->vl_input_queue;
126 
127  vlib_cli_output (vm, "%20s %8d %14d 0x%016llx %s\n",
128  regp->name, q->consumer_pid, q->cursize,
129  q, health);
130  }
131  else
132  {
133  clib_warning ("NULL client registration index %d",
134  regpp - am->vl_clients);
135  vec_add1 (confused_indices, regpp - am->vl_clients);
136  }
137  }
138  /* *INDENT-ON* */
139 
140  /* This should "never happen," but if it does, fix it... */
141  if (PREDICT_FALSE (vec_len (confused_indices) > 0))
142  {
143  int i;
144  for (i = 0; i < vec_len (confused_indices); i++)
145  {
146  pool_put_index (am->vl_clients, confused_indices[i]);
147  }
148  }
149  vec_free (confused_indices);
150 
151  if (am->missing_clients)
152  vlib_cli_output (vm, "%u messages with missing clients",
153  am->missing_clients);
154 socket_clients:
156 
157  return 0;
158 }
159 
160 static clib_error_t *
162  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
163 {
165 
166  /* check if rx_trace and tx_trace are not null pointers */
167  if (am->rx_trace == 0)
168  {
169  vlib_cli_output (vm, "RX Trace disabled\n");
170  }
171  else
172  {
173  if (am->rx_trace->enabled == 0)
174  vlib_cli_output (vm, "RX Trace disabled\n");
175  else
176  vlib_cli_output (vm, "RX Trace enabled\n");
177  }
178 
179  if (am->tx_trace == 0)
180  {
181  vlib_cli_output (vm, "TX Trace disabled\n");
182  }
183  else
184  {
185  if (am->tx_trace->enabled == 0)
186  vlib_cli_output (vm, "TX Trace disabled\n");
187  else
188  vlib_cli_output (vm, "TX Trace enabled\n");
189  }
190 
191  return 0;
192 }
193 
194 /* *INDENT-OFF* */
196 {
197  .path = "show api",
198  .short_help = "Show API information",
199 };
200 /* *INDENT-ON* */
201 
202 /*?
203  * Display current api client connections
204 ?*/
205 /* *INDENT-OFF* */
207 {
208  .path = "show api clients",
209  .short_help = "Client information",
210  .function = vl_api_client_command,
211 };
212 /* *INDENT-ON* */
213 
214 /*?
215  * Display the current api message tracing status
216 ?*/
217 /* *INDENT-OFF* */
219 {
220  .path = "show api trace-status",
221  .short_help = "Display API trace status",
222  .function = vl_api_status_command,
223 };
224 /* *INDENT-ON* */
225 
226 static clib_error_t *
228  unformat_input_t * input,
229  vlib_cli_command_t * cli_cmd)
230 {
232  int i;
233  int verbose = 0;
234 
235  if (unformat (input, "verbose"))
236  verbose = 1;
237 
238 
239  if (verbose == 0)
240  vlib_cli_output (vm, "%-4s %s", "ID", "Name");
241  else
242  vlib_cli_output (vm, "%-4s %-40s %6s %7s", "ID", "Name", "Bounce",
243  "MP-safe");
244 
245  for (i = 1; i < vec_len (am->msg_names); i++)
246  {
247  if (verbose == 0)
248  {
249  vlib_cli_output (vm, "%-4d %s", i,
250  am->msg_names[i] ? am->msg_names[i] :
251  " [no handler]");
252  }
253  else
254  {
255  vlib_cli_output (vm, "%-4d %-40s %6d %7d", i,
256  am->msg_names[i] ? am->msg_names[i] :
257  " [no handler]", am->message_bounce[i],
258  am->is_mp_safe[i]);
259  }
260  }
261 
262  return 0;
263 }
264 
265 /*?
266  * Display the current api message decode tables
267 ?*/
268 /* *INDENT-OFF* */
270 {
271  .path = "show api message-table",
272  .short_help = "Message Table",
273  .function = vl_api_message_table_command,
274 };
275 /* *INDENT-ON* */
276 
277 static int
279 {
280  int len0, len1, clen;
281 
282  len0 = vec_len (a0->name);
283  len1 = vec_len (a1->name);
284  clen = len0 < len1 ? len0 : len1;
285  return (strncmp ((char *) a0->name, (char *) a1->name, clen));
286 }
287 
288 static u8 *
289 format_api_msg_range (u8 * s, va_list * args)
290 {
291  vl_api_msg_range_t *rp = va_arg (*args, vl_api_msg_range_t *);
292 
293  if (rp == 0)
294  s = format (s, "%-50s%9s%9s", "Name", "First-ID", "Last-ID");
295  else
296  s = format (s, "%-50s%9d%9d", rp->name, rp->first_msg_id,
297  rp->last_msg_id);
298 
299  return s;
300 }
301 
302 static clib_error_t *
304  unformat_input_t * input,
305  vlib_cli_command_t * cli_cmd)
306 {
308  vl_api_msg_range_t *rp = 0;
309  int i;
310 
311  if (vec_len (am->msg_ranges) == 0)
312  {
313  vlib_cli_output (vm, "No plugin API message ranges configured...");
314  return 0;
315  }
316 
317  rp = vec_dup (am->msg_ranges);
318 
320 
321  vlib_cli_output (vm, "Plugin API message ID ranges...\n");
322  vlib_cli_output (vm, "%U", format_api_msg_range, 0 /* header */ );
323 
324  for (i = 0; i < vec_len (rp); i++)
325  vlib_cli_output (vm, "%U", format_api_msg_range, rp + i);
326 
327  vec_free (rp);
328 
329  return 0;
330 }
331 
332 /*?
333  * Display the plugin binary API message range table
334 ?*/
335 /* *INDENT-OFF* */
337 {
338  .path = "show api plugin",
339  .short_help = "show api plugin",
340  .function = vl_api_show_plugin_command,
341 };
342 /* *INDENT-ON* */
343 
344 typedef enum
345 {
351 
352 u8 *
353 format_vl_msg_api_trace_status (u8 * s, va_list * args)
354 {
355  api_main_t *am = va_arg (*args, api_main_t *);
357  vl_api_trace_t *tp;
358  char *trace_name;
359 
360  switch (which)
361  {
362  case VL_API_TRACE_TX:
363  tp = am->tx_trace;
364  trace_name = "TX trace";
365  break;
366 
367  case VL_API_TRACE_RX:
368  tp = am->rx_trace;
369  trace_name = "RX trace";
370  break;
371 
372  default:
373  abort ();
374  }
375 
376  if (tp == 0)
377  {
378  s = format (s, "%s: not yet configured.\n", trace_name);
379  return s;
380  }
381 
382  s = format (s, "%s: used %d of %d items, %s enabled, %s wrapped\n",
383  trace_name, vec_len (tp->traces), tp->nitems,
384  tp->enabled ? "is" : "is not", tp->wrapped ? "has" : "has not");
385  return s;
386 }
387 
389  __attribute__ ((weak));
390 void
392 {
393 }
394 
395 static void
397  u32 first_index, u32 last_index,
399 {
400  vl_api_trace_file_header_t *hp;
401  int i, fd;
402  struct stat statb;
403  size_t file_size;
404  u8 *msg;
406  u8 *tmpbuf = 0;
407  u32 nitems, nitems_msgtbl;
408  void **saved_print_handlers = 0;
409 
410  fd = open ((char *) filename, O_RDONLY);
411 
412  if (fd < 0)
413  {
414  vlib_cli_output (vm, "Couldn't open %s\n", filename);
415  return;
416  }
417 
418  if (fstat (fd, &statb) < 0)
419  {
420  vlib_cli_output (vm, "Couldn't stat %s\n", filename);
421  close (fd);
422  return;
423  }
424 
425  if (!(statb.st_mode & S_IFREG) || (statb.st_size < sizeof (*hp)))
426  {
427  vlib_cli_output (vm, "File not plausible: %s\n", filename);
428  close (fd);
429  return;
430  }
431 
432  file_size = statb.st_size;
433  file_size = (file_size + 4095) & ~(4095);
434 
435  hp = mmap (0, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
436 
437  if (hp == (vl_api_trace_file_header_t *) MAP_FAILED)
438  {
439  vlib_cli_output (vm, "mmap failed: %s\n", filename);
440  close (fd);
441  return;
442  }
443  close (fd);
444 
445  CLIB_MEM_UNPOISON (hp, file_size);
446 
447  nitems = ntohl (hp->nitems);
448 
449  if (last_index == (u32) ~ 0)
450  {
451  last_index = nitems - 1;
452  }
453 
454  if (first_index >= nitems || last_index >= nitems)
455  {
456  vlib_cli_output (vm, "Range (%d, %d) outside file range (0, %d)\n",
457  first_index, last_index, nitems - 1);
458  munmap (hp, file_size);
459  return;
460  }
461  if (hp->wrapped)
463  "Note: wrapped/incomplete trace, results may vary\n");
464 
465  if (which == CUSTOM_DUMP)
466  {
467  saved_print_handlers = (void **) vec_dup (am->msg_print_handlers);
469  }
470 
471  msg = (u8 *) (hp + 1);
472 
473  u16 *msgid_vec = 0;
474  serialize_main_t _sm, *sm = &_sm;
475  u32 msgtbl_size = ntohl (hp->msgtbl_size);
476  u8 *name_and_crc;
477 
478  unserialize_open_data (sm, msg, msgtbl_size);
479  unserialize_integer (sm, &nitems_msgtbl, sizeof (u32));
480 
481  for (i = 0; i < nitems_msgtbl; i++)
482  {
484  unserialize_cstring (sm, (char **) &name_and_crc);
485  u16 msg_index2 = vl_msg_api_get_msg_index (name_and_crc);
486  vec_validate (msgid_vec, msg_index);
487  msgid_vec[msg_index] = msg_index2;
488  }
489 
490  msg += msgtbl_size;
491 
492  for (i = 0; i < first_index; i++)
493  {
494  trace_cfg_t *cfgp;
495  int size;
496  u16 msg_id;
497 
498  size = clib_host_to_net_u32 (*(u32 *) msg);
499  msg += sizeof (u32);
500 
501  msg_id = ntohs (*((u16 *) msg));
502  if (msg_id < vec_len (msgid_vec))
503  msg_id = msgid_vec[msg_id];
504  cfgp = am->api_trace_cfg + msg_id;
505  if (!cfgp)
506  {
507  vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id);
508  munmap (hp, file_size);
509  return;
510  }
511  msg += size;
512  }
513 
514  if (which == REPLAY)
515  am->replay_in_progress = 1;
516 
517  for (; i <= last_index; i++)
518  {
519  trace_cfg_t *cfgp;
520  u16 msg_id;
521  int size;
522 
523  if (which == DUMP)
524  vlib_cli_output (vm, "---------- trace %d -----------\n", i);
525 
526  size = clib_host_to_net_u32 (*(u32 *) msg);
527  msg += sizeof (u32);
528 
529  msg_id = ntohs (*((u16 *) msg));
530  if (msg_id < vec_len (msgid_vec))
531  {
532  msg_id = msgid_vec[msg_id];
533  }
534 
535  cfgp = am->api_trace_cfg + msg_id;
536  if (!cfgp)
537  {
538  vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id);
539  munmap (hp, file_size);
540  vec_free (tmpbuf);
541  am->replay_in_progress = 0;
542  return;
543  }
544 
545  /* Copy the buffer (from the read-only mmap'ed file) */
546  vec_validate (tmpbuf, size - 1 + sizeof (uword));
547  clib_memcpy (tmpbuf + sizeof (uword), msg, size);
548  clib_memset (tmpbuf, 0xf, sizeof (uword));
549 
550  /*
551  * Endian swap if needed. All msg data is supposed to be in
552  * network byte order.
553  */
554  if (((which == DUMP || which == CUSTOM_DUMP)
556  {
557  void (*endian_fp) (void *);
558  if (msg_id >= vec_len (am->msg_endian_handlers)
559  || (am->msg_endian_handlers[msg_id] == 0))
560  {
561  vlib_cli_output (vm, "Ugh: msg id %d no endian swap\n", msg_id);
562  munmap (hp, file_size);
563  vec_free (tmpbuf);
564  am->replay_in_progress = 0;
565  return;
566  }
567  endian_fp = am->msg_endian_handlers[msg_id];
568  (*endian_fp) (tmpbuf + sizeof (uword));
569  }
570 
571  /* msg_id always in network byte order */
573  {
574  u16 *msg_idp = (u16 *) (tmpbuf + sizeof (uword));
575  *msg_idp = msg_id;
576  }
577 
578  switch (which)
579  {
580  case CUSTOM_DUMP:
581  case DUMP:
582  if (msg_id < vec_len (am->msg_print_handlers) &&
583  am->msg_print_handlers[msg_id])
584  {
585  u8 *(*print_fp) (void *, void *);
586 
587  print_fp = (void *) am->msg_print_handlers[msg_id];
588  (*print_fp) (tmpbuf + sizeof (uword), vm);
589  }
590  else
591  {
592  vlib_cli_output (vm, "Skipping msg id %d: no print fcn\n",
593  msg_id);
594  break;
595  }
596  break;
597 
598  case INITIALIZERS:
599  if (msg_id < vec_len (am->msg_print_handlers) &&
600  am->msg_print_handlers[msg_id])
601  {
602  u8 *s;
603  int j;
604  u8 *(*print_fp) (void *, void *);
605 
606  print_fp = (void *) am->msg_print_handlers[msg_id];
607 
608  vlib_cli_output (vm, "/*");
609 
610  (*print_fp) (tmpbuf + sizeof (uword), vm);
611  vlib_cli_output (vm, "*/\n");
612 
613  s = format (0, "static u8 * vl_api_%s_%d[%d] = {",
614  am->msg_names[msg_id], i,
615  am->api_trace_cfg[msg_id].size);
616 
617  for (j = 0; j < am->api_trace_cfg[msg_id].size; j++)
618  {
619  if ((j & 7) == 0)
620  s = format (s, "\n ");
621  s = format (s, "0x%02x,", tmpbuf[sizeof (uword) + j]);
622  }
623  s = format (s, "\n};\n%c", 0);
624  vlib_cli_output (vm, (char *) s);
625  vec_free (s);
626  }
627  break;
628 
629  case REPLAY:
630  if (msg_id < vec_len (am->msg_print_handlers) &&
631  am->msg_print_handlers[msg_id] && cfgp->replay_enable)
632  {
633  void (*handler) (void *, vlib_main_t *);
634 
635  handler = (void *) am->msg_handlers[msg_id];
636 
637  if (!am->is_mp_safe[msg_id])
639  (*handler) (tmpbuf + sizeof (uword), vm);
640  if (!am->is_mp_safe[msg_id])
642  }
643  else
644  {
645  if (cfgp->replay_enable)
646  vlib_cli_output (vm, "Skipping msg id %d: no handler\n",
647  msg_id);
648  break;
649  }
650  break;
651  }
652 
653  _vec_len (tmpbuf) = 0;
654  msg += size;
655  }
656 
657  if (saved_print_handlers)
658  {
659  clib_memcpy (am->msg_print_handlers, saved_print_handlers,
660  vec_len (am->msg_print_handlers) * sizeof (void *));
661  vec_free (saved_print_handlers);
662  }
663 
664  munmap (hp, file_size);
665  vec_free (tmpbuf);
666  am->replay_in_progress = 0;
667 }
668 
669 /** api_trace_command_fn - control the binary API trace / replay feature
670 
671  Note: this command MUST be marked thread-safe. Replay with
672  multiple worker threads depends in many cases on worker thread
673  graph replica maintenance. If we (implicitly) assert a worker
674  thread barrier at the debug CLI level, all graph replica changes
675  are deferred until the replay operation completes. If an interface
676  is deleted, the wheels fall off.
677  */
678 
679 static clib_error_t *
681  unformat_input_t * input, vlib_cli_command_t * cmd)
682 {
683  unformat_input_t _line_input, *line_input = &_line_input;
684  u32 nitems = 256 << 10;
687  u8 *filename = 0;
688  u8 *chroot_filename = 0;
689  u32 first = 0;
690  u32 last = (u32) ~ 0;
691  FILE *fp;
692  int rv;
693 
694  /* Get a line of input. */
695  if (!unformat_user (input, unformat_line_input, line_input))
696  return 0;
697 
698  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
699  {
700  if (unformat (line_input, "on") || unformat (line_input, "enable"))
701  {
702  if (unformat (line_input, "nitems %d", &nitems))
703  ;
706  vl_msg_api_trace_onoff (am, which, 1 /* on */ );
708  }
709  else if (unformat (line_input, "off"))
710  {
714  }
715  else if (unformat (line_input, "save %s", &filename))
716  {
717  if (strstr ((char *) filename, "..")
718  || index ((char *) filename, '/'))
719  {
720  vlib_cli_output (vm, "illegal characters in filename '%s'",
721  filename);
722  goto out;
723  }
724 
725  chroot_filename = format (0, "/tmp/%s%c", filename, 0);
726 
727  vec_free (filename);
728 
729  fp = fopen ((char *) chroot_filename, "w");
730  if (fp == NULL)
731  {
732  vlib_cli_output (vm, "Couldn't create %s\n", chroot_filename);
733  goto out;
734  }
736  rv = vl_msg_api_trace_save (am, which, fp);
738  fclose (fp);
739  if (rv == -1)
740  vlib_cli_output (vm, "API Trace data not present\n");
741  else if (rv == -2)
742  vlib_cli_output (vm, "File for writing is closed\n");
743  else if (rv == -10)
744  vlib_cli_output (vm, "Error while writing header to file\n");
745  else if (rv == -11)
746  vlib_cli_output (vm, "Error while writing trace to file\n");
747  else if (rv == -12)
749  "Error while writing end of buffer trace to file\n");
750  else if (rv == -13)
752  "Error while writing start of buffer trace to file\n");
753  else if (rv < 0)
754  vlib_cli_output (vm, "Unknown error while saving: %d", rv);
755  else
756  vlib_cli_output (vm, "API trace saved to %s\n", chroot_filename);
757  goto out;
758  }
759  else if (unformat (line_input, "dump %s", &filename))
760  {
761  vl_msg_api_process_file (vm, filename, first, last, DUMP);
762  }
763  else if (unformat (line_input, "custom-dump %s", &filename))
764  {
766  }
767  else if (unformat (line_input, "replay %s", &filename))
768  {
769  vl_msg_api_process_file (vm, filename, first, last, REPLAY);
770  }
771  else if (unformat (line_input, "initializers %s", &filename))
772  {
774  }
775  else if (unformat (line_input, "tx"))
776  {
778  }
779  else if (unformat (line_input, "first %d", &first))
780  {
781  ;
782  }
783  else if (unformat (line_input, "last %d", &last))
784  {
785  ;
786  }
787  else if (unformat (line_input, "status"))
788  {
790  am, which);
791  }
792  else if (unformat (line_input, "free"))
793  {
798  }
799  else if (unformat (line_input, "post-mortem-on"))
801  else if (unformat (line_input, "post-mortem-off"))
803  else
804  return clib_error_return (0, "unknown input `%U'",
805  format_unformat_error, input);
806  }
807 out:
808  vec_free (filename);
809  vec_free (chroot_filename);
810  unformat_free (line_input);
811  return 0;
812 }
813 
814 /*?
815  * Display, replay, or save a binary API trace
816 ?*/
817 
818 /* *INDENT-OFF* */
820 {
821  .path = "api trace",
822  .short_help = "api trace [on|off][first <n>][last <n>][status][free]"
823  "[post-mortem-on][dump|custom-dump|save|replay <file>]",
824  .function = api_trace_command_fn,
825  .is_mp_safe = 1,
826 };
827 /* *INDENT-ON* */
828 
829 static clib_error_t *
831  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
832 {
833  u32 nitems = 1024;
836 
838  {
839  if (unformat (input, "rx nitems %u", &nitems) || unformat (input, "rx"))
840  goto configure;
841  else if (unformat (input, "tx nitems %u", &nitems)
842  || unformat (input, "tx"))
843  {
845  goto configure;
846  }
847  else if (unformat (input, "on rx"))
848  {
850  }
851  else if (unformat (input, "on tx"))
852  {
854  }
855  else if (unformat (input, "on"))
856  {
858  }
859  else if (unformat (input, "off"))
860  {
863  }
864  else if (unformat (input, "free"))
865  {
870  }
871  else if (unformat (input, "debug on"))
872  {
873  am->msg_print_flag = 1;
874  }
875  else if (unformat (input, "debug off"))
876  {
877  am->msg_print_flag = 0;
878  }
879  else
880  return clib_error_return (0, "unknown input `%U'",
881  format_unformat_error, input);
882  }
883  return 0;
884 
885 configure:
886  if (vl_msg_api_trace_configure (am, which, nitems))
887  {
888  vlib_cli_output (vm, "warning: trace configure error (%d, %d)",
889  which, nitems);
890  }
891 
892  return 0;
893 }
894 
895 /*?
896  * Control the binary API trace mechanism
897 ?*/
898 /* *INDENT-OFF* */
900 {
901  .path = "set api-trace",
902  .short_help = "API trace [on][on tx][on rx][off][free][debug on][debug off]",
903  .function = vl_api_trace_command,
904 };
905 /* *INDENT-ON* */
906 
907 static clib_error_t *
909 {
910  u32 nitems = 256 << 10;
913 
915  {
916  if (unformat (input, "on") || unformat (input, "enable"))
917  {
918  if (unformat (input, "nitems %d", &nitems))
919  ;
921  vl_msg_api_trace_onoff (am, which, 1 /* on */ );
923  }
924  else if (unformat (input, "save-api-table %s",
925  &am->save_msg_table_filename))
926  ;
927  else
928  return clib_error_return (0, "unknown input `%U'",
929  format_unformat_error, input);
930  }
931  return 0;
932 }
933 
934 /*?
935  * This module has three configuration parameters:
936  * "on" or "enable" - enables binary api tracing
937  * "nitems <nnn>" - sets the size of the circular buffer to <nnn>
938  * "save-api-table <filename>" - dumps the API message table to /tmp/<filename>
939 ?*/
941 
942 static clib_error_t *
944 {
946  u32 nitems;
947 
949  {
950  if (unformat (input, "length %d", &nitems) ||
951  (unformat (input, "len %d", &nitems)))
952  {
953  if (nitems >= 1024)
954  am->vlib_input_queue_length = nitems;
955  else
956  clib_warning ("vlib input queue length %d too small, ignored",
957  nitems);
958  }
959  else
960  return clib_error_return (0, "unknown input `%U'",
961  format_unformat_error, input);
962  }
963  return 0;
964 }
965 
967 
968 static u8 *
970 {
971  u8 *rv;
972 
973  rv = vec_dup (s);
974 
975  while (vec_len (rv) && rv[vec_len (rv)] != '_')
976  _vec_len (rv)--;
977 
978  rv[vec_len (rv)] = 0;
979 
980  return rv;
981 }
982 
983 static u8 *
985 {
986  int i;
987  u8 *rv;
988 
989  rv = vec_dup (s);
990 
991  for (i = vec_len (rv) - 1; i >= 0; i--)
992  {
993  if (rv[i] == '_')
994  {
995  vec_delete (rv, i + 1, 0);
996  break;
997  }
998  }
999  return rv;
1000 }
1001 
1002 typedef struct
1003 {
1008  int which;
1010 
1011 static int
1012 table_id_cmp (void *a1, void *a2)
1013 {
1014  msg_table_unserialize_t *n1 = a1;
1015  msg_table_unserialize_t *n2 = a2;
1016 
1017  return (n1->msg_index - n2->msg_index);
1018 }
1019 
1020 static int
1021 table_name_and_crc_cmp (void *a1, void *a2)
1022 {
1023  msg_table_unserialize_t *n1 = a1;
1024  msg_table_unserialize_t *n2 = a2;
1025 
1026  return strcmp ((char *) n1->name_and_crc, (char *) n2->name_and_crc);
1027 }
1028 
1029 static clib_error_t *
1031  unformat_input_t * input,
1032  vlib_cli_command_t * cmd)
1033 {
1034  u8 *filename = 0;
1036  serialize_main_t _sm, *sm = &_sm;
1038  u32 nmsgs;
1039  u32 msg_index;
1040  u8 *name_and_crc;
1041  int compare_current = 0;
1042  int numeric_sort = 0;
1043  msg_table_unserialize_t *table = 0, *item;
1044  u32 i;
1045  u32 ndifferences = 0;
1046 
1047  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1048  {
1049  if (unformat (input, "file %s", &filename))
1050  ;
1051  else if (unformat (input, "compare-current")
1052  || unformat (input, "compare"))
1053  compare_current = 1;
1054  else if (unformat (input, "numeric"))
1055  numeric_sort = 1;
1056  else
1057  return clib_error_return (0, "unknown input `%U'",
1058  format_unformat_error, input);
1059  }
1060 
1061  if (numeric_sort && compare_current)
1062  return clib_error_return
1063  (0, "Comparison and numeric sorting are incompatible");
1064 
1065  if (filename == 0)
1066  return clib_error_return (0, "File not specified");
1067 
1068  /* Load the serialized message table from the table dump */
1069 
1070  error = unserialize_open_clib_file (sm, (char *) filename);
1071 
1072  if (error)
1073  return error;
1074 
1075  unserialize_integer (sm, &nmsgs, sizeof (u32));
1076 
1077  for (i = 0; i < nmsgs; i++)
1078  {
1080  unserialize_cstring (sm, (char **) &name_and_crc);
1081  vec_add2 (table, item, 1);
1082  item->msg_index = msg_index;
1083  item->name_and_crc = name_and_crc;
1084  item->name = extract_name (name_and_crc);
1085  item->crc = extract_crc (name_and_crc);
1086  item->which = 0; /* file */
1087  }
1088  unserialize_close (sm);
1089 
1090  /* Compare with the current image? */
1091  if (compare_current)
1092  {
1093  /* Append the current message table */
1094  u8 *tblv = vl_api_serialize_message_table (am, 0);
1095 
1096  serialize_open_vector (sm, tblv);
1097  unserialize_integer (sm, &nmsgs, sizeof (u32));
1098 
1099  for (i = 0; i < nmsgs; i++)
1100  {
1102  unserialize_cstring (sm, (char **) &name_and_crc);
1103 
1104  vec_add2 (table, item, 1);
1105  item->msg_index = msg_index;
1106  item->name_and_crc = name_and_crc;
1107  item->name = extract_name (name_and_crc);
1108  item->crc = extract_crc (name_and_crc);
1109  item->which = 1; /* current_image */
1110  }
1111  vec_free (tblv);
1112  }
1113 
1114  /* Sort the table. */
1115  if (numeric_sort)
1117  else
1119 
1120  if (compare_current)
1121  {
1122  u8 *dashes = 0;
1123  ndifferences = 0;
1124 
1125  /*
1126  * In this case, the recovered table will have two entries per
1127  * API message. So, if entries i and i+1 match, the message definitions
1128  * are identical. Otherwise, the crc is different, or a message is
1129  * present in only one of the tables.
1130  */
1131  vlib_cli_output (vm, "%-60s | %s", "Message Name", "Result");
1132  vec_validate_init_empty (dashes, 60, '-');
1133  vec_terminate_c_string (dashes);
1134  vlib_cli_output (vm, "%60s-|-%s", dashes, "-----------------");
1135  vec_free (dashes);
1136  for (i = 0; i < vec_len (table);)
1137  {
1138  /* Last message lonely? */
1139  if (i == vec_len (table) - 1)
1140  {
1141  ndifferences++;
1142  goto last_unique;
1143  }
1144 
1145  /* Identical pair? */
1146  if (!strncmp
1147  ((char *) table[i].name_and_crc,
1148  (char *) table[i + 1].name_and_crc,
1149  vec_len (table[i].name_and_crc)))
1150  {
1151  i += 2;
1152  continue;
1153  }
1154 
1155  ndifferences++;
1156 
1157  /* Only in one of two tables? */
1158  if (i + 1 == vec_len (table)
1159  || strcmp ((char *) table[i].name, (char *) table[i + 1].name))
1160  {
1161  last_unique:
1162  vlib_cli_output (vm, "%-60s | only in %s",
1163  table[i].name, table[i].which ?
1164  "image" : "file");
1165  i++;
1166  continue;
1167  }
1168  /* In both tables, but with different signatures */
1169  vlib_cli_output (vm, "%-60s | definition changed", table[i].name);
1170  i += 2;
1171  }
1172  if (ndifferences == 0)
1173  vlib_cli_output (vm, "No api message signature differences found.");
1174  else
1175  vlib_cli_output (vm, "\nFound %u api message signature differences",
1176  ndifferences);
1177  goto cleanup;
1178  }
1179 
1180  /* Dump the table, sorted as shown above */
1181  vlib_cli_output (vm, "%=60s %=8s %=10s", "Message name", "MsgID", "CRC");
1182 
1183  for (i = 0; i < vec_len (table); i++)
1184  {
1185  item = table + i;
1186  vlib_cli_output (vm, "%-60s %8u %10s", item->name,
1187  item->msg_index, item->crc);
1188  }
1189 
1190 cleanup:
1191  for (i = 0; i < vec_len (table); i++)
1192  {
1193  vec_free (table[i].name_and_crc);
1194  vec_free (table[i].name);
1195  vec_free (table[i].crc);
1196  }
1197 
1198  vec_free (table);
1199 
1200  return 0;
1201 }
1202 
1203 /*?
1204  * Displays a serialized API message decode table, sorted by message name
1205  *
1206  * @cliexpar
1207  * @cliexstart{show api dump file <filename>}
1208  * Message name MsgID CRC
1209  * accept_session 407 8e2a127e
1210  * accept_session_reply 408 67d8c22a
1211  * add_node_next 549 e4202993
1212  * add_node_next_reply 550 e89d6eed
1213  * etc.
1214  * @cliexend
1215 ?*/
1216 
1217 /*?
1218  * Compares a serialized API message decode table with the current image
1219  *
1220  * @cliexpar
1221  * @cliexstart{show api dump file <filename> compare}
1222  * ip_add_del_route definition changed
1223  * ip_table_add_del definition changed
1224  * l2_macs_event only in image
1225  * vnet_ip4_fib_counters only in file
1226  * vnet_ip4_nbr_counters only in file
1227  * @cliexend
1228 ?*/
1229 
1230 /*?
1231  * Display a serialized API message decode table, compare a saved
1232  * decode table with the current image, to establish API differences.
1233  *
1234 ?*/
1235 /* *INDENT-OFF* */
1237 {
1238  .path = "show api dump",
1239  .short_help = "show api dump file <filename> [numeric | compare-current]",
1240  .function = dump_api_table_file_command_fn,
1241 };
1242 
1243 /* *INDENT-ON* */
1244 /*
1245  * fd.io coding-style-patch-verification: ON
1246  *
1247  * Local Variables:
1248  * eval: (c-set-style "gnu")
1249  * End:
1250  */
extract_name
static u8 * extract_name(u8 *s)
Definition: vlib_api_cli.c:969
vl_api_status_command
static clib_error_t * vl_api_status_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: vlib_api_cli.c:161
vl_msg_api_barrier_release
void vl_msg_api_barrier_release(void)
Definition: api_shared.c:432
msg_table_unserialize_t::msg_index
u32 msg_index
Definition: vlib_api_cli.c:1007
trace
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:899
api.h
vlib_worker_thread_barrier_release
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1386
unformat_user
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
ntohs
#define ntohs(x)
Definition: af_xdp.bpf.c:29
cli_show_api_histogram_command
static vlib_cli_command_t cli_show_api_histogram_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_histogram_command)
Definition: vlib_api_cli.c:65
clib_memcpy
#define clib_memcpy(d, s, n)
Definition: string.h:197
vl_api_replay_t
vl_api_replay_t
Definition: vlib_api_cli.c:344
vl_api_msg_range_t::name
u8 * name
name of the plugin
Definition: api_common.h:116
cli_show_api_status_command
static vlib_cli_command_t cli_show_api_status_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_status_command)
Definition: vlib_api_cli.c:218
cli_show_api_command
static vlib_cli_command_t cli_show_api_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_command)
Definition: vlib_api_cli.c:195
unformat_line_input
unformat_function_t unformat_line_input
Definition: format.h:275
name
string name[64]
Definition: fib.api:25
vl_msg_api_custom_dump_configure
void vl_msg_api_custom_dump_configure(api_main_t *am)
Definition: vlib_api_cli.c:391
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
vlib_cli_command_t::path
char * path
Definition: cli.h:96
foreach_histogram_bucket
#define foreach_histogram_bucket
Definition: api.h:137
svm_queue_t
struct _svm_queue svm_queue_t
VL_API_TRACE_RX
@ VL_API_TRACE_RX
Definition: api_common.h:107
u16
unsigned short u16
Definition: types.h:57
vl_api_trace_t::traces
u8 ** traces
Trace ring.
Definition: api_common.h:100
first
static heap_elt_t * first(heap_header_t *h)
Definition: heap.c:59
am
app_main_t * am
Definition: application.c:489
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
api.h
vl_api_registration_::vl_input_queue
svm_queue_t * vl_input_queue
shared memory only: pointer to client input queue
Definition: api_common.h:63
vec_delete
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:875
vl_api_trace_which_t
vl_api_trace_which_t
Trace RX / TX enum.
Definition: api_common.h:104
vl_api_msg_range_t::last_msg_id
u16 last_msg_id
last assigned message ID
Definition: api_common.h:118
VL_API_TRACE_TX
@ VL_API_TRACE_TX
Definition: api_common.h:106
unformat_input_t
struct _unformat_input_t unformat_input_t
serialize_open_vector
__clib_export void serialize_open_vector(serialize_main_t *m, u8 *vector)
Definition: serialize.c:909
serialize_main_t
Definition: serialize.h:144
api_trace_command_fn
static clib_error_t * api_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
api_trace_command_fn - control the binary API trace / replay feature
Definition: vlib_api_cli.c:680
pool_put_index
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:337
error
Definition: cJSON.c:88
msg_table_unserialize_t::which
int which
Definition: vlib_api_cli.c:1008
api_trace_command
static vlib_cli_command_t api_trace_command
(constructor) VLIB_CLI_COMMAND (api_trace_command)
Definition: vlib_api_cli.c:819
table_name_and_crc_cmp
static int table_name_and_crc_cmp(void *a1, void *a2)
Definition: vlib_api_cli.c:1021
VLIB_CONFIG_FUNCTION
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:181
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
vl_api_trace_t::enabled
u8 enabled
trace is enabled
Definition: api_common.h:95
vl_api_show_plugin_command
static clib_error_t * vl_api_show_plugin_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: vlib_api_cli.c:303
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
vl_msg_api_trace_save
int vl_msg_api_trace_save(api_main_t *am, vl_api_trace_which_t which, FILE *fp)
Definition: api_shared.c:227
dump_api_table_file
static vlib_cli_command_t dump_api_table_file
(constructor) VLIB_CLI_COMMAND (dump_api_table_file)
Definition: vlib_api_cli.c:1236
which
int which
Definition: cJSON.h:234
msg_table_unserialize_t
Definition: vlib_api_cli.c:1002
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
trace_cfg_t
Trace configuration for a single message.
Definition: api_common.h:82
unformat_free
static void unformat_free(unformat_input_t *i)
Definition: format.h:155
vl_msg_api_trace_configure
int vl_msg_api_trace_configure(api_main_t *am, vl_api_trace_which_t which, u32 nitems)
Definition: api_shared.c:366
vl_api_registration_::unanswered_pings
int unanswered_pings
Definition: api_common.h:59
vec_add2
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:644
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
CUSTOM_DUMP
@ CUSTOM_DUMP
Definition: vlib_api_cli.c:347
unserialize_open_clib_file
__clib_export clib_error_t * unserialize_open_clib_file(serialize_main_t *m, char *file)
Definition: serialize.c:1242
vec_dup
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:444
dump_api_table_file_command_fn
static clib_error_t * dump_api_table_file_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: vlib_api_cli.c:1030
vlib_worker_thread_barrier_sync
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:194
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
vl_api_registration_
An API client registration, only in vpp/vlib.
Definition: api_common.h:47
unformat_check_input
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
vlib_config_function_runtime_t
Definition: init.h:68
api_trace_config_fn
static clib_error_t * api_trace_config_fn(vlib_main_t *vm, unformat_input_t *input)
Definition: vlib_api_cli.c:908
cli_show_api_plugin_command
static vlib_cli_command_t cli_show_api_plugin_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_plugin_command)
Definition: vlib_api_cli.c:336
unserialize_integer
static void unserialize_integer(serialize_main_t *m, void *x, u32 n_bytes)
Definition: serialize.h:201
uword
u64 uword
Definition: types.h:112
last
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
if
if(node->flags &VLIB_NODE_FLAG_TRACE) vnet_interface_output_trace(vm
DUMP
@ DUMP
Definition: vlib_api_cli.c:346
vlibapi_get_main
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:390
i
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
vl_msg_api_get_msg_index
u32 vl_msg_api_get_msg_index(u8 *name_and_crc)
Definition: api_shared.c:1119
vl_sock_api_dump_clients
void vl_sock_api_dump_clients(vlib_main_t *vm, api_main_t *am)
Definition: socket_api.c:72
vl_api_serialize_message_table
u8 * vl_api_serialize_message_table(api_main_t *am, u8 *vector)
Definition: api_shared.c:204
format_unformat_error
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
REPLAY
@ REPLAY
Definition: vlib_api_cli.c:348
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
VLIB_CLI_COMMAND
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
cli_clear_api_histogram_command
static vlib_cli_command_t cli_clear_api_histogram_command
(constructor) VLIB_CLI_COMMAND (cli_clear_api_histogram_command)
Definition: vlib_api_cli.c:89
msg_table_unserialize_t::name_and_crc
u8 * name_and_crc
Definition: vlib_api_cli.c:1004
vl_api_trace_command
static clib_error_t * vl_api_trace_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: vlib_api_cli.c:830
vl_api_show_histogram_command
static clib_error_t * vl_api_show_histogram_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: vlib_api_cli.c:27
vlib_cli_output
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
unserialize_open_data
__clib_export void unserialize_open_data(serialize_main_t *m, u8 *data, uword n_data_bytes)
Definition: serialize.c:891
vl_api_trace_t
API trace state.
Definition: api_common.h:92
api_main_t
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:228
vl_api_clear_histogram_command
static clib_error_t * vl_api_clear_histogram_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: vlib_api_cli.c:74
unserialize_cstring
__clib_export void unserialize_cstring(serialize_main_t *m, char **s)
Definition: serialize.c:178
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
size
u32 size
Definition: vhost_user.h:125
index
u32 index
Definition: flow_types.api:221
format_api_msg_range
static u8 * format_api_msg_range(u8 *s, va_list *args)
Definition: vlib_api_cli.c:289
range_compare
static int range_compare(vl_api_msg_range_t *a0, vl_api_msg_range_t *a1)
Definition: vlib_api_cli.c:278
vl_api_trace_t::nitems
u32 nitems
Number of trace records.
Definition: api_common.h:98
vl_api_trace_t::wrapped
u8 wrapped
trace has wrapped
Definition: api_common.h:96
u64
unsigned long u64
Definition: types.h:89
vl_msg_api_trace_free
int vl_msg_api_trace_free(api_main_t *am, vl_api_trace_which_t which)
Definition: api_shared.c:167
format
description fragment has unexpected format
Definition: map.api:433
vec_validate_init_empty
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header,...
Definition: vec.h:570
vl_api_msg_range_t
Message range (belonging to a plugin)
Definition: api_common.h:114
u32
unsigned int u32
Definition: types.h:88
format_vl_msg_api_trace_status
u8 * format_vl_msg_api_trace_status(u8 *s, va_list *args)
Definition: vlib_api_cli.c:353
vector_rate_histogram
u64 vector_rate_histogram[]
Definition: vlib_api.c:179
CLIB_MEM_UNPOISON
#define CLIB_MEM_UNPOISON(a, s)
Definition: sanitizer.h:47
vl_api_client_command
static clib_error_t * vl_api_client_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: vlib_api_cli.c:98
vl_api_message_table_command
static clib_error_t * vl_api_message_table_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: vlib_api_cli.c:227
table_id_cmp
static int table_id_cmp(void *a1, void *a2)
Definition: vlib_api_cli.c:1012
vl_api_msg_range_t::first_msg_id
u16 first_msg_id
first assigned message ID
Definition: api_common.h:117
cli_show_api_clients_command
static vlib_cli_command_t cli_show_api_clients_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_clients_command)
Definition: vlib_api_cli.c:206
pool_elts
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127
trace_cfg_t::replay_enable
int replay_enable
This message can be replayed
Definition: api_common.h:86
vl_msg_api_post_mortem_dump_enable_disable
void vl_msg_api_post_mortem_dump_enable_disable(int enable)
Definition: api_shared.c:963
clib_arch_is_little_endian
#define clib_arch_is_little_endian
Definition: byte_order.h:54
vec_sort_with_function
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1097
clib_memset
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
vlib_main_t
Definition: main.h:102
item
cJSON * item
Definition: cJSON.h:222
SLEEP_N_BUCKETS
@ SLEEP_N_BUCKETS
Definition: api.h:148
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
unserialize_close
__clib_export void unserialize_close(serialize_main_t *m)
Definition: serialize.c:877
vec_terminate_c_string
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
Definition: vec.h:1132
msg_table_unserialize_t::crc
u8 * crc
Definition: vlib_api_cli.c:1006
clib_warning
#define clib_warning(format, args...)
Definition: error.h:59
unserialize_likely_small_unsigned_integer
static u64 unserialize_likely_small_unsigned_integer(serialize_main_t *m)
Definition: serialize.h:254
rv
int __clib_unused rv
Definition: application.c:491
cleanup
static void cleanup(void)
Definition: client.c:98
vl_api_registration_::name
u8 * name
Client name.
Definition: api_common.h:54
vl_msg_api_process_file
static void vl_msg_api_process_file(vlib_main_t *vm, u8 *filename, u32 first_index, u32 last_index, vl_api_replay_t which)
Definition: vlib_api_cli.c:396
vl_msg_api_trace_onoff
int vl_msg_api_trace_onoff(api_main_t *am, vl_api_trace_which_t which, int onoff)
Definition: api_shared.c:125
msg_table_unserialize_t::name
u8 * name
Definition: vlib_api_cli.c:1005
vlib_cli_command_t
Definition: cli.h:92
api_queue_config_fn
static clib_error_t * api_queue_config_fn(vlib_main_t *vm, unformat_input_t *input)
Definition: vlib_api_cli.c:943
vl_msg_api_barrier_sync
void vl_msg_api_barrier_sync(void)
Definition: api_shared.c:427
extract_crc
static u8 * extract_crc(u8 *s)
Definition: vlib_api_cli.c:984
UNFORMAT_END_OF_INPUT
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
cli_show_api_message_table_command
static vlib_cli_command_t cli_show_api_message_table_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_message_table_command)
Definition: vlib_api_cli.c:269
INITIALIZERS
@ INITIALIZERS
Definition: vlib_api_cli.c:349