FD.io VPP  v17.07-30-g839fa73
Vector Packet Processing
memory_vlib.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * memory_vlib.c
4  *
5  * Copyright (c) 2009 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <signal.h>
28 #include <pthread.h>
29 #include <vppinfra/vec.h>
30 #include <vppinfra/hash.h>
31 #include <vppinfra/pool.h>
32 #include <vppinfra/format.h>
33 #include <vppinfra/byte_order.h>
34 #include <vppinfra/elog.h>
35 #include <stdarg.h>
36 #include <vlib/vlib.h>
37 #include <vlib/unix/unix.h>
38 #include <vlibapi/api.h>
39 #include <vlibmemory/api.h>
40 
41 #define TRACE_VLIB_MEMORY_QUEUE 0
42 
43 #include <vlibmemory/vl_memory_msg_enum.h> /* enumerate all vlib messages */
44 
45 #define vl_typedefs /* define message structures */
47 #undef vl_typedefs
48 
49 /* instantiate all the print functions we know about */
50 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
51 #define vl_printfun
53 #undef vl_printfun
54 
55 static inline void *
57 {
58  vl_print (handle, "vl_api_memclnt_create_t:\n");
59  vl_print (handle, "name: %s\n", a->name);
60  vl_print (handle, "input_queue: 0x%wx\n", a->input_queue);
61  vl_print (handle, "context: %u\n", (unsigned) a->context);
62  vl_print (handle, "ctx_quota: %ld\n", (long) a->ctx_quota);
63  return handle;
64 }
65 
66 static inline void *
68 {
69  vl_print (handle, "vl_api_memclnt_delete_t:\n");
70  vl_print (handle, "index: %u\n", (unsigned) a->index);
71  vl_print (handle, "handle: 0x%wx\n", a->handle);
72  return handle;
73 }
74 
75 static inline void *
77  void *handle)
78 {
79  vl_print (handle, "vl_api_trace_plugin_msg_ids: %s first %u last %u\n",
80  a->plugin_name,
81  clib_host_to_net_u16 (a->first_msg_id),
82  clib_host_to_net_u16 (a->last_msg_id));
83  return handle;
84 }
85 
86 /* instantiate all the endian swap functions we know about */
87 #define vl_endianfun
89 #undef vl_endianfun
90 
92  __attribute__ ((weak));
93 
94 void
96 {
97  static int count;
98 
99  if (count++ < 5)
100  clib_warning ("need to link against -lvlibsocket, msg not sent!");
101 }
102 
103 void
105 {
107  {
108  vl_socket_api_send (rp, elem);
109  }
110  else
111  {
113  }
114 }
115 
116 u8 *
118 {
119  serialize_main_t _sm, *sm = &_sm;
120  hash_pair_t *hp;
122 
123  serialize_open_vector (sm, vector);
124 
125  /* serialize the count */
126  serialize_integer (sm, nmsg, sizeof (u32));
127 
128  /* *INDENT-OFF* */
130  ({
131  serialize_likely_small_unsigned_integer (sm, hp->value[0]);
132  serialize_cstring (sm, (char *) hp->key);
133  }));
134  /* *INDENT-ON* */
135 
136  return serialize_close_vector (sm);
137 }
138 
139 /*
140  * vl_api_memclnt_create_t_handler
141  */
142 void
144 {
145  vl_api_registration_t **regpp;
146  vl_api_registration_t *regp;
148  svm_region_t *svm;
150  int rv = 0;
151  void *oldheap;
152  api_main_t *am = &api_main;
153  u8 *serialized_message_table = 0;
154 
155  /*
156  * This is tortured. Maintain a vlib-address-space private
157  * pool of client registrations. We use the shared-memory virtual
158  * address of client structure as a handle, to allow direct
159  * manipulation of context quota vbls from the client library.
160  *
161  * This scheme causes trouble w/ API message trace replay, since
162  * some random VA from clib_mem_alloc() certainly won't
163  * occur in the Linux sim. The (very) few places
164  * that care need to use the pool index.
165  *
166  * Putting the registration object(s) into a pool in shared memory and
167  * using the pool index as a handle seems like a great idea.
168  * Unfortunately, each and every reference to that pool would need
169  * to be protected by a mutex:
170  *
171  * Client VLIB
172  * ------ ----
173  * convert pool index to
174  * pointer.
175  * <deschedule>
176  * expand pool
177  * <deschedule>
178  * kaboom!
179  */
180 
181  pool_get (am->vl_clients, regpp);
182 
183  svm = am->vlib_rp;
184 
186  serialized_message_table = vl_api_serialize_message_table (am, 0);
187 
188  pthread_mutex_lock (&svm->mutex);
189  oldheap = svm_push_data_heap (svm);
190  *regpp = clib_mem_alloc (sizeof (vl_api_registration_t));
191 
192  regp = *regpp;
193  memset (regp, 0, sizeof (*regp));
195  regp->vl_api_registration_pool_index = regpp - am->vl_clients;
196 
198  mp->input_queue;
199 
200  regp->name = format (0, "%s", mp->name);
201  vec_add1 (regp->name, 0);
202  if (serialized_message_table)
204  vec_dup (serialized_message_table);
205 
206  pthread_mutex_unlock (&svm->mutex);
207  svm_pop_heap (oldheap);
208 
209  vec_free (serialized_message_table);
210 
211  rp = vl_msg_api_alloc (sizeof (*rp));
212  rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_CREATE_REPLY);
213  rp->handle = (uword) regp;
217  rp->context = mp->context;
218  rp->response = ntohl (rv);
219  rp->message_table =
221 
222  vl_msg_api_send_shmem (q, (u8 *) & rp);
223 }
224 
225 static int
227 {
228  clib_error_t *error = 0;
229  _vl_msg_api_function_list_elt_t *i;
230 
232  while (i)
233  {
234  error = i->f (client_index);
235  if (error)
236  clib_error_report (error);
237  i = i->next_init_function;
238  }
239  return 0;
240 }
241 
242 /*
243  * vl_api_memclnt_delete_t_handler
244  */
245 void
247 {
248  vl_api_registration_t **regpp;
249  vl_api_registration_t *regp;
251  svm_region_t *svm;
252  void *oldheap;
253  api_main_t *am = &api_main;
254  u32 handle, client_index, epoch;
255 
256  handle = mp->index;
257 
258  if (call_reaper_functions (handle))
259  return;
260 
261  epoch = vl_msg_api_handle_get_epoch (handle);
262  client_index = vl_msg_api_handle_get_index (handle);
263 
264  if (epoch != (am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK))
265  {
267  ("Stale clnt delete index %d old epoch %d cur epoch %d",
268  client_index, epoch,
270  return;
271  }
272 
273  regpp = am->vl_clients + client_index;
274 
275  if (!pool_is_free (am->vl_clients, regpp))
276  {
277  regp = *regpp;
278  svm = am->vlib_rp;
279 
280  /* $$$ check the input queue for e.g. punted sf's */
281 
282  rp = vl_msg_api_alloc (sizeof (*rp));
283  rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_DELETE_REPLY);
284  rp->handle = mp->handle;
285  rp->response = 1;
286 
287  vl_msg_api_send_shmem (regp->vl_input_queue, (u8 *) & rp);
288 
289  if (client_index != regp->vl_api_registration_pool_index)
290  {
291  clib_warning ("mismatch client_index %d pool_index %d",
292  client_index, regp->vl_api_registration_pool_index);
293  vl_msg_api_free (rp);
294  return;
295  }
296 
297  /* No dangling references, please */
298  *regpp = 0;
299 
301 
302  pthread_mutex_lock (&svm->mutex);
303  oldheap = svm_push_data_heap (svm);
304  /* Poison the old registration */
305  memset (regp, 0xF1, sizeof (*regp));
306  clib_mem_free (regp);
307  pthread_mutex_unlock (&svm->mutex);
308  svm_pop_heap (oldheap);
309  }
310  else
311  {
312  clib_warning ("unknown client ID %d", mp->index);
313  }
314 }
315 
316 void
318 {
321  uword *p;
322  api_main_t *am = &api_main;
323  vl_api_msg_range_t *rp;
324  u8 name[64];
325  u16 first_msg_id = ~0;
326  int rv = -7; /* VNET_API_ERROR_INVALID_VALUE */
327 
329  if (!q)
330  return;
331 
332  if (am->msg_range_by_name == 0)
333  goto out;
334 
335  strncpy ((char *) name, (char *) mp->name, ARRAY_LEN (name) - 1);
336 
337  p = hash_get_mem (am->msg_range_by_name, name);
338  if (p == 0)
339  goto out;
340 
341  rp = vec_elt_at_index (am->msg_ranges, p[0]);
342 
343  first_msg_id = rp->first_msg_id;
344  rv = 0;
345 
346 out:
347 
348  rmp = vl_msg_api_alloc (sizeof (*rmp));
349  rmp->_vl_msg_id = ntohs (VL_API_GET_FIRST_MSG_ID_REPLY);
350  rmp->context = mp->context;
351  rmp->retval = ntohl (rv);
352  rmp->first_msg_id = ntohs (first_msg_id);
353  vl_msg_api_send_shmem (q, (u8 *) & rmp);
354 }
355 
356 #define foreach_vlib_api_msg \
357 _(MEMCLNT_CREATE, memclnt_create) \
358 _(MEMCLNT_DELETE, memclnt_delete) \
359 _(GET_FIRST_MSG_ID, get_first_msg_id)
360 
361 /*
362  * vl_api_init
363  */
364 static int
365 memory_api_init (const char *region_name)
366 {
367  int rv;
369  vl_msg_api_msg_config_t *c = &cfg;
370 
371  memset (c, 0, sizeof (*c));
372 
373  if ((rv = vl_map_shmem (region_name, 1 /* is_vlib */ )) < 0)
374  return rv;
375 
376 #define _(N,n) do { \
377  c->id = VL_API_##N; \
378  c->name = #n; \
379  c->handler = vl_api_##n##_t_handler; \
380  c->cleanup = vl_noop_handler; \
381  c->endian = vl_api_##n##_t_endian; \
382  c->print = vl_api_##n##_t_print; \
383  c->size = sizeof(vl_api_##n##_t); \
384  c->traced = 1; /* trace, so these msgs print */ \
385  c->replay = 0; /* don't replay client create/delete msgs */ \
386  c->message_bounce = 0; /* don't bounce this message */ \
387  vl_msg_api_config(c);} while (0);
388 
390 #undef _
391 
392  return 0;
393 }
394 
395 #define foreach_histogram_bucket \
396 _(400) \
397 _(200) \
398 _(100) \
399 _(10)
400 
401 typedef enum
402 {
403 #define _(n) SLEEP_##n##_US,
405 #undef _
408 
410 
411 static void memclnt_queue_callback (vlib_main_t * vm);
412 
413 /*
414  * Callback to send ourselves a plugin numbering-space trace msg
415  */
416 static void
417 send_one_plugin_msg_ids_msg (u8 * name, u16 first_msg_id, u16 last_msg_id)
418 {
420  api_main_t *am = &api_main;
423 
424  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp));
425  memset (mp, 0, sizeof (*mp));
426 
427  mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_TRACE_PLUGIN_MSG_IDS);
428  strncpy ((char *) mp->plugin_name, (char *) name,
429  sizeof (mp->plugin_name) - 1);
430  mp->first_msg_id = clib_host_to_net_u16 (first_msg_id);
431  mp->last_msg_id = clib_host_to_net_u16 (last_msg_id);
432 
433  q = shmem_hdr->vl_input_queue;
434 
435  vl_msg_api_send_shmem (q, (u8 *) & mp);
436 }
437 
438 static uword
440  vlib_node_runtime_t * node, vlib_frame_t * f)
441 {
442  uword mp;
443  vl_shmem_hdr_t *shm;
445  clib_error_t *e;
446  int rv;
447  api_main_t *am = &api_main;
448  f64 dead_client_scan_time;
449  f64 sleep_time, start_time;
450  f64 vector_rate;
451  int i;
452 
454 
455  if ((rv = memory_api_init (am->region_name)) < 0)
456  {
457  clib_warning ("memory_api_init returned %d, wait for godot...", rv);
458  vlib_process_suspend (vm, 1e70);
459  }
460 
461  shm = am->shmem_hdr;
462  ASSERT (shm);
463  q = shm->vl_input_queue;
464  ASSERT (q);
465 
467  (vm, vm->api_init_function_registrations, 1 /* call_once */ );
468  if (e)
469  clib_error_report (e);
470 
471  sleep_time = 20.0;
472  dead_client_scan_time = vlib_time_now (vm) + 20.0;
473 
474  /*
475  * Send plugin message range messages for each plugin we loaded
476  */
477  for (i = 0; i < vec_len (am->msg_ranges); i++)
478  {
479  vl_api_msg_range_t *rp = am->msg_ranges + i;
481  rp->last_msg_id);
482  }
483 
484  /* $$$ pay attention to frame size, control CPU usage */
485  while (1)
486  {
487  uword event_type __attribute__ ((unused));
488  i8 *headp;
489  int need_broadcast;
490 
491  /*
492  * There's a reason for checking the queue before
493  * sleeping. If the vlib application crashes, it's entirely
494  * possible for a client to enqueue a connect request
495  * during the process restart interval.
496  *
497  * Unless some force of physics causes the new incarnation
498  * of the application to process the request, the client will
499  * sit and wait for Godot...
500  */
501  vector_rate = vlib_last_vector_length_per_node (vm);
502  start_time = vlib_time_now (vm);
503  while (1)
504  {
505  pthread_mutex_lock (&q->mutex);
506  if (q->cursize == 0)
507  {
508  vm->api_queue_nonempty = 0;
509  pthread_mutex_unlock (&q->mutex);
510 
512  {
513  /* *INDENT-OFF* */
514  ELOG_TYPE_DECLARE (e) =
515  {
516  .format = "q-underflow: len %d",
517  .format_args = "i4",
518  };
519  /* *INDENT-ON* */
520  struct
521  {
522  u32 len;
523  } *ed;
524  ed = ELOG_DATA (&vm->elog_main, e);
525  ed->len = 0;
526  }
527  sleep_time = 20.0;
528  break;
529  }
530 
531  headp = (i8 *) (q->data + sizeof (uword) * q->head);
532  clib_memcpy (&mp, headp, sizeof (uword));
533 
534  q->head++;
535  need_broadcast = (q->cursize == q->maxsize / 2);
536  q->cursize--;
537 
538  if (PREDICT_FALSE (q->head == q->maxsize))
539  q->head = 0;
540  pthread_mutex_unlock (&q->mutex);
541  if (need_broadcast)
542  (void) pthread_cond_broadcast (&q->condvar);
543 
544  vl_msg_api_handler_with_vm_node (am, (void *) mp, vm, node);
545 
546  /* Allow no more than 10us without a pause */
547  if (vlib_time_now (vm) > start_time + 10e-6)
548  {
549  int index = SLEEP_400_US;
550  if (vector_rate > 40.0)
551  sleep_time = 400e-6;
552  else if (vector_rate > 20.0)
553  {
554  index = SLEEP_200_US;
555  sleep_time = 200e-6;
556  }
557  else if (vector_rate >= 1.0)
558  {
559  index = SLEEP_100_US;
560  sleep_time = 100e-6;
561  }
562  else
563  {
564  index = SLEEP_10_US;
565  sleep_time = 10e-6;
566  }
567  vector_rate_histogram[index] += 1;
568  break;
569  }
570  }
571 
572  event_type = vlib_process_wait_for_event_or_clock (vm, sleep_time);
573  vm->queue_signal_pending = 0;
574  vlib_process_get_events (vm, 0 /* event_data */ );
575 
576  if (vlib_time_now (vm) > dead_client_scan_time)
577  {
578  vl_api_registration_t **regpp;
579  vl_api_registration_t *regp;
581  static u32 *dead_indices;
582  static u32 *confused_indices;
583 
584  vec_reset_length (dead_indices);
585  vec_reset_length (confused_indices);
586 
587  /* *INDENT-OFF* */
588  pool_foreach (regpp, am->vl_clients,
589  ({
590  regp = *regpp;
591  if (regp)
592  {
593  q = regp->vl_input_queue;
594  if (kill (q->consumer_pid, 0) < 0)
595  {
596  vec_add1(dead_indices, regpp - am->vl_clients);
597  }
598  }
599  else
600  {
601  clib_warning ("NULL client registration index %d",
602  regpp - am->vl_clients);
603  vec_add1 (confused_indices, regpp - am->vl_clients);
604  }
605  }));
606  /* *INDENT-ON* */
607  /* This should "never happen," but if it does, fix it... */
608  if (PREDICT_FALSE (vec_len (confused_indices) > 0))
609  {
610  int i;
611  for (i = 0; i < vec_len (confused_indices); i++)
612  {
613  pool_put_index (am->vl_clients, confused_indices[i]);
614  }
615  }
616 
617  if (PREDICT_FALSE (vec_len (dead_indices) > 0))
618  {
619  int i;
620  svm_region_t *svm;
621  void *oldheap;
622 
623  /* Allow the application to clean up its registrations */
624  for (i = 0; i < vec_len (dead_indices); i++)
625  {
626  regpp = pool_elt_at_index (am->vl_clients, dead_indices[i]);
627  if (regpp)
628  {
629  u32 handle;
630 
632  (dead_indices[i], shm->application_restarts);
633  (void) call_reaper_functions (handle);
634  }
635  }
636 
637  svm = am->vlib_rp;
638  pthread_mutex_lock (&svm->mutex);
639  oldheap = svm_push_data_heap (svm);
640 
641  for (i = 0; i < vec_len (dead_indices); i++)
642  {
643  regpp = pool_elt_at_index (am->vl_clients, dead_indices[i]);
644  if (regpp)
645  {
646  /* Poison the old registration */
647  memset (*regpp, 0xF3, sizeof (**regpp));
648  clib_mem_free (*regpp);
649  /* no dangling references, please */
650  *regpp = 0;
651  }
652  else
653  {
654  svm_pop_heap (oldheap);
655  clib_warning ("Duplicate free, client index %d",
656  regpp - am->vl_clients);
657  oldheap = svm_push_data_heap (svm);
658  }
659  }
660 
662 
663  pthread_mutex_unlock (&svm->mutex);
664  svm_pop_heap (oldheap);
665  for (i = 0; i < vec_len (dead_indices); i++)
666  pool_put_index (am->vl_clients, dead_indices[i]);
667  }
668 
669  dead_client_scan_time = vlib_time_now (vm) + 20.0;
670  }
671 
673  {
674  /* *INDENT-OFF* */
675  ELOG_TYPE_DECLARE (e) = {
676  .format = "q-awake: len %d",
677  .format_args = "i4",
678  };
679  /* *INDENT-ON* */
680  struct
681  {
682  u32 len;
683  } *ed;
684  ed = ELOG_DATA (&vm->elog_main, e);
685  ed->len = q->cursize;
686  }
687  }
688 
689  return 0;
690 }
691 
692 static clib_error_t *
694  unformat_input_t * input,
695  vlib_cli_command_t * cli_cmd)
696 {
697  u64 total_counts = 0;
698  int i;
699 
700  for (i = 0; i < SLEEP_N_BUCKETS; i++)
701  {
702  total_counts += vector_rate_histogram[i];
703  }
704 
705  if (total_counts == 0)
706  {
707  vlib_cli_output (vm, "No control-plane activity.");
708  return 0;
709  }
710 
711 #define _(n) \
712  do { \
713  f64 percent; \
714  percent = ((f64) vector_rate_histogram[SLEEP_##n##_US]) \
715  / (f64) total_counts; \
716  percent *= 100.0; \
717  vlib_cli_output (vm, "Sleep %3d us: %llu, %.2f%%",n, \
718  vector_rate_histogram[SLEEP_##n##_US], \
719  percent); \
720  } while (0);
722 #undef _
723 
724  return 0;
725 }
726 
727 /* *INDENT-OFF* */
728 VLIB_CLI_COMMAND (cli_show_api_histogram_command, static) = {
729  .path = "show api histogram",
730  .short_help = "show api histogram",
731  .function = vl_api_show_histogram_command,
732 };
733 /* *INDENT-ON* */
734 
735 static clib_error_t *
737  unformat_input_t * input,
738  vlib_cli_command_t * cli_cmd)
739 {
740  int i;
741 
742  for (i = 0; i < SLEEP_N_BUCKETS; i++)
743  vector_rate_histogram[i] = 0;
744  return 0;
745 }
746 
747 /* *INDENT-OFF* */
748 VLIB_CLI_COMMAND (cli_clear_api_histogram_command, static) = {
749  .path = "clear api histogram",
750  .short_help = "clear api histogram",
751  .function = vl_api_clear_histogram_command,
752 };
753 /* *INDENT-ON* */
754 
755 
756 /* *INDENT-OFF* */
758  .function = memclnt_process,
759  .type = VLIB_NODE_TYPE_PROCESS,
760  .name = "api-rx-from-ring",
761  .state = VLIB_NODE_STATE_DISABLED,
762 };
763 /* *INDENT-ON* */
764 
765 static void
767 {
768  static volatile int *cursizep;
769 
770  if (PREDICT_FALSE (cursizep == 0))
771  {
772  api_main_t *am = &api_main;
775 
776  if (shmem_hdr == 0)
777  return;
778 
779  q = shmem_hdr->vl_input_queue;
780  if (q == 0)
781  return;
782  cursizep = &q->cursize;
783  }
784 
785  if (*cursizep >= 1)
786  {
787  vm->queue_signal_pending = 1;
788  vm->api_queue_nonempty = 1;
790  /* event_type */ 0, /* event_data */ 0);
791  }
792 }
793 
794 void
796 {
798  (enable
799  ? VLIB_NODE_STATE_POLLING
800  : VLIB_NODE_STATE_DISABLED));
801 }
802 
803 static uword
805  vlib_node_runtime_t * node, vlib_frame_t * frame)
806 {
807  uword n_packets = frame->n_vectors;
808  uword n_left_from;
809  u32 *from;
810  static u8 *long_msg;
811 
812  vec_validate (long_msg, 4095);
813  n_left_from = frame->n_vectors;
814  from = vlib_frame_args (frame);
815 
816  while (n_left_from > 0)
817  {
818  u32 bi0;
819  vlib_buffer_t *b0;
820  void *msg;
821  uword msg_len;
822 
823  bi0 = from[0];
824  b0 = vlib_get_buffer (vm, bi0);
825  from += 1;
826  n_left_from -= 1;
827 
828  msg = b0->data + b0->current_data;
829  msg_len = b0->current_length;
831  {
832  ASSERT (long_msg != 0);
833  _vec_len (long_msg) = 0;
834  vec_add (long_msg, msg, msg_len);
835  while (b0->flags & VLIB_BUFFER_NEXT_PRESENT)
836  {
837  b0 = vlib_get_buffer (vm, b0->next_buffer);
838  msg = b0->data + b0->current_data;
839  msg_len = b0->current_length;
840  vec_add (long_msg, msg, msg_len);
841  }
842  msg = long_msg;
843  }
845  }
846 
847  /* Free what we've been given. */
848  vlib_buffer_free (vm, vlib_frame_args (frame), n_packets);
849 
850  return n_packets;
851 }
852 
853 /* *INDENT-OFF* */
855  .function = api_rx_from_node,
856  .type = VLIB_NODE_TYPE_INTERNAL,
857  .vector_size = 4,
858  .name = "api-rx-from-node",
859 };
860 /* *INDENT-ON* */
861 
862 static clib_error_t *
864 {
865  atexit (vl_unmap_shmem);
866  return 0;
867 }
868 
870 
871 
872 static clib_error_t *
874  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
875 {
876  int i;
877  ring_alloc_t *ap;
879  api_main_t *am = &api_main;
880 
881  shmem_hdr = am->shmem_hdr;
882 
883  if (shmem_hdr == 0)
884  {
885  vlib_cli_output (vm, "Shared memory segment not initialized...\n");
886  return 0;
887  }
888 
889  vlib_cli_output (vm, "%8s %8s %8s %8s %8s\n",
890  "Owner", "Size", "Nitems", "Hits", "Misses");
891 
892  ap = shmem_hdr->vl_rings;
893 
894  for (i = 0; i < vec_len (shmem_hdr->vl_rings); i++)
895  {
896  vlib_cli_output (vm, "%8s %8d %8d %8d %8d\n",
897  "vlib", ap->size, ap->nitems, ap->hits, ap->misses);
898  ap++;
899  }
900 
901  ap = shmem_hdr->client_rings;
902 
903  for (i = 0; i < vec_len (shmem_hdr->client_rings); i++)
904  {
905  vlib_cli_output (vm, "%8s %8d %8d %8d %8d\n",
906  "clnt", ap->size, ap->nitems, ap->hits, ap->misses);
907  ap++;
908  }
909 
910  vlib_cli_output (vm, "%d ring miss fallback allocations\n",
911  am->ring_misses);
912 
914  (vm, "%d application restarts, %d reclaimed msgs, %d garbage collects\n",
915  shmem_hdr->application_restarts,
916  shmem_hdr->restart_reclaims, shmem_hdr->garbage_collects);
917  return 0;
918 }
919 
921  __attribute__ ((weak));
922 
923 void
925 {
926 }
927 
928 static clib_error_t *
930  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
931 {
932  vl_api_registration_t **regpp, *regp;
934  char *health;
935  api_main_t *am = &api_main;
936  u32 *confused_indices = 0;
937 
938  if (!pool_elts (am->vl_clients))
939  goto socket_clients;
940  vlib_cli_output (vm, "Shared memory clients");
941  vlib_cli_output (vm, "%16s %8s %14s %18s %s",
942  "Name", "PID", "Queue Length", "Queue VA", "Health");
943 
944  /* *INDENT-OFF* */
945  pool_foreach (regpp, am->vl_clients,
946  ({
947  regp = *regpp;
948 
949  if (regp)
950  {
951  q = regp->vl_input_queue;
952  if (kill (q->consumer_pid, 0) < 0)
953  {
954  health = "DEAD";
955  }
956  else
957  {
958  health = "alive";
959  }
960  vlib_cli_output (vm, "%16s %8d %14d 0x%016llx %s\n",
961  regp->name, q->consumer_pid, q->cursize,
962  q, health);
963  }
964  else
965  {
966  clib_warning ("NULL client registration index %d",
967  regpp - am->vl_clients);
968  vec_add1 (confused_indices, regpp - am->vl_clients);
969  }
970  }));
971  /* *INDENT-ON* */
972 
973  /* This should "never happen," but if it does, fix it... */
974  if (PREDICT_FALSE (vec_len (confused_indices) > 0))
975  {
976  int i;
977  for (i = 0; i < vec_len (confused_indices); i++)
978  {
979  pool_put_index (am->vl_clients, confused_indices[i]);
980  }
981  }
982  vec_free (confused_indices);
983 
984  if (am->missing_clients)
985  vlib_cli_output (vm, "%u messages with missing clients",
986  am->missing_clients);
987 socket_clients:
988  dump_socket_clients (vm, am);
989 
990  return 0;
991 }
992 
993 static clib_error_t *
995  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
996 {
997  api_main_t *am = &api_main;
998 
999  // check if rx_trace and tx_trace are not null pointers
1000 
1001  if (am->rx_trace == 0)
1002  {
1003  vlib_cli_output (vm, "RX Trace disabled\n");
1004  }
1005  else
1006  {
1007  if (am->rx_trace->enabled == 0)
1008  vlib_cli_output (vm, "RX Trace disabled\n");
1009  else
1010  vlib_cli_output (vm, "RX Trace enabled\n");
1011  }
1012 
1013  if (am->tx_trace == 0)
1014  {
1015  vlib_cli_output (vm, "TX Trace disabled\n");
1016  }
1017  else
1018  {
1019  if (am->tx_trace->enabled == 0)
1020  vlib_cli_output (vm, "TX Trace disabled\n");
1021  else
1022  vlib_cli_output (vm, "TX Trace enabled\n");
1023  }
1024 
1025  return 0;
1026 }
1027 
1028 /* *INDENT-OFF* */
1030  .path = "show api",
1031  .short_help = "Show API information",
1032 };
1033 /* *INDENT-ON* */
1034 
1035 /* *INDENT-OFF* */
1037  .path = "show api ring-stats",
1038  .short_help = "Message ring statistics",
1039  .function = vl_api_ring_command,
1040 };
1041 /* *INDENT-ON* */
1042 
1043 /* *INDENT-OFF* */
1045  .path = "show api clients",
1046  .short_help = "Client information",
1047  .function = vl_api_client_command,
1048 };
1049 /* *INDENT-ON* */
1050 
1051 /* *INDENT-OFF* */
1053  .path = "show api status",
1054  .short_help = "Show API trace status",
1055  .function = vl_api_status_command,
1056 };
1057 /* *INDENT-ON* */
1058 
1059 static clib_error_t *
1061  unformat_input_t * input,
1062  vlib_cli_command_t * cli_cmd)
1063 {
1064  api_main_t *am = &api_main;
1065  int i;
1066  int verbose = 0;
1067 
1068  if (unformat (input, "verbose"))
1069  verbose = 1;
1070 
1071 
1072  if (verbose == 0)
1073  vlib_cli_output (vm, "%-4s %s", "ID", "Name");
1074  else
1075  vlib_cli_output (vm, "%-4s %-40s %6s %7s", "ID", "Name", "Bounce",
1076  "MP-safe");
1077 
1078  for (i = 1; i < vec_len (am->msg_names); i++)
1079  {
1080  if (verbose == 0)
1081  {
1082  vlib_cli_output (vm, "%-4d %s", i,
1083  am->msg_names[i] ? am->msg_names[i] :
1084  " [no handler]");
1085  }
1086  else
1087  {
1088  vlib_cli_output (vm, "%-4d %-40s %6d %7d", i,
1089  am->msg_names[i] ? am->msg_names[i] :
1090  " [no handler]", am->message_bounce[i],
1091  am->is_mp_safe[i]);
1092  }
1093  }
1094 
1095  return 0;
1096 }
1097 
1098 /* *INDENT-OFF* */
1100  .path = "show api message-table",
1101  .short_help = "Message Table",
1102  .function = vl_api_message_table_command,
1103 };
1104 /* *INDENT-ON* */
1105 
1106 static clib_error_t *
1108  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
1109 {
1110  u32 nitems = 1024;
1112  api_main_t *am = &api_main;
1113 
1114  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1115  {
1116  if (unformat (input, "rx nitems %u", &nitems) || unformat (input, "rx"))
1117  goto configure;
1118  else if (unformat (input, "tx nitems %u", &nitems)
1119  || unformat (input, "tx"))
1120  {
1121  which = VL_API_TRACE_RX;
1122  goto configure;
1123  }
1124  else if (unformat (input, "on rx"))
1125  {
1127  }
1128  else if (unformat (input, "on tx"))
1129  {
1131  }
1132  else if (unformat (input, "on"))
1133  {
1135  }
1136  else if (unformat (input, "off"))
1137  {
1140  }
1141  else if (unformat (input, "free"))
1142  {
1147  }
1148  else if (unformat (input, "debug on"))
1149  {
1150  am->msg_print_flag = 1;
1151  }
1152  else if (unformat (input, "debug off"))
1153  {
1154  am->msg_print_flag = 0;
1155  }
1156  else
1157  return clib_error_return (0, "unknown input `%U'",
1158  format_unformat_error, input);
1159  }
1160  return 0;
1161 
1162 configure:
1163  if (vl_msg_api_trace_configure (am, which, nitems))
1164  {
1165  vlib_cli_output (vm, "warning: trace configure error (%d, %d)",
1166  which, nitems);
1167  }
1168 
1169  return 0;
1170 }
1171 
1172 /* *INDENT-OFF* */
1174  .path = "set api-trace",
1175  .short_help = "API trace",
1176  .function = vl_api_trace_command,
1177 };
1178 /* *INDENT-ON* */
1179 
1180 clib_error_t *
1182 {
1183  api_main_t *am = &api_main;
1184  svm_map_region_args_t _a, *a = &_a;
1185 
1186  memset (a, 0, sizeof (*a));
1187  a->root_path = am->root_path;
1189  a->baseva = (am->global_baseva != 0) ?
1191  a->size = (am->global_size != 0) ? am->global_size : SVM_GLOBAL_REGION_SIZE;
1192  a->flags = SVM_FLAGS_NODATA;
1193  a->uid = am->api_uid;
1194  a->gid = am->api_gid;
1195  a->pvt_heap_size =
1196  (am->global_pvt_heap_size !=
1198 
1200  return 0;
1201 }
1202 
1204 
1205 void
1206 vl_set_memory_region_name (const char *name)
1207 {
1208  api_main_t *am = &api_main;
1209 
1210  am->region_name = name;
1211 }
1212 
1213 static int
1215 {
1216  int len0, len1, clen;
1217 
1218  len0 = vec_len (a0->name);
1219  len1 = vec_len (a1->name);
1220  clen = len0 < len1 ? len0 : len1;
1221  return (strncmp ((char *) a0->name, (char *) a1->name, clen));
1222 }
1223 
1224 static u8 *
1225 format_api_msg_range (u8 * s, va_list * args)
1226 {
1227  vl_api_msg_range_t *rp = va_arg (*args, vl_api_msg_range_t *);
1228 
1229  if (rp == 0)
1230  s = format (s, "%-20s%9s%9s", "Name", "First-ID", "Last-ID");
1231  else
1232  s = format (s, "%-20s%9d%9d", rp->name, rp->first_msg_id,
1233  rp->last_msg_id);
1234 
1235  return s;
1236 }
1237 
1238 static clib_error_t *
1240  unformat_input_t * input,
1241  vlib_cli_command_t * cli_cmd)
1242 {
1243  api_main_t *am = &api_main;
1244  vl_api_msg_range_t *rp = 0;
1245  int i;
1246 
1247  if (vec_len (am->msg_ranges) == 0)
1248  {
1249  vlib_cli_output (vm, "No plugin API message ranges configured...");
1250  return 0;
1251  }
1252 
1253  rp = vec_dup (am->msg_ranges);
1254 
1256 
1257  vlib_cli_output (vm, "Plugin API message ID ranges...\n");
1258  vlib_cli_output (vm, "%U", format_api_msg_range, 0 /* header */ );
1259 
1260  for (i = 0; i < vec_len (rp); i++)
1261  vlib_cli_output (vm, "%U", format_api_msg_range, rp + i);
1262 
1263  vec_free (rp);
1264 
1265  return 0;
1266 }
1267 
1268 /* *INDENT-OFF* */
1270  .path = "show api plugin",
1271  .short_help = "show api plugin",
1272  .function = vl_api_show_plugin_command,
1273 };
1274 /* *INDENT-ON* */
1275 
1276 static void
1278 {
1279  vl_api_rpc_call_reply_t *rmp;
1280  int (*fp) (void *);
1281  i32 rv = 0;
1282  vlib_main_t *vm = vlib_get_main ();
1283 
1284  if (mp->function == 0)
1285  {
1286  rv = -1;
1287  clib_warning ("rpc NULL function pointer");
1288  }
1289 
1290  else
1291  {
1292  if (mp->need_barrier_sync)
1294 
1295  fp = uword_to_pointer (mp->function, int (*)(void *));
1296  rv = fp (mp->data);
1297 
1298  if (mp->need_barrier_sync)
1300  }
1301 
1302  if (mp->send_reply)
1303  {
1306  if (q)
1307  {
1308  rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp));
1309  rmp->_vl_msg_id = ntohs (VL_API_RPC_CALL_REPLY);
1310  rmp->context = mp->context;
1311  rmp->retval = rv;
1312  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1313  }
1314  }
1315  if (mp->multicast)
1316  {
1317  clib_warning ("multicast not yet implemented...");
1318  }
1319 }
1320 
1321 static void
1322 vl_api_rpc_call_reply_t_handler (vl_api_rpc_call_reply_t * mp)
1323 {
1324  clib_warning ("unimplemented");
1325 }
1326 
1327 void
1328 vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length)
1329 {
1330  vl_api_rpc_call_t *mp;
1331  api_main_t *am = &api_main;
1334 
1335  /* Main thread: call the function directly */
1336  if (vlib_get_thread_index () == 0)
1337  {
1338  vlib_main_t *vm = vlib_get_main ();
1339  void (*call_fp) (void *);
1340 
1342 
1343  call_fp = fp;
1344  call_fp (data);
1345 
1347  return;
1348  }
1349 
1350  /* Any other thread, actually do an RPC call... */
1351  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) + data_length);
1352 
1353  memset (mp, 0, sizeof (*mp));
1354  clib_memcpy (mp->data, data, data_length);
1355  mp->_vl_msg_id = ntohs (VL_API_RPC_CALL);
1356  mp->function = pointer_to_uword (fp);
1357  mp->need_barrier_sync = 1;
1358 
1359  /*
1360  * Use the "normal" control-plane mechanism for the main thread.
1361  * Well, almost. if the main input queue is full, we cannot
1362  * block. Otherwise, we can expect a barrier sync timeout.
1363  */
1364  q = shmem_hdr->vl_input_queue;
1365 
1366  while (pthread_mutex_trylock (&q->mutex))
1368 
1370  {
1371  pthread_mutex_unlock (&q->mutex);
1373  while (pthread_mutex_trylock (&q->mutex))
1375  }
1376 
1377  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
1378 
1379  pthread_mutex_unlock (&q->mutex);
1380 }
1381 
1382 static void
1384 {
1385  api_main_t *am = &api_main;
1386  vl_api_msg_range_t *rp;
1387  uword *p;
1388 
1389  /* Noop (except for tracing) during normal operation */
1390  if (am->replay_in_progress == 0)
1391  return;
1392 
1394  if (p == 0)
1395  {
1396  clib_warning ("WARNING: traced plugin '%s' not in current image",
1397  mp->plugin_name);
1398  return;
1399  }
1400 
1401  rp = vec_elt_at_index (am->msg_ranges, p[0]);
1402  if (rp->first_msg_id != clib_net_to_host_u16 (mp->first_msg_id))
1403  {
1404  clib_warning ("WARNING: traced plugin '%s' first message id %d not %d",
1405  mp->plugin_name, clib_net_to_host_u16 (mp->first_msg_id),
1406  rp->first_msg_id);
1407  }
1408 
1409  if (rp->last_msg_id != clib_net_to_host_u16 (mp->last_msg_id))
1410  {
1411  clib_warning ("WARNING: traced plugin '%s' last message id %d not %d",
1412  mp->plugin_name, clib_net_to_host_u16 (mp->last_msg_id),
1413  rp->last_msg_id);
1414  }
1415 }
1416 
1417 #define foreach_rpc_api_msg \
1418 _(RPC_CALL,rpc_call) \
1419 _(RPC_CALL_REPLY,rpc_call_reply)
1420 
1421 #define foreach_plugin_trace_msg \
1422 _(TRACE_PLUGIN_MSG_IDS,trace_plugin_msg_ids)
1423 
1424 static clib_error_t *
1426 {
1427 #define _(N,n) \
1428  vl_msg_api_set_handlers(VL_API_##N, #n, \
1429  vl_api_##n##_t_handler, \
1430  vl_noop_handler, \
1431  vl_noop_handler, \
1432  vl_api_##n##_t_print, \
1433  sizeof(vl_api_##n##_t), 0 /* do not trace */);
1435 #undef _
1436 
1437 #define _(N,n) \
1438  vl_msg_api_set_handlers(VL_API_##N, #n, \
1439  vl_api_##n##_t_handler, \
1440  vl_noop_handler, \
1441  vl_noop_handler, \
1442  vl_api_##n##_t_print, \
1443  sizeof(vl_api_##n##_t), 1 /* do trace */);
1445 #undef _
1446  return 0;
1447 }
1448 
1450 
1451 typedef enum
1452 {
1457 } vl_api_replay_t;
1458 
1459 u8 *
1460 format_vl_msg_api_trace_status (u8 * s, va_list * args)
1461 {
1462  api_main_t *am = va_arg (*args, api_main_t *);
1463  vl_api_trace_which_t which = va_arg (*args, vl_api_trace_which_t);
1464  vl_api_trace_t *tp;
1465  char *trace_name;
1466 
1467  switch (which)
1468  {
1469  case VL_API_TRACE_TX:
1470  tp = am->tx_trace;
1471  trace_name = "TX trace";
1472  break;
1473 
1474  case VL_API_TRACE_RX:
1475  tp = am->rx_trace;
1476  trace_name = "RX trace";
1477  break;
1478 
1479  default:
1480  abort ();
1481  }
1482 
1483  if (tp == 0)
1484  {
1485  s = format (s, "%s: not yet configured.\n", trace_name);
1486  return s;
1487  }
1488 
1489  s = format (s, "%s: used %d of %d items, %s enabled, %s wrapped\n",
1490  trace_name, vec_len (tp->traces), tp->nitems,
1491  tp->enabled ? "is" : "is not", tp->wrapped ? "has" : "has not");
1492  return s;
1493 }
1494 
1496  __attribute__ ((weak));
1497 void
1499 {
1500 }
1501 
1502 static void
1504  u32 first_index, u32 last_index,
1505  vl_api_replay_t which)
1506 {
1507  vl_api_trace_file_header_t *hp;
1508  int i, fd;
1509  struct stat statb;
1510  size_t file_size;
1511  u8 *msg;
1512  u8 endian_swap_needed = 0;
1513  api_main_t *am = &api_main;
1514  u8 *tmpbuf = 0;
1515  u32 nitems;
1516  void **saved_print_handlers = 0;
1517 
1518  fd = open ((char *) filename, O_RDONLY);
1519 
1520  if (fd < 0)
1521  {
1522  vlib_cli_output (vm, "Couldn't open %s\n", filename);
1523  return;
1524  }
1525 
1526  if (fstat (fd, &statb) < 0)
1527  {
1528  vlib_cli_output (vm, "Couldn't stat %s\n", filename);
1529  close (fd);
1530  return;
1531  }
1532 
1533  if (!(statb.st_mode & S_IFREG) || (statb.st_size < sizeof (*hp)))
1534  {
1535  vlib_cli_output (vm, "File not plausible: %s\n", filename);
1536  close (fd);
1537  return;
1538  }
1539 
1540  file_size = statb.st_size;
1541  file_size = (file_size + 4095) & ~(4096);
1542 
1543  hp = mmap (0, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
1544 
1545  if (hp == (vl_api_trace_file_header_t *) MAP_FAILED)
1546  {
1547  vlib_cli_output (vm, "mmap failed: %s\n", filename);
1548  close (fd);
1549  return;
1550  }
1551  close (fd);
1552 
1553  if ((clib_arch_is_little_endian && hp->endian == VL_API_BIG_ENDIAN)
1554  || (clib_arch_is_big_endian && hp->endian == VL_API_LITTLE_ENDIAN))
1555  endian_swap_needed = 1;
1556 
1557  if (endian_swap_needed)
1558  nitems = ntohl (hp->nitems);
1559  else
1560  nitems = hp->nitems;
1561 
1562  if (last_index == (u32) ~ 0)
1563  {
1564  last_index = nitems - 1;
1565  }
1566 
1567  if (first_index >= nitems || last_index >= nitems)
1568  {
1569  vlib_cli_output (vm, "Range (%d, %d) outside file range (0, %d)\n",
1570  first_index, last_index, nitems - 1);
1571  munmap (hp, file_size);
1572  return;
1573  }
1574  if (hp->wrapped)
1575  vlib_cli_output (vm,
1576  "Note: wrapped/incomplete trace, results may vary\n");
1577 
1578  if (which == CUSTOM_DUMP)
1579  {
1580  saved_print_handlers = (void **) vec_dup (am->msg_print_handlers);
1582  }
1583 
1584 
1585  msg = (u8 *) (hp + 1);
1586 
1587  for (i = 0; i < first_index; i++)
1588  {
1589  trace_cfg_t *cfgp;
1590  int size;
1591  u16 msg_id;
1592 
1593  size = clib_host_to_net_u32 (*(u32 *) msg);
1594  msg += sizeof (u32);
1595 
1597  msg_id = ntohs (*((u16 *) msg));
1598  else
1599  msg_id = *((u16 *) msg);
1600 
1601  cfgp = am->api_trace_cfg + msg_id;
1602  if (!cfgp)
1603  {
1604  vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id);
1605  munmap (hp, file_size);
1606  return;
1607  }
1608  msg += size;
1609  }
1610 
1611  if (which == REPLAY)
1612  am->replay_in_progress = 1;
1613 
1614  for (; i <= last_index; i++)
1615  {
1616  trace_cfg_t *cfgp;
1617  u16 *msg_idp;
1618  u16 msg_id;
1619  int size;
1620 
1621  if (which == DUMP)
1622  vlib_cli_output (vm, "---------- trace %d -----------\n", i);
1623 
1624  size = clib_host_to_net_u32 (*(u32 *) msg);
1625  msg += sizeof (u32);
1626 
1628  msg_id = ntohs (*((u16 *) msg));
1629  else
1630  msg_id = *((u16 *) msg);
1631 
1632  cfgp = am->api_trace_cfg + msg_id;
1633  if (!cfgp)
1634  {
1635  vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id);
1636  munmap (hp, file_size);
1637  vec_free (tmpbuf);
1638  am->replay_in_progress = 0;
1639  return;
1640  }
1641 
1642  /* Copy the buffer (from the read-only mmap'ed file) */
1643  vec_validate (tmpbuf, size - 1 + sizeof (uword));
1644  clib_memcpy (tmpbuf + sizeof (uword), msg, size);
1645  memset (tmpbuf, 0xf, sizeof (uword));
1646 
1647  /*
1648  * Endian swap if needed. All msg data is supposed to be
1649  * in network byte order. All msg handlers are supposed to
1650  * know that. The generic message dumpers don't know that.
1651  * One could fix apigen, I suppose.
1652  */
1653  if ((which == DUMP && clib_arch_is_little_endian) || endian_swap_needed)
1654  {
1655  void (*endian_fp) (void *);
1656  if (msg_id >= vec_len (am->msg_endian_handlers)
1657  || (am->msg_endian_handlers[msg_id] == 0))
1658  {
1659  vlib_cli_output (vm, "Ugh: msg id %d no endian swap\n", msg_id);
1660  munmap (hp, file_size);
1661  vec_free (tmpbuf);
1662  am->replay_in_progress = 0;
1663  return;
1664  }
1665  endian_fp = am->msg_endian_handlers[msg_id];
1666  (*endian_fp) (tmpbuf + sizeof (uword));
1667  }
1668 
1669  /* msg_id always in network byte order */
1671  {
1672  msg_idp = (u16 *) (tmpbuf + sizeof (uword));
1673  *msg_idp = msg_id;
1674  }
1675 
1676  switch (which)
1677  {
1678  case CUSTOM_DUMP:
1679  case DUMP:
1680  if (msg_id < vec_len (am->msg_print_handlers) &&
1681  am->msg_print_handlers[msg_id])
1682  {
1683  u8 *(*print_fp) (void *, void *);
1684 
1685  print_fp = (void *) am->msg_print_handlers[msg_id];
1686  (*print_fp) (tmpbuf + sizeof (uword), vm);
1687  }
1688  else
1689  {
1690  vlib_cli_output (vm, "Skipping msg id %d: no print fcn\n",
1691  msg_id);
1692  break;
1693  }
1694  break;
1695 
1696  case INITIALIZERS:
1697  if (msg_id < vec_len (am->msg_print_handlers) &&
1698  am->msg_print_handlers[msg_id])
1699  {
1700  u8 *s;
1701  int j;
1702  u8 *(*print_fp) (void *, void *);
1703 
1704  print_fp = (void *) am->msg_print_handlers[msg_id];
1705 
1706  vlib_cli_output (vm, "/*");
1707 
1708  (*print_fp) (tmpbuf + sizeof (uword), vm);
1709  vlib_cli_output (vm, "*/\n");
1710 
1711  s = format (0, "static u8 * vl_api_%s_%d[%d] = {",
1712  am->msg_names[msg_id], i,
1713  am->api_trace_cfg[msg_id].size);
1714 
1715  for (j = 0; j < am->api_trace_cfg[msg_id].size; j++)
1716  {
1717  if ((j & 7) == 0)
1718  s = format (s, "\n ");
1719  s = format (s, "0x%02x,", tmpbuf[sizeof (uword) + j]);
1720  }
1721  s = format (s, "\n};\n%c", 0);
1722  vlib_cli_output (vm, (char *) s);
1723  vec_free (s);
1724  }
1725  break;
1726 
1727  case REPLAY:
1728  if (msg_id < vec_len (am->msg_print_handlers) &&
1729  am->msg_print_handlers[msg_id] && cfgp->replay_enable)
1730  {
1731  void (*handler) (void *);
1732 
1733  handler = (void *) am->msg_handlers[msg_id];
1734 
1735  if (!am->is_mp_safe[msg_id])
1737  (*handler) (tmpbuf + sizeof (uword));
1738  if (!am->is_mp_safe[msg_id])
1740  }
1741  else
1742  {
1743  if (cfgp->replay_enable)
1744  vlib_cli_output (vm, "Skipping msg id %d: no handler\n",
1745  msg_id);
1746  break;
1747  }
1748  break;
1749  }
1750 
1751  _vec_len (tmpbuf) = 0;
1752  msg += size;
1753  }
1754 
1755  if (saved_print_handlers)
1756  {
1757  clib_memcpy (am->msg_print_handlers, saved_print_handlers,
1758  vec_len (am->msg_print_handlers) * sizeof (void *));
1759  vec_free (saved_print_handlers);
1760  }
1761 
1762  munmap (hp, file_size);
1763  vec_free (tmpbuf);
1764  am->replay_in_progress = 0;
1765 }
1766 
1767 static clib_error_t *
1769  unformat_input_t * input, vlib_cli_command_t * cmd)
1770 {
1771  u32 nitems = 256 << 10;
1772  api_main_t *am = &api_main;
1774  u8 *filename;
1775  u32 first = 0;
1776  u32 last = (u32) ~ 0;
1777  FILE *fp;
1778  int rv;
1779 
1780  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1781  {
1782  if (unformat (input, "on") || unformat (input, "enable"))
1783  {
1784  if (unformat (input, "nitems %d", &nitems))
1785  ;
1786  vl_msg_api_trace_configure (am, which, nitems);
1787  vl_msg_api_trace_onoff (am, which, 1 /* on */ );
1788  }
1789  else if (unformat (input, "off"))
1790  {
1791  vl_msg_api_trace_onoff (am, which, 0);
1792  }
1793  else if (unformat (input, "save %s", &filename))
1794  {
1795  u8 *chroot_filename;
1796  if (strstr ((char *) filename, "..")
1797  || index ((char *) filename, '/'))
1798  {
1799  vlib_cli_output (vm, "illegal characters in filename '%s'",
1800  filename);
1801  return 0;
1802  }
1803 
1804  chroot_filename = format (0, "/tmp/%s%c", filename, 0);
1805 
1806  vec_free (filename);
1807 
1808  fp = fopen ((char *) chroot_filename, "w");
1809  if (fp == NULL)
1810  {
1811  vlib_cli_output (vm, "Couldn't create %s\n", chroot_filename);
1812  return 0;
1813  }
1814  rv = vl_msg_api_trace_save (am, which, fp);
1815  fclose (fp);
1816  if (rv == -1)
1817  vlib_cli_output (vm, "API Trace data not present\n");
1818  else if (rv == -2)
1819  vlib_cli_output (vm, "File for writing is closed\n");
1820  else if (rv == -10)
1821  vlib_cli_output (vm, "Error while writing header to file\n");
1822  else if (rv == -11)
1823  vlib_cli_output (vm, "Error while writing trace to file\n");
1824  else if (rv == -12)
1825  vlib_cli_output (vm,
1826  "Error while writing end of buffer trace to file\n");
1827  else if (rv == -13)
1828  vlib_cli_output (vm,
1829  "Error while writing start of buffer trace to file\n");
1830  else if (rv < 0)
1831  vlib_cli_output (vm, "Unkown error while saving: %d", rv);
1832  else
1833  vlib_cli_output (vm, "API trace saved to %s\n", chroot_filename);
1834  vec_free (chroot_filename);
1835  }
1836  else if (unformat (input, "dump %s", &filename))
1837  {
1838  vl_msg_api_process_file (vm, filename, first, last, DUMP);
1839  }
1840  else if (unformat (input, "custom-dump %s", &filename))
1841  {
1842  vl_msg_api_process_file (vm, filename, first, last, CUSTOM_DUMP);
1843  }
1844  else if (unformat (input, "replay %s", &filename))
1845  {
1846  vl_msg_api_process_file (vm, filename, first, last, REPLAY);
1847  }
1848  else if (unformat (input, "initializers %s", &filename))
1849  {
1850  vl_msg_api_process_file (vm, filename, first, last, INITIALIZERS);
1851  }
1852  else if (unformat (input, "tx"))
1853  {
1854  which = VL_API_TRACE_TX;
1855  }
1856  else if (unformat (input, "first %d", &first))
1857  {
1858  ;
1859  }
1860  else if (unformat (input, "last %d", &last))
1861  {
1862  ;
1863  }
1864  else if (unformat (input, "status"))
1865  {
1867  am, which);
1868  }
1869  else if (unformat (input, "free"))
1870  {
1871  vl_msg_api_trace_onoff (am, which, 0);
1872  vl_msg_api_trace_free (am, which);
1873  }
1874  else if (unformat (input, "post-mortem-on"))
1876  else if (unformat (input, "post-mortem-off"))
1878  else
1879  return clib_error_return (0, "unknown input `%U'",
1880  format_unformat_error, input);
1881  }
1882  return 0;
1883 }
1884 
1885 /* *INDENT-OFF* */
1887  .path = "api trace",
1888  .short_help =
1889  "api trace [on|off][dump|save|replay <file>][status][free][post-mortem-on]",
1890  .function = api_trace_command_fn,
1891 };
1892 /* *INDENT-ON* */
1893 
1894 static clib_error_t *
1896 {
1897  u32 nitems = 256 << 10;
1899  api_main_t *am = &api_main;
1900 
1901  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1902  {
1903  if (unformat (input, "on") || unformat (input, "enable"))
1904  {
1905  if (unformat (input, "nitems %d", &nitems))
1906  ;
1907  vl_msg_api_trace_configure (am, which, nitems);
1908  vl_msg_api_trace_onoff (am, which, 1 /* on */ );
1910  }
1911  else
1912  return clib_error_return (0, "unknown input `%U'",
1913  format_unformat_error, input);
1914  }
1915  return 0;
1916 }
1917 
1918 VLIB_CONFIG_FUNCTION (api_config_fn, "api-trace");
1919 
1920 static clib_error_t *
1922 {
1923  api_main_t *am = &api_main;
1924  u32 nitems;
1925 
1926  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1927  {
1928  if (unformat (input, "length %d", &nitems) ||
1929  (unformat (input, "len %d", &nitems)))
1930  {
1931  if (nitems >= 1024)
1932  am->vlib_input_queue_length = nitems;
1933  else
1934  clib_warning ("vlib input queue length %d too small, ignored",
1935  nitems);
1936  }
1937  else
1938  return clib_error_return (0, "unknown input `%U'",
1939  format_unformat_error, input);
1940  }
1941  return 0;
1942 }
1943 
1945 
1946 /*
1947  * fd.io coding-style-patch-verification: ON
1948  *
1949  * Local Variables:
1950  * eval: (c-set-style "gnu")
1951  * End:
1952  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
void vl_set_memory_region_name(const char *name)
Definition: memory_vlib.c:1206
void * vl_msg_api_alloc_as_if_client(int nbytes)
#define TRACE_VLIB_MEMORY_QUEUE
Definition: memory_vlib.c:41
#define vl_print(handle,...)
Definition: memory_vlib.c:50
static int memory_api_init(const char *region_name)
Definition: memory_vlib.c:365
#define SVM_GLOBAL_REGION_NAME
Definition: svm_common.h:88
const char * root_path
Definition: svm_common.h:67
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
void vl_api_memclnt_delete_t_handler(vl_api_memclnt_delete_t *mp)
Definition: memory_vlib.c:246
static void svm_pop_heap(void *oldheap)
Definition: svm.h:94
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:699
a
Definition: bitmap.h:516
#define SVM_FLAGS_NODATA
Definition: svm_common.h:29
int unix_shared_memory_queue_is_full(unix_shared_memory_queue_t *q)
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:290
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: memory_vlib.c:1173
static clib_error_t * api_queue_config_fn(vlib_main_t *vm, unformat_input_t *input)
Definition: memory_vlib.c:1921
static clib_error_t * setup_memclnt_exit(vlib_main_t *vm)
Definition: memory_vlib.c:863
u32 application_restarts
Definition: api_common.h:79
Fixed length block allocator.
unix_shared_memory_queue_t * vl_input_queue
Definition: api_common.h:68
static vlib_node_registration_t api_rx_from_node_node
(constructor) VLIB_REGISTER_NODE (api_rx_from_node_node)
Definition: memory_vlib.c:854
#define NULL
Definition: clib.h:55
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:192
static clib_error_t * vl_api_client_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: memory_vlib.c:929
u8 * message_bounce
Definition: api_common.h:176
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
static void vl_api_trace_plugin_msg_ids_t_handler(vl_api_trace_plugin_msg_ids_t *mp)
Definition: memory_vlib.c:1383
static clib_error_t * vl_api_message_table_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: memory_vlib.c:1060
static clib_error_t * vl_api_show_plugin_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: memory_vlib.c:1239
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
#define SVM_PVT_MHEAP_SIZE
Definition: svm_common.h:32
static clib_error_t * api_config_fn(vlib_main_t *vm, unformat_input_t *input)
Definition: memory_vlib.c:1895
ring_alloc_t * client_rings
Definition: api_common.h:76
static clib_error_t * vl_api_clear_histogram_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: memory_vlib.c:736
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
void vl_msg_api_send(vl_api_registration_t *rp, u8 *elem)
Definition: memory_vlib.c:104
#define pool_is_free(P, E)
Use free bitmap to query whether given element is free.
Definition: pool.h:230
static void vl_api_rpc_call_reply_t_handler(vl_api_rpc_call_reply_t *mp)
Definition: memory_vlib.c:1322
void vl_api_get_first_msg_id_t_handler(vl_api_get_first_msg_id_t *mp)
Definition: memory_vlib.c:317
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
void vl_enable_disable_memory_api(vlib_main_t *vm, int enable)
Definition: memory_vlib.c:795
#define VL_API_EPOCH_MASK
Definition: api_common.h:91
trace_cfg_t * api_trace_cfg
Definition: api_common.h:185
static vlib_cli_command_t cli_show_api_clients_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_clients_command)
Definition: memory_vlib.c:1044
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
_vl_msg_api_function_list_elt_t * reaper_function_registrations
Definition: api_common.h:253
void vl_msg_api_custom_dump_configure(api_main_t *am)
Definition: memory_vlib.c:1498
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:599
static f64 vlib_last_vector_length_per_node(vlib_main_t *vm)
Definition: main.h:283
static void vlib_worker_thread_barrier_check(void)
Definition: threads.h:356
static uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
Suspend a vlib cooperative multi-tasking thread for a period of time.
Definition: node_funcs.h:448
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:87
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:67
_vlib_init_function_list_elt_t * api_init_function_registrations
Definition: main.h:168
static vlib_cli_command_t cli_show_api_status_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_status_command)
Definition: memory_vlib.c:1052
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
static int range_compare(vl_api_msg_range_t *a0, vl_api_msg_range_t *a1)
Definition: memory_vlib.c:1214
vl_api_trace_t * rx_trace
Definition: api_common.h:182
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:542
void vl_msg_api_handler_no_trace_no_free(void *the_msg)
Definition: api_shared.c:562
u32 ring_misses
Definition: api_common.h:179
static void * svm_push_data_heap(svm_region_t *rp)
Definition: svm.h:86
vl_api_registration_t ** vl_clients
Definition: api_common.h:190
static vlib_cli_command_t cli_show_api_message_table_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_message_table_command)
Definition: memory_vlib.c:1099
int i32
Definition: types.h:81
#define clib_arch_is_little_endian
Definition: byte_order.h:54
char i8
Definition: types.h:45
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
int replay_in_progress
Definition: api_common.h:250
static void send_one_plugin_msg_ids_msg(u8 *name, u16 first_msg_id, u16 last_msg_id)
Definition: memory_vlib.c:417
const char * root_path
Definition: api_common.h:247
#define clib_error_return(e, args...)
Definition: error.h:99
svm_region_t * vlib_rp
Definition: api_common.h:187
clib_error_t * vlib_call_init_exit_functions(vlib_main_t *vm, _vlib_init_function_list_elt_t *head, int call_once)
Definition: init.c:43
static clib_error_t * api_trace_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: memory_vlib.c:1768
#define SVM_GLOBAL_REGION_BASEVA
Definition: svm_common.h:86
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Definition: api_common.h:189
static void * vl_api_memclnt_create_t_print(vl_api_memclnt_create_t *a, void *handle)
Definition: memory_vlib.c:56
void vl_socket_api_send(vl_api_registration_t *rp, u8 *elem)
Definition: memory_vlib.c:95
#define foreach_plugin_trace_msg
Definition: memory_vlib.c:1421
static uword pointer_to_uword(const void *p)
Definition: types.h:131
void * vl_msg_api_alloc(int nbytes)
static void memclnt_queue_callback(vlib_main_t *vm)
Definition: memory_vlib.c:766
static void vlib_set_queue_signal_callback(vlib_main_t *vm, void(*fp)(vlib_main_t *))
Definition: main.h:319
vl_shmem_hdr_t * shmem_hdr
static heap_elt_t * first(heap_header_t *h)
Definition: heap.c:59
int vl_msg_api_trace_free(api_main_t *am, vl_api_trace_which_t which)
Definition: api_shared.c:154
vl_registration_type_t registration_type
Definition: api_common.h:38
static vlib_cli_command_t api_trace_command
(constructor) VLIB_CLI_COMMAND (api_trace_command)
Definition: memory_vlib.c:1886
static void * vl_api_trace_plugin_msg_ids_t_print(vl_api_trace_plugin_msg_ids_t *a, void *handle)
Definition: memory_vlib.c:76
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
#define foreach_rpc_api_msg
Definition: memory_vlib.c:1417
static vlib_node_registration_t memclnt_node
(constructor) VLIB_REGISTER_NODE (memclnt_node)
Definition: memory_vlib.c:757
static clib_error_t * vl_api_ring_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: memory_vlib.c:873
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:71
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:946
static int call_reaper_functions(u32 client_index)
Definition: memory_vlib.c:226
void(** msg_print_handlers)(void *, void *)
Definition: api_common.h:174
int replay_enable
Definition: api_common.h:71
struct _unformat_input_t unformat_input_t
static vlib_cli_command_t cli_show_api_ring_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_ring_command)
Definition: memory_vlib.c:1036
void vl_msg_api_free(void *)
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:374
#define ELOG_DATA(em, f)
Definition: elog.h:481
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:119
void svm_region_init_args(svm_map_region_args_t *a)
Definition: svm.c:834
void vl_msg_api_barrier_sync(void)
Definition: api_shared.c:383
static void vl_api_rpc_call_t_handler(vl_api_rpc_call_t *mp)
Definition: memory_vlib.c:1277
#define SVM_GLOBAL_REGION_SIZE
Definition: svm_common.h:87
static u32 vl_msg_api_handle_get_index(u32 index)
Definition: api.h:37
vl_api_replay_t
Definition: memory_vlib.c:1451
#define foreach_vlib_api_msg
Definition: memory_vlib.c:356
void vl_msg_api_handler_with_vm_node(api_main_t *am, void *the_msg, vlib_main_t *vm, vlib_node_runtime_t *node)
Definition: api_shared.c:465
volatile u32 queue_signal_pending
Definition: main.h:173
#define uword_to_pointer(u, type)
Definition: types.h:136
int vl_msg_api_trace_save(api_main_t *am, vl_api_trace_which_t which, FILE *fp)
Definition: api_shared.c:191
u64 global_size
Definition: api_common.h:212
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
#define clib_arch_is_big_endian
Definition: byte_order.h:53
int vl_msg_api_trace_onoff(api_main_t *am, vl_api_trace_which_t which, int onoff)
Definition: api_shared.c:112
api_main_t api_main
Definition: api_shared.c:35
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
ring_alloc_t * vl_rings
Definition: api_common.h:73
svmdb_client_t * c
u16 n_vectors
Definition: node.h:345
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:185
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: memory_vlib.c:1328
void serialize_open_vector(serialize_main_t *m, u8 *vector)
Definition: serialize.c:908
void vl_unmap_shmem(void)
u64 global_baseva
Definition: api_common.h:209
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
unix_shared_memory_queue_t * vl_input_queue
Definition: api_common.h:51
vl_api_msg_range_t * msg_ranges
Definition: api_common.h:201
#define clib_warning(format, args...)
Definition: error.h:59
#define clib_memcpy(a, b, c)
Definition: string.h:69
#define foreach_histogram_bucket
Definition: memory_vlib.c:395
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
u32 garbage_collects
Definition: api_common.h:85
elog_main_t elog_main
Definition: main.h:141
static void serialize_integer(serialize_main_t *m, u64 x, u32 n_bytes)
Definition: serialize.h:185
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
Definition: threads.c:1166
#define ARRAY_LEN(x)
Definition: clib.h:59
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:439
const char ** msg_names
Definition: api_common.h:175
void vl_msg_api_barrier_release(void)
Definition: api_shared.c:388
static vlib_cli_command_t cli_show_api_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_command)
Definition: memory_vlib.c:1029
static clib_error_t * vl_api_trace_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: memory_vlib.c:1107
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: memory_vlib.c:1503
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define VL_API_BIG_ENDIAN
Definition: api_common.h:95
histogram_index_t
Definition: memory_vlib.c:401
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
vl_api_trace_t * tx_trace
Definition: api_common.h:183
static uword api_rx_from_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: memory_vlib.c:804
static vlib_cli_command_t cli_show_api_plugin_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_plugin_command)
Definition: memory_vlib.c:1269
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:255
#define ASSERT(truth)
static uword hash_elts(void *v)
Definition: hash.h:117
unsigned int u32
Definition: types.h:88
clib_error_t * vlibmemory_init(vlib_main_t *vm)
Definition: memory_vlib.c:1181
#define VL_API_LITTLE_ENDIAN
Definition: api_common.h:94
static u64 vector_rate_histogram[SLEEP_N_BUCKETS]
Definition: memory_vlib.c:409
static uword memclnt_process(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f)
Definition: memory_vlib.c:439
VLIB_API_INIT_FUNCTION(rpc_api_hookup)
u64 size
Definition: vhost-user.h:75
u8 * vl_api_serialize_message_table(api_main_t *am, u8 *vector)
Definition: memory_vlib.c:117
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:109
static void clib_mem_free(void *p)
Definition: mem.h:176
u8 * serialized_message_table_in_shmem
Definition: api_common.h:192
#define clib_error_report(e)
Definition: error.h:113
static void * vlib_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:286
void dump_socket_clients(vlib_main_t *vm, api_main_t *am)
Definition: memory_vlib.c:924
u64 global_pvt_heap_size
Definition: api_common.h:218
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
Definition: node_funcs.h:146
static void * clib_mem_alloc(uword size)
Definition: mem.h:109
u32 restart_reclaims
Definition: api_common.h:82
static u8 * format_api_msg_range(u8 *s, va_list *args)
Definition: memory_vlib.c:1225
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u64 uword
Definition: types.h:112
static clib_error_t * rpc_api_hookup(vlib_main_t *vm)
Definition: memory_vlib.c:1425
static clib_error_t * vl_api_status_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: memory_vlib.c:994
u32 missing_clients
Definition: api_common.h:181
void vl_msg_api_post_mortem_dump_enable_disable(int enable)
Definition: api_shared.c:753
unsigned short u16
Definition: types.h:57
void vl_msg_api_send_shmem_nolock(unix_shared_memory_queue_t *q, u8 *elem)
void vl_api_memclnt_create_t_handler(vl_api_memclnt_create_t *mp)
Definition: memory_vlib.c:143
void(** msg_endian_handlers)(void *)
Definition: api_common.h:173
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:349
const char * name
Definition: svm_common.h:68
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:960
u8 * format_vl_msg_api_trace_status(u8 *s, va_list *args)
Definition: memory_vlib.c:1460
u32 vl_api_registration_pool_index
Definition: api_common.h:41
void svm_client_scan_this_region_nolock(svm_region_t *rp)
Definition: svm.c:1127
static clib_error_t * vl_api_show_histogram_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cli_cmd)
Definition: memory_vlib.c:693
volatile u32 api_queue_nonempty
Definition: main.h:174
#define hash_get_mem(h, key)
Definition: hash.h:268
void(** msg_handlers)(void *)
Definition: api_common.h:170
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1198
u8 * is_mp_safe
Definition: api_common.h:177
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:144
u8 data[0]
Packet data.
Definition: buffer.h:152
int msg_print_flag
Definition: api_common.h:184
void * serialize_close_vector(serialize_main_t *m)
Definition: serialize.c:918
static void * vl_api_memclnt_delete_t_print(vl_api_memclnt_delete_t *a, void *handle)
Definition: memory_vlib.c:67
vl_api_trace_which_t
Definition: api_common.h:88
const char * region_name
Definition: api_common.h:246
static u32 vl_msg_api_handle_get_epoch(u32 index)
Definition: api.h:31
int vl_map_shmem(const char *region_name, int is_vlib)
uword * msg_index_by_name_and_crc
Definition: api_common.h:244
int vl_msg_api_trace_configure(api_main_t *am, vl_api_trace_which_t which, u32 nitems)
Definition: api_shared.c:322
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
uword * msg_range_by_name
Definition: api_common.h:198
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
u32 vlib_input_queue_length
Definition: api_common.h:241
pthread_mutex_t mutex
Definition: svm_common.h:37
static u32 vl_msg_api_handle_from_index_and_epoch(u32 index, u32 epoch)
Definition: api.h:43
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109