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