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