FD.io VPP  v16.12-rc0-308-g931be3a
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 static clib_error_t *
912  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
913 {
914  api_main_t *am = &api_main;
915 
916  // check if rx_trace and tx_trace are not null pointers
917 
918  if (am->rx_trace == 0)
919  {
920  vlib_cli_output (vm, "RX Trace disabled\n");
921  }
922  else
923  {
924  if (am->rx_trace->enabled == 0)
925  vlib_cli_output (vm, "RX Trace disabled\n");
926  else
927  vlib_cli_output (vm, "RX Trace enabled\n");
928  }
929 
930  if (am->tx_trace == 0)
931  {
932  vlib_cli_output (vm, "TX Trace disabled\n");
933  }
934  else
935  {
936  if (am->tx_trace->enabled == 0)
937  vlib_cli_output (vm, "TX Trace disabled\n");
938  else
939  vlib_cli_output (vm, "TX Trace enabled\n");
940  }
941 
942  return 0;
943 }
944 
945 /* *INDENT-OFF* */
947  .path = "show api",
948  .short_help = "Show API information",
949 };
950 /* *INDENT-ON* */
951 
952 /* *INDENT-OFF* */
954  .path = "show api ring-stats",
955  .short_help = "Message ring statistics",
956  .function = vl_api_ring_command,
957 };
958 /* *INDENT-ON* */
959 
960 /* *INDENT-OFF* */
962  .path = "show api clients",
963  .short_help = "Client information",
964  .function = vl_api_client_command,
965 };
966 /* *INDENT-ON* */
967 
968 /* *INDENT-OFF* */
970  .path = "show api status",
971  .short_help = "Show API trace status",
972  .function = vl_api_status_command,
973 };
974 /* *INDENT-ON* */
975 
976 static clib_error_t *
978  unformat_input_t * input,
979  vlib_cli_command_t * cli_cmd)
980 {
981  api_main_t *am = &api_main;
982  int i;
983  int verbose = 0;
984 
985  if (unformat (input, "verbose"))
986  verbose = 1;
987 
988 
989  if (verbose == 0)
990  vlib_cli_output (vm, "%-4s %s", "ID", "Name");
991  else
992  vlib_cli_output (vm, "%-4s %-40s %6s %7s", "ID", "Name", "Bounce",
993  "MP-safe");
994 
995  for (i = 1; i < vec_len (am->msg_names); i++)
996  {
997  if (verbose == 0)
998  {
999  vlib_cli_output (vm, "%-4d %s", i,
1000  am->msg_names[i] ? am->msg_names[i] :
1001  " [no handler]");
1002  }
1003  else
1004  {
1005  vlib_cli_output (vm, "%-4d %-40s %6d %7d", i,
1006  am->msg_names[i] ? am->msg_names[i] :
1007  " [no handler]", am->message_bounce[i],
1008  am->is_mp_safe[i]);
1009  }
1010  }
1011 
1012  return 0;
1013 }
1014 
1015 /* *INDENT-OFF* */
1017  .path = "show api message-table",
1018  .short_help = "Message Table",
1019  .function = vl_api_message_table_command,
1020 };
1021 /* *INDENT-ON* */
1022 
1023 void
1025  u8 * filename)
1026 {
1027  FILE *fp;
1028  static vl_api_trace_t *tp = 0;
1029  int endian_swap = 0;
1030  u32 i;
1031  u16 msg_id;
1032  static u8 *msg_buf = 0;
1033  void (*endian_fp) (void *);
1034  u8 *(*print_fp) (void *, void *);
1035  int size;
1036  api_main_t *am = &api_main;
1037 
1038  /*
1039  * On-demand: allocate enough space for the largest message
1040  */
1041  if (msg_buf == 0)
1042  {
1043  vec_validate (tp, 0);
1044  int max_size = 0;
1045  for (i = 0; i < vec_len (am->api_trace_cfg); i++)
1046  {
1047  if (am->api_trace_cfg[i].size > max_size)
1048  max_size = am->api_trace_cfg[i].size;
1049  }
1050  /* round size to a multiple of the cache-line size */
1051  max_size = (max_size + (CLIB_CACHE_LINE_BYTES - 1)) &
1052  (~(CLIB_CACHE_LINE_BYTES - 1));
1053  vec_validate (msg_buf, max_size - 1);
1054  }
1055 
1056  fp = fopen ((char *) filename, "r");
1057 
1058  if (fp == NULL)
1059  {
1060  vlib_cli_output (vm, "Couldn't open %s\n", filename);
1061  return;
1062  }
1063 
1064  /* first, fish the header record from the file */
1065 
1066  if (fread (tp, sizeof (*tp), 1, fp) != 1)
1067  {
1068  fclose (fp);
1069  vlib_cli_output (vm, "Header read error\n");
1070  return;
1071  }
1072 
1073  /* Endian swap required? */
1074  if (clib_arch_is_big_endian != tp->endian)
1075  {
1076  endian_swap = 1;
1077  }
1078 
1079  for (i = 0; i <= last; i++)
1080  {
1081  /* First 2 bytes are the message type */
1082  if (fread (&msg_id, sizeof (u16), 1, fp) != 1)
1083  {
1084  break;
1085  }
1086  msg_id = ntohs (msg_id);
1087 
1088  if (fseek (fp, -2, SEEK_CUR) < 0)
1089  {
1090  vlib_cli_output (vm, "fseek failed, %s", strerror (errno));
1091  fclose (fp);
1092  return;
1093  }
1094 
1095  /* Mild sanity check */
1096  if (msg_id >= vec_len (am->msg_handlers))
1097  {
1098  fclose (fp);
1099  vlib_cli_output (vm, "msg_id %d out of bounds\n", msg_id);
1100  return;
1101  }
1102 
1103  size = am->api_trace_cfg[msg_id].size;
1104 
1105  if (fread (msg_buf, size, 1, fp) != 1)
1106  {
1107  fclose (fp);
1108  vlib_cli_output (vm, "read error on %s\n", filename);
1109  return;
1110  }
1111 
1112  if (i < first)
1113  continue;
1114 
1115  if (endian_swap)
1116  {
1117  endian_fp = am->msg_endian_handlers[msg_id];
1118  (*endian_fp) (msg_buf);
1119  }
1120 
1121  vlib_cli_output (vm, "[%d]: %s\n", i, am->msg_names[msg_id]);
1122 
1123  print_fp = (void *) am->msg_print_handlers[msg_id];
1124  (*print_fp) (msg_buf, vm);
1125  vlib_cli_output (vm, "-------------\n");
1126  }
1127  fclose (fp);
1128 }
1129 
1130 static clib_error_t *
1132  unformat_input_t * input, vlib_cli_command_t * cli_cmd)
1133 {
1134  u32 nitems = 1024;
1136  u8 *filename;
1137  u32 first = 0;
1138  u32 last = ~0;
1139  api_main_t *am = &api_main;
1140 
1141  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1142  {
1143  if (unformat (input, "rx nitems %u", &nitems) || unformat (input, "rx"))
1144  goto configure;
1145  else if (unformat (input, "tx nitems %u", &nitems)
1146  || unformat (input, "tx"))
1147  {
1148  which = VL_API_TRACE_RX;
1149  goto configure;
1150  }
1151  else if (unformat (input, "on rx"))
1152  {
1154  }
1155  else if (unformat (input, "on tx"))
1156  {
1158  }
1159  else if (unformat (input, "on"))
1160  {
1162  }
1163  else if (unformat (input, "off"))
1164  {
1167  }
1168  else if (unformat (input, "free"))
1169  {
1174  }
1175  else if (unformat (input, "print %s from %d to %d", &filename,
1176  &first, &last)
1177  || unformat (input, "print %s", &filename))
1178  {
1179  goto print;
1180  }
1181  else if (unformat (input, "debug on"))
1182  {
1183  am->msg_print_flag = 1;
1184  }
1185  else if (unformat (input, "debug off"))
1186  {
1187  am->msg_print_flag = 0;
1188  }
1189  else
1190  return clib_error_return (0, "unknown input `%U'",
1191  format_unformat_error, input);
1192  }
1193  return 0;
1194 
1195 print:
1196  vl_api_trace_print_file_cmd (vm, first, last, filename);
1197  goto out;
1198 
1199 configure:
1200  if (vl_msg_api_trace_configure (am, which, nitems))
1201  {
1202  vlib_cli_output (vm, "warning: trace configure error (%d, %d)",
1203  which, nitems);
1204  }
1205 
1206 out:
1207  return 0;
1208 }
1209 
1210 /* *INDENT-OFF* */
1212  .path = "set api-trace",
1213  .short_help = "API trace",
1214  .function = vl_api_trace_command,
1215 };
1216 /* *INDENT-ON* */
1217 
1218 clib_error_t *
1220 {
1221  api_main_t *am = &api_main;
1222  svm_map_region_args_t _a, *a = &_a;
1223 
1224  memset (a, 0, sizeof (*a));
1225  a->root_path = am->root_path;
1227  a->baseva = (am->global_baseva != 0) ?
1229  a->size = (am->global_size != 0) ? am->global_size : SVM_GLOBAL_REGION_SIZE;
1230  a->flags = SVM_FLAGS_NODATA;
1231  a->uid = am->api_uid;
1232  a->gid = am->api_gid;
1233  a->pvt_heap_size =
1234  (am->global_pvt_heap_size !=
1236 
1238  return 0;
1239 }
1240 
1242 
1243 void
1245 {
1246  api_main_t *am = &api_main;
1247 
1248  am->region_name = name;
1249 }
1250 
1251 static int
1253 {
1254  int len0, len1, clen;
1255 
1256  len0 = vec_len (a0->name);
1257  len1 = vec_len (a1->name);
1258  clen = len0 < len1 ? len0 : len1;
1259  return (strncmp ((char *) a0->name, (char *) a1->name, clen));
1260 }
1261 
1262 static u8 *
1263 format_api_msg_range (u8 * s, va_list * args)
1264 {
1265  vl_api_msg_range_t *rp = va_arg (*args, vl_api_msg_range_t *);
1266 
1267  if (rp == 0)
1268  s = format (s, "%-20s%9s%9s", "Name", "First-ID", "Last-ID");
1269  else
1270  s = format (s, "%-20s%9d%9d", rp->name, rp->first_msg_id,
1271  rp->last_msg_id);
1272 
1273  return s;
1274 }
1275 
1276 static clib_error_t *
1278  unformat_input_t * input,
1279  vlib_cli_command_t * cli_cmd)
1280 {
1281  api_main_t *am = &api_main;
1282  vl_api_msg_range_t *rp = 0;
1283  int i;
1284 
1285  if (vec_len (am->msg_ranges) == 0)
1286  {
1287  vlib_cli_output (vm, "No plugin API message ranges configured...");
1288  return 0;
1289  }
1290 
1291  rp = vec_dup (am->msg_ranges);
1292 
1294 
1295  vlib_cli_output (vm, "Plugin API message ID ranges...\n");
1296  vlib_cli_output (vm, "%U", format_api_msg_range, 0 /* header */ );
1297 
1298  for (i = 0; i < vec_len (rp); i++)
1299  vlib_cli_output (vm, "%U", format_api_msg_range, rp + i);
1300 
1301  return 0;
1302 }
1303 
1304 /* *INDENT-OFF* */
1306  .path = "show api plugin",
1307  .short_help = "show api plugin",
1308  .function = vl_api_show_plugin_command,
1309 };
1310 /* *INDENT-ON* */
1311 
1312 static void
1314 {
1315  vl_api_rpc_reply_t *rmp;
1316  int (*fp) (void *);
1317  i32 rv = 0;
1318  vlib_main_t *vm = vlib_get_main ();
1319 
1320  if (mp->function == 0)
1321  {
1322  rv = -1;
1323  clib_warning ("rpc NULL function pointer");
1324  }
1325 
1326  else
1327  {
1328  if (mp->need_barrier_sync)
1330 
1331  fp = uword_to_pointer (mp->function, int (*)(void *));
1332  rv = fp (mp->data);
1333 
1334  if (mp->need_barrier_sync)
1336  }
1337 
1338  if (mp->send_reply)
1339  {
1342  if (q)
1343  {
1344  rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp));
1345  rmp->_vl_msg_id = ntohs (VL_API_RPC_REPLY);
1346  rmp->context = mp->context;
1347  rmp->retval = rv;
1348  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1349  }
1350  }
1351  if (mp->multicast)
1352  {
1353  clib_warning ("multicast not yet implemented...");
1354  }
1355 }
1356 
1357 static void
1359 {
1360  clib_warning ("unimplemented");
1361 }
1362 
1363 void
1364 vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length)
1365 {
1366  vl_api_rpc_call_t *mp;
1367  api_main_t *am = &api_main;
1370 
1371  /* Main thread: call the function directly */
1372  if (os_get_cpu_number () == 0)
1373  {
1374  vlib_main_t *vm = vlib_get_main ();
1375  void (*call_fp) (void *);
1376 
1378 
1379  call_fp = fp;
1380  call_fp (data);
1381 
1383  return;
1384  }
1385 
1386  /* Any other thread, actually do an RPC call... */
1387  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) + data_length);
1388 
1389  memset (mp, 0, sizeof (*mp));
1390  clib_memcpy (mp->data, data, data_length);
1391  mp->_vl_msg_id = ntohs (VL_API_RPC_CALL);
1392  mp->function = pointer_to_uword (fp);
1393  mp->need_barrier_sync = 1;
1394 
1395  /*
1396  * Use the "normal" control-plane mechanism for the main thread.
1397  * Well, almost. if the main input queue is full, we cannot
1398  * block. Otherwise, we can expect a barrier sync timeout.
1399  */
1400  q = shmem_hdr->vl_input_queue;
1401 
1402  while (pthread_mutex_trylock (&q->mutex))
1404 
1406  {
1407  pthread_mutex_unlock (&q->mutex);
1409  while (pthread_mutex_trylock (&q->mutex))
1411  }
1412 
1413  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
1414 
1415  pthread_mutex_unlock (&q->mutex);
1416 }
1417 
1418 #define foreach_rpc_api_msg \
1419 _(RPC_CALL,rpc_call) \
1420 _(RPC_REPLY,rpc_reply)
1421 
1422 static clib_error_t *
1424 {
1425 #define _(N,n) \
1426  vl_msg_api_set_handlers(VL_API_##N, #n, \
1427  vl_api_##n##_t_handler, \
1428  vl_noop_handler, \
1429  vl_noop_handler, \
1430  vl_api_##n##_t_print, \
1431  sizeof(vl_api_##n##_t), 0 /* do not trace */);
1433 #undef _
1434  return 0;
1435 }
1436 
1438 
1439 /*
1440  * fd.io coding-style-patch-verification: ON
1441  *
1442  * Local Variables:
1443  * eval: (c-set-style "gnu")
1444  * End:
1445  */
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: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:1211
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:977
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:1277
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:961
#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:206
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:432
void vl_set_memory_region_name(char *name)
Definition: memory_vlib.c:1244
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:969
#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:1252
vl_api_trace_t * rx_trace
Definition: api.h:125
#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:123
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: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:1016
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:97
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:1418
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:931
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:953
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:1313
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
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: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:1364
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:64
#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:1182
#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:946
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:1131
#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:541
histogram_index_t
Definition: memory_vlib.c:355
vl_api_trace_t * tx_trace
Definition: api.h:126
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:1305
#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:1219
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
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:76
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
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: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:146
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:109
u32 restart_reclaims
Definition: api.h:87
static u8 * format_api_msg_range(u8 *s, va_list *args)
Definition: memory_vlib.c:1263
u64 uword
Definition: types.h:112
static clib_error_t * rpc_api_hookup(vlib_main_t *vm)
Definition: memory_vlib.c:1423
char * root_path
Definition: api.h:182
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:911
static void vl_api_rpc_reply_t_handler(vl_api_rpc_reply_t *mp)
Definition: memory_vlib.c:1358
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
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: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: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:1214
u8 * is_mp_safe
Definition: api.h:121
#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:154
int msg_print_flag
Definition: api.h:127
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: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:1024
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109