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