FD.io VPP  v17.01.1-3-gc6833f8
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 <signal.h>
26 #include <pthread.h>
27 #include <vppinfra/vec.h>
28 #include <vppinfra/hash.h>
29 #include <vppinfra/pool.h>
30 #include <vppinfra/format.h>
31 #include <vppinfra/byte_order.h>
32 #include <vppinfra/elog.h>
33 #include <stdarg.h>
34 #include <vlib/vlib.h>
35 #include <vlib/unix/unix.h>
36 #include <vlibapi/api.h>
37 #include <vlibmemory/api.h>
38 
39 #define TRACE_VLIB_MEMORY_QUEUE 0
40 
41 #include <vlibmemory/vl_memory_msg_enum.h> /* enumerate all vlib messages */
42 
43 #define vl_typedefs /* define message structures */
45 #undef vl_typedefs
46 
47 /* instantiate all the print functions we know about */
48 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
49 #define vl_printfun
51 #undef vl_printfun
52 
53 static inline void *
55 {
56  vl_print (handle, "vl_api_memclnt_create_t:\n");
57  vl_print (handle, "name: %s\n", a->name);
58  vl_print (handle, "input_queue: 0x%wx\n", a->input_queue);
59  vl_print (handle, "context: %u\n", (unsigned) a->context);
60  vl_print (handle, "ctx_quota: %ld\n", (long) a->ctx_quota);
61  return handle;
62 }
63 
64 static inline void *
66 {
67  vl_print (handle, "vl_api_memclnt_delete_t:\n");
68  vl_print (handle, "index: %u\n", (unsigned) a->index);
69  vl_print (handle, "handle: 0x%wx\n", a->handle);
70  return handle;
71 }
72 
73 /* instantiate all the endian swap functions we know about */
74 #define vl_endianfun
76 #undef vl_endianfun
77 
79  __attribute__ ((weak));
80 
81 void
83 {
84  static int count;
85 
86  if (count++ < 5)
87  clib_warning ("need to link against -lvlibsocket, msg not sent!");
88 }
89 
90 void
92 {
94  {
95  vl_socket_api_send (rp, elem);
96  }
97  else
98  {
100  }
101 }
102 
103 u8 *
105 {
106  serialize_main_t _sm, *sm = &_sm;
107  hash_pair_t *hp;
109 
110  serialize_open_vector (sm, vector);
111 
112  /* serialize the count */
113  serialize_integer (sm, nmsg, sizeof (u32));
114 
116  {
117  serialize_likely_small_unsigned_integer
118  (sm, hp->value[0]);
119  serialize_cstring
120  (sm,
121  (char *) hp->key);
122  }));
123 
124  return serialize_close_vector (sm);
125 }
126 
127 /*
128  * vl_api_memclnt_create_t_handler
129  */
130 void
132 {
133  vl_api_registration_t **regpp;
134  vl_api_registration_t *regp;
136  svm_region_t *svm;
138  int rv = 0;
139  void *oldheap;
140  api_main_t *am = &api_main;
141  u8 *serialized_message_table = 0;
142 
143  /*
144  * This is tortured. Maintain a vlib-address-space private
145  * pool of client registrations. We use the shared-memory virtual
146  * address of client structure as a handle, to allow direct
147  * manipulation of context quota vbls from the client library.
148  *
149  * This scheme causes trouble w/ API message trace replay, since
150  * some random VA from clib_mem_alloc() certainly won't
151  * occur in the Linux sim. The (very) few places
152  * that care need to use the pool index.
153  *
154  * Putting the registration object(s) into a pool in shared memory and
155  * using the pool index as a handle seems like a great idea.
156  * Unfortunately, each and every reference to that pool would need
157  * to be protected by a mutex:
158  *
159  * Client VLIB
160  * ------ ----
161  * convert pool index to
162  * pointer.
163  * <deschedule>
164  * expand pool
165  * <deschedule>
166  * kaboom!
167  */
168 
169  pool_get (am->vl_clients, regpp);
170 
171  svm = am->vlib_rp;
172 
174  serialized_message_table = vl_api_serialize_message_table (am, 0);
175 
176  pthread_mutex_lock (&svm->mutex);
177  oldheap = svm_push_data_heap (svm);
178  *regpp = clib_mem_alloc (sizeof (vl_api_registration_t));
179 
180  regp = *regpp;
181  memset (regp, 0, sizeof (*regp));
183  regp->vl_api_registration_pool_index = regpp - am->vl_clients;
184 
186  mp->input_queue;
187 
188  regp->name = format (0, "%s", mp->name);
189  vec_add1 (regp->name, 0);
190  if (serialized_message_table)
192  vec_dup (serialized_message_table);
193 
194  pthread_mutex_unlock (&svm->mutex);
195  svm_pop_heap (oldheap);
196 
197  vec_free (serialized_message_table);
198 
199  rp = vl_msg_api_alloc (sizeof (*rp));
200  rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_CREATE_REPLY);
201  rp->handle = (uword) regp;
205  rp->context = mp->context;
206  rp->response = ntohl (rv);
208 
209  vl_msg_api_send_shmem (q, (u8 *) & rp);
210 }
211 
212 /* Application callback to clean up leftover registrations from this client */
213 int vl_api_memclnt_delete_callback (u32 client_index) __attribute__ ((weak));
214 
215 int
217 {
218  return 0;
219 }
220 
221 /*
222  * vl_api_memclnt_delete_t_handler
223  */
224 void
226 {
227  vl_api_registration_t **regpp;
228  vl_api_registration_t *regp;
230  svm_region_t *svm;
231  void *oldheap;
232  api_main_t *am = &api_main;
233  u32 handle, client_index, epoch;
234 
235  handle = mp->index;
236 
237  if (vl_api_memclnt_delete_callback (handle))
238  return;
239 
240  epoch = vl_msg_api_handle_get_epoch (handle);
241  client_index = vl_msg_api_handle_get_index (handle);
242 
243  if (epoch != (am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK))
244  {
246  ("Stale clnt delete index %d old epoch %d cur epoch %d",
247  client_index, epoch,
249  return;
250  }
251 
252  regpp = am->vl_clients + client_index;
253 
254  if (!pool_is_free (am->vl_clients, regpp))
255  {
256  regp = *regpp;
257  svm = am->vlib_rp;
258 
259  /* $$$ check the input queue for e.g. punted sf's */
260 
261  rp = vl_msg_api_alloc (sizeof (*rp));
262  rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_DELETE_REPLY);
263  rp->handle = mp->handle;
264  rp->response = 1;
265 
266  vl_msg_api_send_shmem (regp->vl_input_queue, (u8 *) & rp);
267 
268  if (client_index != regp->vl_api_registration_pool_index)
269  {
270  clib_warning ("mismatch client_index %d pool_index %d",
271  client_index, regp->vl_api_registration_pool_index);
272  vl_msg_api_free (rp);
273  return;
274  }
275 
276  /* No dangling references, please */
277  *regpp = 0;
278 
280 
281  pthread_mutex_lock (&svm->mutex);
282  oldheap = svm_push_data_heap (svm);
283  /* Poison the old registration */
284  memset (regp, 0xF1, sizeof (*regp));
285  clib_mem_free (regp);
286  pthread_mutex_unlock (&svm->mutex);
287  svm_pop_heap (oldheap);
288  }
289  else
290  {
291  clib_warning ("unknown client ID %d", mp->index);
292  }
293 }
294 
295 void
297 {
300  uword *p;
301  api_main_t *am = &api_main;
302  vl_api_msg_range_t *rp;
303  u8 name[64];
304  u16 first_msg_id = ~0;
305  int rv = -7; /* VNET_API_ERROR_INVALID_VALUE */
306 
308  if (!q)
309  return;
310 
311  if (am->msg_range_by_name == 0)
312  goto out;
313 
314  strncpy ((char *) name, (char *) mp->name, ARRAY_LEN (name) - 1);
315 
316  p = hash_get_mem (am->msg_range_by_name, name);
317  if (p == 0)
318  goto out;
319 
320  rp = vec_elt_at_index (am->msg_ranges, p[0]);
321 
322  first_msg_id = rp->first_msg_id;
323  rv = 0;
324 
325 out:
326 
327  rmp = vl_msg_api_alloc (sizeof (*rmp));
328  rmp->_vl_msg_id = ntohs (VL_API_GET_FIRST_MSG_ID_REPLY);
329  rmp->context = mp->context;
330  rmp->retval = ntohl (rv);
331  rmp->first_msg_id = ntohs (first_msg_id);
332  vl_msg_api_send_shmem (q, (u8 *) & rmp);
333 }
334 
335 #define foreach_vlib_api_msg \
336 _(MEMCLNT_CREATE, memclnt_create) \
337 _(MEMCLNT_DELETE, memclnt_delete) \
338 _(GET_FIRST_MSG_ID, get_first_msg_id)
339 
340 /*
341  * vl_api_init
342  */
343 static int
344 memory_api_init (char *region_name)
345 {
346  int rv;
348  vl_msg_api_msg_config_t *c = &cfg;
349 
350  memset (c, 0, sizeof (*c));
351 
352  if ((rv = vl_map_shmem (region_name, 1 /* is_vlib */ )) < 0)
353  return rv;
354 
355 #define _(N,n) do { \
356  c->id = VL_API_##N; \
357  c->name = #n; \
358  c->handler = vl_api_##n##_t_handler; \
359  c->cleanup = vl_noop_handler; \
360  c->endian = vl_api_##n##_t_endian; \
361  c->print = vl_api_##n##_t_print; \
362  c->size = sizeof(vl_api_##n##_t); \
363  c->traced = 1; /* trace, so these msgs print */ \
364  c->replay = 0; /* don't replay client create/delete msgs */ \
365  c->message_bounce = 0; /* don't bounce this message */ \
366  vl_msg_api_config(c);} while (0);
367 
369 #undef _
370 
371  return 0;
372 }
373 
374 #define foreach_histogram_bucket \
375 _(400) \
376 _(200) \
377 _(100) \
378 _(10)
379 
380 typedef enum
381 {
382 #define _(n) SLEEP_##n##_US,
384 #undef _
387 
389 
390 static void memclnt_queue_callback (vlib_main_t * vm);
391 
392 static uword
394  vlib_node_runtime_t * node, vlib_frame_t * f)
395 {
396  uword mp;
397  vl_shmem_hdr_t *shm;
399  clib_error_t *e;
400  int rv;
401  api_main_t *am = &api_main;
402  f64 dead_client_scan_time;
403  f64 sleep_time, start_time;
404  f64 vector_rate;
405 
407 
408  if ((rv = memory_api_init (am->region_name)) < 0)
409  {
410  clib_warning ("memory_api_init returned %d, wait for godot...", rv);
411  vlib_process_suspend (vm, 1e70);
412  }
413 
414  shm = am->shmem_hdr;
415  ASSERT (shm);
416  q = shm->vl_input_queue;
417  ASSERT (q);
418 
420  (vm, vm->api_init_function_registrations, 1 /* call_once */ );
421  if (e)
422  clib_error_report (e);
423 
424  sleep_time = 20.0;
425  dead_client_scan_time = vlib_time_now (vm) + 20.0;
426 
427  /* $$$ pay attention to frame size, control CPU usage */
428  while (1)
429  {
430  uword event_type __attribute__ ((unused));
431  i8 *headp;
432  int need_broadcast;
433 
434  /*
435  * There's a reason for checking the queue before
436  * sleeping. If the vlib application crashes, it's entirely
437  * possible for a client to enqueue a connect request
438  * during the process restart interval.
439  *
440  * Unless some force of physics causes the new incarnation
441  * of the application to process the request, the client will
442  * sit and wait for Godot...
443  */
444  vector_rate = vlib_last_vector_length_per_node (vm);
445  start_time = vlib_time_now (vm);
446  while (1)
447  {
448  pthread_mutex_lock (&q->mutex);
449  if (q->cursize == 0)
450  {
451  vm->api_queue_nonempty = 0;
452  pthread_mutex_unlock (&q->mutex);
453 
455  {
456  /* *INDENT-OFF* */
457  ELOG_TYPE_DECLARE (e) =
458  {
459  .format = "q-underflow: len %d",
460  .format_args = "i4",
461  };
462  /* *INDENT-ON* */
463  struct
464  {
465  u32 len;
466  } *ed;
467  ed = ELOG_DATA (&vm->elog_main, e);
468  ed->len = 0;
469  }
470  sleep_time = 20.0;
471  break;
472  }
473 
474  headp = (i8 *) (q->data + sizeof (uword) * q->head);
475  clib_memcpy (&mp, headp, sizeof (uword));
476 
477  q->head++;
478  need_broadcast = (q->cursize == q->maxsize / 2);
479  q->cursize--;
480 
481  if (PREDICT_FALSE (q->head == q->maxsize))
482  q->head = 0;
483  pthread_mutex_unlock (&q->mutex);
484  if (need_broadcast)
485  (void) pthread_cond_broadcast (&q->condvar);
486 
487  vl_msg_api_handler_with_vm_node (am, (void *) mp, vm, node);
488 
489  /* Allow no more than 10us without a pause */
490  if (vlib_time_now (vm) > start_time + 10e-6)
491  {
492  int index = SLEEP_400_US;
493  if (vector_rate > 40.0)
494  sleep_time = 400e-6;
495  else if (vector_rate > 20.0)
496  {
497  index = SLEEP_200_US;
498  sleep_time = 200e-6;
499  }
500  else if (vector_rate >= 1.0)
501  {
502  index = SLEEP_100_US;
503  sleep_time = 100e-6;
504  }
505  else
506  {
507  index = SLEEP_10_US;
508  sleep_time = 10e-6;
509  }
510  vector_rate_histogram[index] += 1;
511  break;
512  }
513  }
514 
515  event_type = vlib_process_wait_for_event_or_clock (vm, sleep_time);
516  vm->queue_signal_pending = 0;
517  vlib_process_get_events (vm, 0 /* event_data */ );
518 
519  if (vlib_time_now (vm) > dead_client_scan_time)
520  {
521  vl_api_registration_t **regpp;
522  vl_api_registration_t *regp;
524  static u32 *dead_indices;
525  static u32 *confused_indices;
526 
527  vec_reset_length (dead_indices);
528  vec_reset_length (confused_indices);
529 
530  /* *INDENT-OFF* */
531  pool_foreach (regpp, am->vl_clients,
532  ({
533  regp = *regpp;
534  if (regp)
535  {
536  q = regp->vl_input_queue;
537  if (kill (q->consumer_pid, 0) < 0)
538  {
539  vec_add1(dead_indices, regpp - am->vl_clients);
540  }
541  }
542  else
543  {
544  clib_warning ("NULL client registration index %d",
545  regpp - am->vl_clients);
546  vec_add1 (confused_indices, regpp - am->vl_clients);
547  }
548  }));
549  /* *INDENT-ON* */
550  /* This should "never happen," but if it does, fix it... */
551  if (PREDICT_FALSE (vec_len (confused_indices) > 0))
552  {
553  int i;
554  for (i = 0; i < vec_len (confused_indices); i++)
555  {
556  pool_put_index (am->vl_clients, confused_indices[i]);
557  }
558  }
559 
560  if (PREDICT_FALSE (vec_len (dead_indices) > 0))
561  {
562  int i;
563  svm_region_t *svm;
564  void *oldheap;
565 
566  /* Allow the application to clean up its registrations */
567  for (i = 0; i < vec_len (dead_indices); i++)
568  {
569  regpp = pool_elt_at_index (am->vl_clients, dead_indices[i]);
570  if (regpp)
571  {
572  u32 handle;
573 
575  (dead_indices[i], shm->application_restarts);
576  (void) vl_api_memclnt_delete_callback (handle);
577  }
578  }
579 
580  svm = am->vlib_rp;
581  pthread_mutex_lock (&svm->mutex);
582  oldheap = svm_push_data_heap (svm);
583 
584  for (i = 0; i < vec_len (dead_indices); i++)
585  {
586  regpp = pool_elt_at_index (am->vl_clients, dead_indices[i]);
587  if (regpp)
588  {
589  /* Poison the old registration */
590  memset (*regpp, 0xF3, sizeof (**regpp));
591  clib_mem_free (*regpp);
592  /* no dangling references, please */
593  *regpp = 0;
594  }
595  else
596  {
597  svm_pop_heap (oldheap);
598  clib_warning ("Duplicate free, client index %d",
599  regpp - am->vl_clients);
600  oldheap = svm_push_data_heap (svm);
601  }
602  }
603 
605 
606  pthread_mutex_unlock (&svm->mutex);
607  svm_pop_heap (oldheap);
608  for (i = 0; i < vec_len (dead_indices); i++)
609  pool_put_index (am->vl_clients, dead_indices[i]);
610  }
611 
612  dead_client_scan_time = vlib_time_now (vm) + 20.0;
613  }
614 
616  {
617  /* *INDENT-OFF* */
618  ELOG_TYPE_DECLARE (e) = {
619  .format = "q-awake: len %d",
620  .format_args = "i4",
621  };
622  /* *INDENT-ON* */
623  struct
624  {
625  u32 len;
626  } *ed;
627  ed = ELOG_DATA (&vm->elog_main, e);
628  ed->len = q->cursize;
629  }
630  }
631 
632  return 0;
633 }
634 
635 static clib_error_t *
637  unformat_input_t * input,
638  vlib_cli_command_t * cli_cmd)
639 {
640  u64 total_counts = 0;
641  int i;
642 
643  for (i = 0; i < SLEEP_N_BUCKETS; i++)
644  {
645  total_counts += vector_rate_histogram[i];
646  }
647 
648  if (total_counts == 0)
649  {
650  vlib_cli_output (vm, "No control-plane activity.");
651  return 0;
652  }
653 
654 #define _(n) \
655  do { \
656  f64 percent; \
657  percent = ((f64) vector_rate_histogram[SLEEP_##n##_US]) \
658  / (f64) total_counts; \
659  percent *= 100.0; \
660  vlib_cli_output (vm, "Sleep %3d us: %llu, %.2f%%",n, \
661  vector_rate_histogram[SLEEP_##n##_US], \
662  percent); \
663  } while (0);
665 #undef _
666 
667  return 0;
668 }
669 
670 /* *INDENT-OFF* */
671 VLIB_CLI_COMMAND (cli_show_api_histogram_command, static) = {
672  .path = "show api histogram",
673  .short_help = "show api histogram",
674  .function = vl_api_show_histogram_command,
675 };
676 /* *INDENT-ON* */
677 
678 static clib_error_t *
680  unformat_input_t * input,
681  vlib_cli_command_t * cli_cmd)
682 {
683  int i;
684 
685  for (i = 0; i < SLEEP_N_BUCKETS; i++)
686  vector_rate_histogram[i] = 0;
687  return 0;
688 }
689 
690 /* *INDENT-OFF* */
691 VLIB_CLI_COMMAND (cli_clear_api_histogram_command, static) = {
692  .path = "clear api histogram",
693  .short_help = "clear api histogram",
694  .function = vl_api_clear_histogram_command,
695 };
696 /* *INDENT-ON* */
697 
698 
699 /* *INDENT-OFF* */
701  .function = memclnt_process,
702  .type = VLIB_NODE_TYPE_PROCESS,
703  .name = "api-rx-from-ring",
704  .state = VLIB_NODE_STATE_DISABLED,
705 };
706 /* *INDENT-ON* */
707 
708 static void
710 {
711  static volatile int *cursizep;
712 
713  if (PREDICT_FALSE (cursizep == 0))
714  {
715  api_main_t *am = &api_main;
718 
719  if (shmem_hdr == 0)
720  return;
721 
722  q = shmem_hdr->vl_input_queue;
723  if (q == 0)
724  return;
725  cursizep = &q->cursize;
726  }
727 
728  if (*cursizep >= 1)
729  {
730  vm->queue_signal_pending = 1;
731  vm->api_queue_nonempty = 1;
733  /* event_type */ 0, /* event_data */ 0);
734  }
735 }
736 
737 void
739 {
741  (enable
742  ? VLIB_NODE_STATE_POLLING
743  : VLIB_NODE_STATE_DISABLED));
744 }
745 
746 static uword
748  vlib_node_runtime_t * node, vlib_frame_t * frame)
749 {
750  uword n_packets = frame->n_vectors;
751  uword n_left_from;
752  u32 *from;
753  static u8 *long_msg;
754 
755  vec_validate (long_msg, 4095);
756  n_left_from = frame->n_vectors;
757  from = vlib_frame_args (frame);
758 
759  while (n_left_from > 0)
760  {
761  u32 bi0;
762  vlib_buffer_t *b0;
763  void *msg;
764  uword msg_len;
765 
766  bi0 = from[0];
767  b0 = vlib_get_buffer (vm, bi0);
768  from += 1;
769  n_left_from -= 1;
770 
771  msg = b0->data + b0->current_data;
772  msg_len = b0->current_length;
774  {
775  ASSERT (long_msg != 0);
776  _vec_len (long_msg) = 0;
777  vec_add (long_msg, msg, msg_len);
778  while (b0->flags & VLIB_BUFFER_NEXT_PRESENT)
779  {
780  b0 = vlib_get_buffer (vm, b0->next_buffer);
781  msg = b0->data + b0->current_data;
782  msg_len = b0->current_length;
783  vec_add (long_msg, msg, msg_len);
784  }
785  msg = long_msg;
786  }
788  }
789 
790  /* Free what we've been given. */
791  vlib_buffer_free (vm, vlib_frame_args (frame), n_packets);
792 
793  return n_packets;
794 }
795 
796 /* *INDENT-OFF* */
798  .function = api_rx_from_node,
799  .type = VLIB_NODE_TYPE_INTERNAL,
800  .vector_size = 4,
801  .name = "api-rx-from-node",
802 };
803 /* *INDENT-ON* */
804 
805 static clib_error_t *
807 {
808  atexit (vl_unmap_shmem);
809  return 0;
810 }
811 
813 
814 
815 static clib_error_t *
817  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
818 {
819  int i;
820  ring_alloc_t *ap;
822  api_main_t *am = &api_main;
823 
824  shmem_hdr = am->shmem_hdr;
825 
826  if (shmem_hdr == 0)
827  {
828  vlib_cli_output (vm, "Shared memory segment not initialized...\n");
829  return 0;
830  }
831 
832  vlib_cli_output (vm, "%8s %8s %8s %8s %8s\n",
833  "Owner", "Size", "Nitems", "Hits", "Misses");
834 
835  ap = shmem_hdr->vl_rings;
836 
837  for (i = 0; i < vec_len (shmem_hdr->vl_rings); i++)
838  {
839  vlib_cli_output (vm, "%8s %8d %8d %8d %8d\n",
840  "vlib", ap->size, ap->nitems, ap->hits, ap->misses);
841  ap++;
842  }
843 
844  ap = shmem_hdr->client_rings;
845 
846  for (i = 0; i < vec_len (shmem_hdr->client_rings); i++)
847  {
848  vlib_cli_output (vm, "%8s %8d %8d %8d %8d\n",
849  "clnt", ap->size, ap->nitems, ap->hits, ap->misses);
850  ap++;
851  }
852 
853  vlib_cli_output (vm, "%d ring miss fallback allocations\n",
854  am->ring_misses);
855 
856  vlib_cli_output (vm, "%d application restarts, %d reclaimed msgs\n",
857  shmem_hdr->application_restarts,
858  shmem_hdr->restart_reclaims);
859  return 0;
860 }
861 
863  __attribute__ ((weak));
864 
865 void
867 {
868 }
869 
870 static clib_error_t *
872  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
873 {
874  vl_api_registration_t **regpp, *regp;
876  char *health;
877  api_main_t *am = &api_main;
878  u32 *confused_indices = 0;
879 
880  if (!pool_elts (am->vl_clients))
881  goto socket_clients;
882  vlib_cli_output (vm, "Shared memory clients");
883  vlib_cli_output (vm, "%16s %8s %14s %18s %s",
884  "Name", "PID", "Queue Length", "Queue VA", "Health");
885 
886  /* *INDENT-OFF* */
887  pool_foreach (regpp, am->vl_clients,
888  ({
889  regp = *regpp;
890 
891  if (regp)
892  {
893  q = regp->vl_input_queue;
894  if (kill (q->consumer_pid, 0) < 0)
895  {
896  health = "DEAD";
897  }
898  else
899  {
900  health = "alive";
901  }
902  vlib_cli_output (vm, "%16s %8d %14d 0x%016llx %s\n",
903  regp->name, q->consumer_pid, q->cursize,
904  q, health);
905  }
906  else
907  {
908  clib_warning ("NULL client registration index %d",
909  regpp - am->vl_clients);
910  vec_add1 (confused_indices, regpp - am->vl_clients);
911  }
912  }));
913  /* *INDENT-ON* */
914 
915  /* This should "never happen," but if it does, fix it... */
916  if (PREDICT_FALSE (vec_len (confused_indices) > 0))
917  {
918  int i;
919  for (i = 0; i < vec_len (confused_indices); i++)
920  {
921  pool_put_index (am->vl_clients, confused_indices[i]);
922  }
923  }
924  vec_free (confused_indices);
925 
926  if (am->missing_clients)
927  vlib_cli_output (vm, "%u messages with missing clients",
928  am->missing_clients);
929 socket_clients:
930  dump_socket_clients (vm, am);
931 
932  return 0;
933 }
934 
935 static clib_error_t *
937  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
938 {
939  api_main_t *am = &api_main;
940 
941  // check if rx_trace and tx_trace are not null pointers
942 
943  if (am->rx_trace == 0)
944  {
945  vlib_cli_output (vm, "RX Trace disabled\n");
946  }
947  else
948  {
949  if (am->rx_trace->enabled == 0)
950  vlib_cli_output (vm, "RX Trace disabled\n");
951  else
952  vlib_cli_output (vm, "RX Trace enabled\n");
953  }
954 
955  if (am->tx_trace == 0)
956  {
957  vlib_cli_output (vm, "TX Trace disabled\n");
958  }
959  else
960  {
961  if (am->tx_trace->enabled == 0)
962  vlib_cli_output (vm, "TX Trace disabled\n");
963  else
964  vlib_cli_output (vm, "TX Trace enabled\n");
965  }
966 
967  return 0;
968 }
969 
970 /* *INDENT-OFF* */
972  .path = "show api",
973  .short_help = "Show API information",
974 };
975 /* *INDENT-ON* */
976 
977 /* *INDENT-OFF* */
979  .path = "show api ring-stats",
980  .short_help = "Message ring statistics",
981  .function = vl_api_ring_command,
982 };
983 /* *INDENT-ON* */
984 
985 /* *INDENT-OFF* */
987  .path = "show api clients",
988  .short_help = "Client information",
989  .function = vl_api_client_command,
990 };
991 /* *INDENT-ON* */
992 
993 /* *INDENT-OFF* */
995  .path = "show api status",
996  .short_help = "Show API trace status",
997  .function = vl_api_status_command,
998 };
999 /* *INDENT-ON* */
1000 
1001 static clib_error_t *
1003  unformat_input_t * input,
1004  vlib_cli_command_t * cli_cmd)
1005 {
1006  api_main_t *am = &api_main;
1007  int i;
1008  int verbose = 0;
1009 
1010  if (unformat (input, "verbose"))
1011  verbose = 1;
1012 
1013 
1014  if (verbose == 0)
1015  vlib_cli_output (vm, "%-4s %s", "ID", "Name");
1016  else
1017  vlib_cli_output (vm, "%-4s %-40s %6s %7s", "ID", "Name", "Bounce",
1018  "MP-safe");
1019 
1020  for (i = 1; i < vec_len (am->msg_names); i++)
1021  {
1022  if (verbose == 0)
1023  {
1024  vlib_cli_output (vm, "%-4d %s", i,
1025  am->msg_names[i] ? am->msg_names[i] :
1026  " [no handler]");
1027  }
1028  else
1029  {
1030  vlib_cli_output (vm, "%-4d %-40s %6d %7d", i,
1031  am->msg_names[i] ? am->msg_names[i] :
1032  " [no handler]", am->message_bounce[i],
1033  am->is_mp_safe[i]);
1034  }
1035  }
1036 
1037  return 0;
1038 }
1039 
1040 /* *INDENT-OFF* */
1042  .path = "show api message-table",
1043  .short_help = "Message Table",
1044  .function = vl_api_message_table_command,
1045 };
1046 /* *INDENT-ON* */
1047 
1048 static clib_error_t *
1050  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
1051 {
1052  u32 nitems = 1024;
1054  api_main_t *am = &api_main;
1055 
1056  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1057  {
1058  if (unformat (input, "rx nitems %u", &nitems) || unformat (input, "rx"))
1059  goto configure;
1060  else if (unformat (input, "tx nitems %u", &nitems)
1061  || unformat (input, "tx"))
1062  {
1063  which = VL_API_TRACE_RX;
1064  goto configure;
1065  }
1066  else if (unformat (input, "on rx"))
1067  {
1069  }
1070  else if (unformat (input, "on tx"))
1071  {
1073  }
1074  else if (unformat (input, "on"))
1075  {
1077  }
1078  else if (unformat (input, "off"))
1079  {
1082  }
1083  else if (unformat (input, "free"))
1084  {
1089  }
1090  else if (unformat (input, "debug on"))
1091  {
1092  am->msg_print_flag = 1;
1093  }
1094  else if (unformat (input, "debug off"))
1095  {
1096  am->msg_print_flag = 0;
1097  }
1098  else
1099  return clib_error_return (0, "unknown input `%U'",
1100  format_unformat_error, input);
1101  }
1102  return 0;
1103 
1104 configure:
1105  if (vl_msg_api_trace_configure (am, which, nitems))
1106  {
1107  vlib_cli_output (vm, "warning: trace configure error (%d, %d)",
1108  which, nitems);
1109  }
1110 
1111  return 0;
1112 }
1113 
1114 /* *INDENT-OFF* */
1116  .path = "set api-trace",
1117  .short_help = "API trace",
1118  .function = vl_api_trace_command,
1119 };
1120 /* *INDENT-ON* */
1121 
1122 clib_error_t *
1124 {
1125  api_main_t *am = &api_main;
1126  svm_map_region_args_t _a, *a = &_a;
1127 
1128  memset (a, 0, sizeof (*a));
1129  a->root_path = am->root_path;
1131  a->baseva = (am->global_baseva != 0) ?
1133  a->size = (am->global_size != 0) ? am->global_size : SVM_GLOBAL_REGION_SIZE;
1134  a->flags = SVM_FLAGS_NODATA;
1135  a->uid = am->api_uid;
1136  a->gid = am->api_gid;
1137  a->pvt_heap_size =
1138  (am->global_pvt_heap_size !=
1140 
1142  return 0;
1143 }
1144 
1146 
1147 void
1149 {
1150  api_main_t *am = &api_main;
1151 
1152  am->region_name = name;
1153 }
1154 
1155 static int
1157 {
1158  int len0, len1, clen;
1159 
1160  len0 = vec_len (a0->name);
1161  len1 = vec_len (a1->name);
1162  clen = len0 < len1 ? len0 : len1;
1163  return (strncmp ((char *) a0->name, (char *) a1->name, clen));
1164 }
1165 
1166 static u8 *
1167 format_api_msg_range (u8 * s, va_list * args)
1168 {
1169  vl_api_msg_range_t *rp = va_arg (*args, vl_api_msg_range_t *);
1170 
1171  if (rp == 0)
1172  s = format (s, "%-20s%9s%9s", "Name", "First-ID", "Last-ID");
1173  else
1174  s = format (s, "%-20s%9d%9d", rp->name, rp->first_msg_id,
1175  rp->last_msg_id);
1176 
1177  return s;
1178 }
1179 
1180 static clib_error_t *
1182  unformat_input_t * input,
1183  vlib_cli_command_t * cli_cmd)
1184 {
1185  api_main_t *am = &api_main;
1186  vl_api_msg_range_t *rp = 0;
1187  int i;
1188 
1189  if (vec_len (am->msg_ranges) == 0)
1190  {
1191  vlib_cli_output (vm, "No plugin API message ranges configured...");
1192  return 0;
1193  }
1194 
1195  rp = vec_dup (am->msg_ranges);
1196 
1198 
1199  vlib_cli_output (vm, "Plugin API message ID ranges...\n");
1200  vlib_cli_output (vm, "%U", format_api_msg_range, 0 /* header */ );
1201 
1202  for (i = 0; i < vec_len (rp); i++)
1203  vlib_cli_output (vm, "%U", format_api_msg_range, rp + i);
1204 
1205  return 0;
1206 }
1207 
1208 /* *INDENT-OFF* */
1210  .path = "show api plugin",
1211  .short_help = "show api plugin",
1212  .function = vl_api_show_plugin_command,
1213 };
1214 /* *INDENT-ON* */
1215 
1216 static void
1218 {
1219  vl_api_rpc_reply_t *rmp;
1220  int (*fp) (void *);
1221  i32 rv = 0;
1222  vlib_main_t *vm = vlib_get_main ();
1223 
1224  if (mp->function == 0)
1225  {
1226  rv = -1;
1227  clib_warning ("rpc NULL function pointer");
1228  }
1229 
1230  else
1231  {
1232  if (mp->need_barrier_sync)
1234 
1235  fp = uword_to_pointer (mp->function, int (*)(void *));
1236  rv = fp (mp->data);
1237 
1238  if (mp->need_barrier_sync)
1240  }
1241 
1242  if (mp->send_reply)
1243  {
1246  if (q)
1247  {
1248  rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp));
1249  rmp->_vl_msg_id = ntohs (VL_API_RPC_REPLY);
1250  rmp->context = mp->context;
1251  rmp->retval = rv;
1252  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1253  }
1254  }
1255  if (mp->multicast)
1256  {
1257  clib_warning ("multicast not yet implemented...");
1258  }
1259 }
1260 
1261 static void
1263 {
1264  clib_warning ("unimplemented");
1265 }
1266 
1267 void
1268 vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length)
1269 {
1270  vl_api_rpc_call_t *mp;
1271  api_main_t *am = &api_main;
1274 
1275  /* Main thread: call the function directly */
1276  if (os_get_cpu_number () == 0)
1277  {
1278  vlib_main_t *vm = vlib_get_main ();
1279  void (*call_fp) (void *);
1280 
1282 
1283  call_fp = fp;
1284  call_fp (data);
1285 
1287  return;
1288  }
1289 
1290  /* Any other thread, actually do an RPC call... */
1291  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) + data_length);
1292 
1293  memset (mp, 0, sizeof (*mp));
1294  clib_memcpy (mp->data, data, data_length);
1295  mp->_vl_msg_id = ntohs (VL_API_RPC_CALL);
1296  mp->function = pointer_to_uword (fp);
1297  mp->need_barrier_sync = 1;
1298 
1299  /*
1300  * Use the "normal" control-plane mechanism for the main thread.
1301  * Well, almost. if the main input queue is full, we cannot
1302  * block. Otherwise, we can expect a barrier sync timeout.
1303  */
1304  q = shmem_hdr->vl_input_queue;
1305 
1306  while (pthread_mutex_trylock (&q->mutex))
1308 
1310  {
1311  pthread_mutex_unlock (&q->mutex);
1313  while (pthread_mutex_trylock (&q->mutex))
1315  }
1316 
1317  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
1318 
1319  pthread_mutex_unlock (&q->mutex);
1320 }
1321 
1322 #define foreach_rpc_api_msg \
1323 _(RPC_CALL,rpc_call) \
1324 _(RPC_REPLY,rpc_reply)
1325 
1326 static clib_error_t *
1328 {
1329 #define _(N,n) \
1330  vl_msg_api_set_handlers(VL_API_##N, #n, \
1331  vl_api_##n##_t_handler, \
1332  vl_noop_handler, \
1333  vl_noop_handler, \
1334  vl_api_##n##_t_print, \
1335  sizeof(vl_api_##n##_t), 0 /* do not trace */);
1337 #undef _
1338  return 0;
1339 }
1340 
1342 
1343 /*
1344  * fd.io coding-style-patch-verification: ON
1345  *
1346  * Local Variables:
1347  * eval: (c-set-style "gnu")
1348  * End:
1349  */
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:396
#define TRACE_VLIB_MEMORY_QUEUE
Definition: memory_vlib.c:39
u64 pvt_heap_size
Definition: svm.h:76
#define vl_print(handle,...)
Definition: memory_vlib.c:48
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:225
char * region_name
Definition: api.h:189
static void svm_pop_heap(void *oldheap)
Definition: svm.h:190
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
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:684
a
Definition: bitmap.h:516
int unix_shared_memory_queue_is_full(unix_shared_memory_queue_t *q)
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: memory_vlib.c:1115
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static clib_error_t * setup_memclnt_exit(vlib_main_t *vm)
Definition: memory_vlib.c:806
u32 application_restarts
Definition: api.h:84
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:797
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
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:871
u8 * message_bounce
Definition: api.h:123
u16 nitems
Definition: api.h:45
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
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:1002
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:1181
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
int api_uid
Definition: api.h:150
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:679
void vl_msg_api_send(vl_api_registration_t *rp, u8 *elem)
Definition: memory_vlib.c:91
#define pool_is_free(P, E)
Use free bitmap to query whether given element is free.
Definition: pool.h:203
#define clib_error_report(e)
Definition: error.h:125
void vl_api_get_first_msg_id_t_handler(vl_api_get_first_msg_id_t *mp)
Definition: memory_vlib.c:296
#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:152
int vl_api_memclnt_delete_callback(u32 client_index)
Definition: memory_vlib.c:216
void vl_enable_disable_memory_api(vlib_main_t *vm, int enable)
Definition: memory_vlib.c:738
static vlib_cli_command_t cli_show_api_clients_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_clients_command)
Definition: memory_vlib.c:986
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:559
static f64 vlib_last_vector_length_per_node(vlib_main_t *vm)
Definition: main.h:273
static void vlib_worker_thread_barrier_check(void)
Definition: threads.h:214
api_main_t api_main
Definition: api_shared.c:39
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:1148
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
_vlib_init_function_list_elt_t * api_init_function_registrations
Definition: main.h:167
static vlib_cli_command_t cli_show_api_status_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_status_command)
Definition: memory_vlib.c:994
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
static int range_compare(vl_api_msg_range_t *a0, vl_api_msg_range_t *a1)
Definition: memory_vlib.c:1156
vl_api_trace_t * rx_trace
Definition: api.h:128
#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:527
u32 ring_misses
Definition: api.h:126
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:136
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:1041
int i32
Definition: types.h:81
char * name
Definition: svm.h:73
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.
svm_region_t * vlib_rp
Definition: api.h:133
#define clib_warning(format, args...)
Definition: error.h:59
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Definition: api.h:135
static void * vl_api_memclnt_create_t_print(vl_api_memclnt_create_t *a, void *handle)
Definition: memory_vlib.c:54
void vl_socket_api_send(vl_api_registration_t *rp, u8 *elem)
Definition: memory_vlib.c:82
#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:709
static void vlib_set_queue_signal_callback(vlib_main_t *vm, void(*fp)(vlib_main_t *))
Definition: main.h:309
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:97
vl_shmem_hdr_t * shmem_hdr
int vl_msg_api_trace_free(api_main_t *am, vl_api_trace_which_t which)
Definition: api_shared.c:172
vl_registration_type_t registration_type
Definition: api.h:40
u16 last_msg_id
Definition: api.h:112
#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:369
#define foreach_rpc_api_msg
Definition: memory_vlib.c:1322
static vlib_node_registration_t memclnt_node
(constructor) VLIB_REGISTER_NODE (memclnt_node)
Definition: memory_vlib.c:700
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:816
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:931
static vlib_cli_command_t cli_show_api_ring_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_ring_command)
Definition: memory_vlib.c:978
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:334
#define ELOG_DATA(em, f)
Definition: elog.h:392
#define PREDICT_FALSE(x)
Definition: clib.h:97
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:1217
static u32 vl_msg_api_handle_get_index(u32 index)
Definition: api.h:103
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
#define foreach_vlib_api_msg
Definition: memory_vlib.c:335
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:473
volatile u32 queue_signal_pending
Definition: main.h:172
#define uword_to_pointer(u, type)
Definition: types.h:136
u64 global_size
Definition: api.h:158
u8 enabled
Definition: api.h:82
int vl_msg_api_trace_onoff(api_main_t *am, vl_api_trace_which_t which, int onoff)
Definition: api_shared.c:130
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
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: memory_vlib.c:1268
void serialize_open_vector(serialize_main_t *m, u8 *vector)
Definition: serialize.c:908
u64 global_baseva
Definition: api.h:155
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:53
vl_api_msg_range_t * msg_ranges
Definition: api.h:147
#define clib_memcpy(a, b, c)
Definition: string.h:69
#define foreach_histogram_bucket
Definition: memory_vlib.c:374
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:1163
#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:971
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:1049
#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:570
histogram_index_t
Definition: memory_vlib.c:380
vl_api_trace_t * tx_trace
Definition: api.h:129
static uword api_rx_from_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: memory_vlib.c:747
static vlib_cli_command_t cli_show_api_plugin_command
(constructor) VLIB_CLI_COMMAND (cli_show_api_plugin_command)
Definition: memory_vlib.c:1209
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:228
#define ASSERT(truth)
static uword hash_elts(void *v)
Definition: hash.h:117
#define VL_API_EPOCH_MASK
Definition: api.h:93
unsigned int u32
Definition: types.h:88
clib_error_t * vlibmemory_init(vlib_main_t *vm)
Definition: memory_vlib.c:1123
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u16 size
Definition: api.h:44
static u64 vector_rate_histogram[SLEEP_N_BUCKETS]
Definition: memory_vlib.c:388
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
static uword memclnt_process(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f)
Definition: memory_vlib.c:393
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
VLIB_API_INIT_FUNCTION(rpc_api_hookup)
u8 * vl_api_serialize_message_table(api_main_t *am, u8 *vector)
Definition: memory_vlib.c:104
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:117
static void clib_mem_free(void *p)
Definition: mem.h:176
u32 misses
Definition: api.h:47
u8 * serialized_message_table_in_shmem
Definition: api.h:138
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:866
u64 global_pvt_heap_size
Definition: api.h:164
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:122
#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:1167
u64 uword
Definition: types.h:112
static clib_error_t * rpc_api_hookup(vlib_main_t *vm)
Definition: memory_vlib.c:1327
char * root_path
Definition: api.h:190
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:936
static void vl_api_rpc_reply_t_handler(vl_api_rpc_reply_t *mp)
Definition: memory_vlib.c:1262
u32 missing_clients
Definition: api.h:127
#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:131
#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:920
int vl_map_shmem(char *region_name, int is_vlib)
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:636
volatile u32 api_queue_nonempty
Definition: main.h:173
#define hash_get_mem(h, key)
Definition: hash.h:268
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1195
u8 * is_mp_safe
Definition: api.h:124
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u8 data[0]
Packet data.
Definition: buffer.h:158
int msg_print_flag
Definition: api.h:130
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:344
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:65
void * vl_msg_api_alloc_as_if_client(int nbytes)
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
static u32 vl_msg_api_handle_get_epoch(u32 index)
Definition: api.h:97
uword * msg_index_by_name_and_crc
Definition: api.h:187
int vl_msg_api_trace_configure(api_main_t *am, vl_api_trace_which_t which, u32 nitems)
Definition: api_shared.c:340
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
u32 hits
Definition: api.h:46
uword * msg_range_by_name
Definition: api.h:144
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
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:109
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
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