FD.io VPP  v18.01.2-1-g9b554f3
Vector Packet Processing
memory_shared.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * memclnt_shared.c - API message handling, common code for both clients
4  * and the vlib process itself.
5  *
6  *
7  * Copyright (c) 2009 Cisco and/or its affiliates.
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at:
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *------------------------------------------------------------------
20  */
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <signal.h>
28 #include <vppinfra/format.h>
29 #include <vppinfra/byte_order.h>
30 #include <vppinfra/error.h>
31 #include <vlib/vlib.h>
32 #include <vlib/unix/unix.h>
33 #include <vlibmemory/api.h>
35 
37 
38 #define vl_typedefs
40 #undef vl_typedefs
41 
43 
44 #define DEBUG_MESSAGE_BUFFER_OVERRUN 0
45 
46 static inline void *
47 vl_msg_api_alloc_internal (int nbytes, int pool, int may_return_null)
48 {
49  int i;
50  msgbuf_t *rv;
51  ring_alloc_t *ap;
53  void *oldheap;
55  api_main_t *am = &api_main;
56 
57  shmem_hdr = am->shmem_hdr;
58 
59 #if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
60  nbytes += 4;
61 #endif
62 
63  ASSERT (pool == 0 || vlib_get_thread_index () == 0);
64 
65  if (shmem_hdr == 0)
66  {
67  clib_warning ("shared memory header NULL");
68  return 0;
69  }
70 
71  /* account for the msgbuf_t header */
72  nbytes += sizeof (msgbuf_t);
73 
74  if (shmem_hdr->vl_rings == 0)
75  {
76  clib_warning ("vl_rings NULL");
77  ASSERT (0);
78  abort ();
79  }
80 
81  if (shmem_hdr->client_rings == 0)
82  {
83  clib_warning ("client_rings NULL");
84  ASSERT (0);
85  abort ();
86  }
87 
88  ap = pool ? shmem_hdr->vl_rings : shmem_hdr->client_rings;
89  for (i = 0; i < vec_len (ap); i++)
90  {
91  /* Too big? */
92  if (nbytes > ap[i].size)
93  {
94  continue;
95  }
96 
97  q = ap[i].rp;
98  if (pool == 0)
99  {
100  pthread_mutex_lock (&q->mutex);
101  }
102  rv = (msgbuf_t *) (&q->data[0] + q->head * q->elsize);
103  /*
104  * Is this item still in use?
105  */
106  if (rv->q)
107  {
108  u32 now = (u32) time (0);
109 
110  if (PREDICT_TRUE (rv->gc_mark_timestamp == 0))
111  rv->gc_mark_timestamp = now;
112  else
113  {
114  if (now - rv->gc_mark_timestamp > 10)
115  {
116  if (CLIB_DEBUG > 0)
117  {
118  u16 *msg_idp, msg_id;
120  ("garbage collect pool %d ring %d index %d", pool, i,
121  q->head);
122  msg_idp = (u16 *) (rv->data);
123  msg_id = clib_net_to_host_u16 (*msg_idp);
124  if (msg_id < vec_len (api_main.msg_names))
125  clib_warning ("msg id %d name %s", (u32) msg_id,
126  api_main.msg_names[msg_id]);
127  }
128  shmem_hdr->garbage_collects++;
129  goto collected;
130  }
131  }
132 
133 
134  /* yes, loser; try next larger pool */
135  ap[i].misses++;
136  if (pool == 0)
137  pthread_mutex_unlock (&q->mutex);
138  continue;
139  }
140  collected:
141 
142  /* OK, we have a winner */
143  ap[i].hits++;
144  /*
145  * Remember the source queue, although we
146  * don't need to know the queue to free the item.
147  */
148  rv->q = q;
149  rv->gc_mark_timestamp = 0;
150  q->head++;
151  if (q->head == q->maxsize)
152  q->head = 0;
153 
154  if (pool == 0)
155  pthread_mutex_unlock (&q->mutex);
156  goto out;
157  }
158 
159  /*
160  * Request too big, or head element of all size-compatible rings
161  * still in use. Fall back to shared-memory malloc.
162  */
163  am->ring_misses++;
164 
165  pthread_mutex_lock (&am->vlib_rp->mutex);
166  oldheap = svm_push_data_heap (am->vlib_rp);
167  if (may_return_null)
168  {
169  rv = clib_mem_alloc_or_null (nbytes);
170  if (PREDICT_FALSE (rv == 0))
171  {
172  svm_pop_heap (oldheap);
173  pthread_mutex_unlock (&am->vlib_rp->mutex);
174  return 0;
175  }
176  }
177  else
178  rv = clib_mem_alloc (nbytes);
179 
180  rv->q = 0;
181  svm_pop_heap (oldheap);
182  pthread_mutex_unlock (&am->vlib_rp->mutex);
183 
184 out:
185 #if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
186  {
187  nbytes -= 4;
188  u32 *overrun;
189  overrun = (u32 *) (rv->data + nbytes - sizeof (msgbuf_t));
190  *overrun = 0x1badbabe;
191  }
192 #endif
193  rv->data_len = htonl (nbytes - sizeof (msgbuf_t));
194 
195  return (rv->data);
196 }
197 
198 void *
199 vl_msg_api_alloc (int nbytes)
200 {
201  int pool;
202  api_main_t *am = &api_main;
204 
205  /*
206  * Clients use pool-0, vlib proc uses pool 1
207  */
208  pool = (am->our_pid == shmem_hdr->vl_pid);
209  return vl_msg_api_alloc_internal (nbytes, pool, 0 /* may_return_null */ );
210 }
211 
212 void *
214 {
215  int pool;
216  api_main_t *am = &api_main;
218 
219  pool = (am->our_pid == shmem_hdr->vl_pid);
220  return vl_msg_api_alloc_internal (nbytes, pool, 1 /* may_return_null */ );
221 }
222 
223 void *
225 {
226  return vl_msg_api_alloc_internal (nbytes, 0, 0 /* may_return_null */ );
227 }
228 
229 void *
231 {
232  return vl_msg_api_alloc_internal (nbytes, 0, 1 /* may_return_null */ );
233 }
234 
235 void
237 {
238  msgbuf_t *rv;
239  void *oldheap;
240  api_main_t *am = &api_main;
241 
242  rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data));
243 
244  /*
245  * Here's the beauty of the scheme. Only one proc/thread has
246  * control of a given message buffer. To free a buffer, we just clear the
247  * queue field, and leave. No locks, no hits, no errors...
248  */
249  if (rv->q)
250  {
251  rv->q = 0;
252  rv->gc_mark_timestamp = 0;
253 #if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
254  {
255  u32 *overrun;
256  overrun = (u32 *) (rv->data + ntohl (rv->data_len));
257  ASSERT (*overrun == 0x1badbabe);
258  }
259 #endif
260  return;
261  }
262 
263  pthread_mutex_lock (&am->vlib_rp->mutex);
264  oldheap = svm_push_data_heap (am->vlib_rp);
265 
266 #if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
267  {
268  u32 *overrun;
269  overrun = (u32 *) (rv->data + ntohl (rv->data_len));
270  ASSERT (*overrun == 0x1badbabe);
271  }
272 #endif
273 
274  clib_mem_free (rv);
275  svm_pop_heap (oldheap);
276  pthread_mutex_unlock (&am->vlib_rp->mutex);
277 }
278 
279 static void
281 {
282  msgbuf_t *rv;
283  void *oldheap;
284  api_main_t *am = &api_main;
285 
286  rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data));
287  /*
288  * Here's the beauty of the scheme. Only one proc/thread has
289  * control of a given message buffer. To free a buffer, we just clear the
290  * queue field, and leave. No locks, no hits, no errors...
291  */
292  if (rv->q)
293  {
294  rv->q = 0;
295  return;
296  }
297 
298  oldheap = svm_push_data_heap (am->vlib_rp);
299  clib_mem_free (rv);
300  svm_pop_heap (oldheap);
301 }
302 
303 void
304 vl_set_memory_root_path (const char *name)
305 {
306  api_main_t *am = &api_main;
307 
308  am->root_path = name;
309 }
310 
311 void
313 {
314  api_main_t *am = &api_main;
315 
316  am->api_uid = uid;
317 }
318 
319 void
321 {
322  api_main_t *am = &api_main;
323 
324  am->api_gid = gid;
325 }
326 
327 void
329 {
330  api_main_t *am = &api_main;
331 
332  am->global_baseva = baseva;
333 }
334 
335 void
337 {
338  api_main_t *am = &api_main;
339 
340  am->global_size = size;
341 }
342 
343 void
345 {
346  api_main_t *am = &api_main;
347 
348  am->api_size = size;
349 }
350 
351 void
353 {
354  api_main_t *am = &api_main;
355 
357 }
358 
359 void
361 {
362  api_main_t *am = &api_main;
363 
364  am->api_pvt_heap_size = size;
365 }
366 
367 void
368 vl_init_shmem (svm_region_t * vlib_rp, int is_vlib, int is_private_region)
369 {
370  api_main_t *am = &api_main;
372  u32 vlib_input_queue_length;
373  void *oldheap;
374  ASSERT (vlib_rp);
375 
376  /* $$$$ need private region config parameters */
377 
378  oldheap = svm_push_data_heap (vlib_rp);
379 
380  vec_validate (shmem_hdr, 0);
381  shmem_hdr->version = VL_SHM_VERSION;
382 
383  /* vlib main input queue */
384  vlib_input_queue_length = 1024;
385  if (am->vlib_input_queue_length)
386  vlib_input_queue_length = am->vlib_input_queue_length;
387 
388  shmem_hdr->vl_input_queue =
389  unix_shared_memory_queue_init (vlib_input_queue_length, sizeof (uword),
390  getpid (), am->vlib_signal);
391 
392  /* Set up the msg ring allocator */
393 #define _(sz,n) \
394  do { \
395  ring_alloc_t _rp; \
396  _rp.rp = unix_shared_memory_queue_init ((n), (sz), 0, 0); \
397  _rp.size = (sz); \
398  _rp.nitems = n; \
399  _rp.hits = 0; \
400  _rp.misses = 0; \
401  vec_add1(shmem_hdr->vl_rings, _rp); \
402  } while (0);
403 
405 #undef _
406 
407 #define _(sz,n) \
408  do { \
409  ring_alloc_t _rp; \
410  _rp.rp = unix_shared_memory_queue_init ((n), (sz), 0, 0); \
411  _rp.size = (sz); \
412  _rp.nitems = n; \
413  _rp.hits = 0; \
414  _rp.misses = 0; \
415  vec_add1(shmem_hdr->client_rings, _rp); \
416  } while (0);
417 
419 #undef _
420 
421  if (is_private_region == 0)
422  {
423  am->shmem_hdr = shmem_hdr;
424  am->vlib_rp = vlib_rp;
425  am->our_pid = getpid ();
426  if (is_vlib)
427  am->shmem_hdr->vl_pid = am->our_pid;
428  }
429  else
430  shmem_hdr->vl_pid = am->our_pid;
431 
432  svm_pop_heap (oldheap);
433 
434  /*
435  * After absolutely everything that a client might see is set up,
436  * declare the shmem region valid
437  */
438  vlib_rp->user_ctx = shmem_hdr;
439 
440  pthread_mutex_unlock (&vlib_rp->mutex);
441 }
442 
443 
444 int
445 vl_map_shmem (const char *region_name, int is_vlib)
446 {
447  svm_map_region_args_t _a, *a = &_a;
448  svm_region_t *vlib_rp, *root_rp;
449  api_main_t *am = &api_main;
450  int i, rv;
451  struct timespec ts, tsrem;
452  char *vpe_api_region_suffix = "-vpe-api";
453 
454  memset (a, 0, sizeof (*a));
455 
456  if (strstr (region_name, vpe_api_region_suffix))
457  {
458  u8 *root_path = format (0, "%s", region_name);
459  _vec_len (root_path) = (vec_len (root_path) -
460  strlen (vpe_api_region_suffix));
461  vec_terminate_c_string (root_path);
462  a->root_path = (const char *) root_path;
463  am->root_path = (const char *) root_path;
464  }
465 
466  if (is_vlib == 0)
467  {
469  if (rv)
470  return rv;
471  }
472 
473  if (a->root_path != NULL)
474  {
475  a->name = "/vpe-api";
476  }
477  else
478  a->name = region_name;
479  a->size = am->api_size ? am->api_size : (16 << 20);
480  a->flags = SVM_FLAGS_MHEAP;
481  a->uid = am->api_uid;
482  a->gid = am->api_gid;
484 
485  vlib_rp = svm_region_find_or_create (a);
486 
487  if (vlib_rp == 0)
488  return (-2);
489 
490  pthread_mutex_lock (&vlib_rp->mutex);
491  /* Has someone else set up the shared-memory variable table? */
492  if (vlib_rp->user_ctx)
493  {
494  am->shmem_hdr = (void *) vlib_rp->user_ctx;
495  am->our_pid = getpid ();
496  if (is_vlib)
497  {
499  uword old_msg;
500  /*
501  * application restart. Reset cached pids, API message
502  * rings, list of clients; otherwise, various things
503  * fail. (e.g. queue non-empty notification)
504  */
505 
506  /* ghosts keep the region from disappearing properly */
509  q = am->shmem_hdr->vl_input_queue;
510  am->shmem_hdr->vl_pid = getpid ();
511  q->consumer_pid = am->shmem_hdr->vl_pid;
512  /* Drain the input queue, freeing msgs */
513  for (i = 0; i < 10; i++)
514  {
515  if (pthread_mutex_trylock (&q->mutex) == 0)
516  {
517  pthread_mutex_unlock (&q->mutex);
518  goto mutex_ok;
519  }
520  ts.tv_sec = 0;
521  ts.tv_nsec = 10000 * 1000; /* 10 ms */
522  while (nanosleep (&ts, &tsrem) < 0)
523  ts = tsrem;
524  }
525  /* Mutex buggered, "fix" it */
526  memset (&q->mutex, 0, sizeof (q->mutex));
527  clib_warning ("forcibly release main input queue mutex");
528 
529  mutex_ok:
530  am->vlib_rp = vlib_rp;
532  (u8 *) & old_msg,
533  1 /* nowait */ )
534  != -2 /* queue underflow */ )
535  {
536  vl_msg_api_free_nolock ((void *) old_msg);
538  }
539  pthread_mutex_unlock (&vlib_rp->mutex);
540  root_rp = svm_get_root_rp ();
541  ASSERT (root_rp);
542  /* Clean up the root region client list */
543  pthread_mutex_lock (&root_rp->mutex);
545  pthread_mutex_unlock (&root_rp->mutex);
546  }
547  else
548  {
549  pthread_mutex_unlock (&vlib_rp->mutex);
550  }
551  am->vlib_rp = vlib_rp;
552  vec_add1 (am->mapped_shmem_regions, vlib_rp);
553  return 0;
554  }
555  /* Clients simply have to wait... */
556  if (!is_vlib)
557  {
558  pthread_mutex_unlock (&vlib_rp->mutex);
559 
560  /* Wait up to 100 seconds... */
561  for (i = 0; i < 10000; i++)
562  {
563  ts.tv_sec = 0;
564  ts.tv_nsec = 10000 * 1000; /* 10 ms */
565  while (nanosleep (&ts, &tsrem) < 0)
566  ts = tsrem;
567  if (vlib_rp->user_ctx)
568  goto ready;
569  }
570  /* Clean up and leave... */
571  svm_region_unmap (vlib_rp);
572  clib_warning ("region init fail");
573  return (-2);
574 
575  ready:
576  am->shmem_hdr = (void *) vlib_rp->user_ctx;
577  am->our_pid = getpid ();
578  am->vlib_rp = vlib_rp;
579  vec_add1 (am->mapped_shmem_regions, vlib_rp);
580  return 0;
581  }
582 
583  /* Nope, it's our problem... */
584  vl_init_shmem (vlib_rp, 1 /* is vlib */ , 0 /* is_private_region */ );
585 
586  vec_add1 (am->mapped_shmem_regions, vlib_rp);
587  return 0;
588 }
589 
590 void
592 {
593  api_main_t *am = &api_main;
594 
595  vec_add1 (am->mapped_shmem_regions, rp);
596 }
597 
598 void
600 {
601  svm_region_t *rp;
602  int i;
603  api_main_t *am = &api_main;
604 
605  if (!svm_get_root_rp ())
606  return;
607 
608  for (i = 0; i < vec_len (am->mapped_shmem_regions); i++)
609  {
610  rp = am->mapped_shmem_regions[i];
611  svm_region_unmap (rp);
612  }
613 
615  am->shmem_hdr = 0;
616 
617  svm_region_exit ();
618  /* $$$ more careful cleanup, valgrind run... */
619  vec_free (am->msg_handlers);
622 }
623 
624 void
626 {
627  api_main_t *am = &api_main;
628  uword *trace = (uword *) elem;
629 
630  if (am->tx_trace && am->tx_trace->enabled)
631  vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]);
632 
633  (void) unix_shared_memory_queue_add (q, elem, 0 /* nowait */ );
634 }
635 
636 void
638 {
639  api_main_t *am = &api_main;
640  uword *trace = (uword *) elem;
641 
642  if (am->tx_trace && am->tx_trace->enabled)
643  vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]);
644 
645  (void) unix_shared_memory_queue_add_nolock (q, elem);
646 }
647 
648 u32
649 vl_api_get_msg_index (u8 * name_and_crc)
650 {
651  api_main_t *am = &api_main;
652  uword *p;
653 
655  {
656  p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
657  if (p)
658  return p[0];
659  }
660  return ~0;
661 }
662 
663 static inline vl_api_registration_t *
665 {
666  vl_api_registration_t **regpp;
667  vl_api_registration_t *regp;
668  api_main_t *am = &api_main;
669  u32 index;
670 
671  index = vl_msg_api_handle_get_index (handle);
673  != vl_msg_api_handle_get_epoch (handle))
674  {
676  return 0;
677  }
678 
679  regpp = am->vl_clients + index;
680 
681  if (pool_is_free (am->vl_clients, regpp))
682  {
684  return 0;
685  }
686  regp = *regpp;
687  return (regp);
688 }
689 
692 {
693  if (PREDICT_FALSE (socket_main.current_rp != 0))
694  return socket_main.current_rp;
695 
697 }
698 
701 {
702  vl_api_registration_t *regp;
703  api_main_t *am = &api_main;
704 
705  /* Special case: vlib trying to send itself a message */
706  if (index == (u32) ~ 0)
707  return (am->shmem_hdr->vl_input_queue);
708 
710  if (!regp)
711  return 0;
712  return (regp->vl_input_queue);
713 }
714 
715 /*
716  * fd.io coding-style-patch-verification: ON
717  *
718  * Local Variables:
719  * eval: (c-set-style "gnu")
720  * End:
721  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:432
u64 api_pvt_heap_size
size of the api private mheap
Definition: api_common.h:297
svm_region_t * svm_get_root_rp(void)
Definition: svm.c:54
const char * root_path
Definition: svm_common.h:67
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
static void svm_pop_heap(void *oldheap)
Definition: svm.h:94
struct msgbuf_ msgbuf_t
Message header structure.
a
Definition: bitmap.h:516
void vl_set_global_memory_baseva(u64 baseva)
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: memory_vlib.c:1679
int vl_map_shmem(const char *region_name, int is_vlib)
u64 api_size
size of the API region
Definition: api_common.h:291
u32 application_restarts
Definition: api_common.h:79
#define PREDICT_TRUE(x)
Definition: clib.h:106
void vl_set_memory_uid(int uid)
unix_shared_memory_queue_t * vl_input_queue
Definition: api_common.h:68
void vl_set_global_pvt_heap_size(u64 size)
#define NULL
Definition: clib.h:55
void vl_unmap_shmem(void)
u32 gc_mark_timestamp
message garbage collector mark TS
Definition: api_common.h:138
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
Definition: vec.h:990
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:518
int api_uid
uid for the api shared memory region
Definition: api_common.h:279
ring_alloc_t * client_rings
Definition: api_common.h:76
#define foreach_clnt_aring_size
Definition: api_common.h:55
u8 data[0]
actual message begins here
Definition: api_common.h:139
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
#define pool_is_free(P, E)
Use free bitmap to query whether given element is free.
Definition: pool.h:260
static vl_api_registration_t * vl_api_client_index_to_registration_internal(u32 handle)
void * vl_msg_api_alloc(int nbytes)
int api_gid
gid for the api shared memory region
Definition: api_common.h:282
#define VL_API_EPOCH_MASK
Definition: api_common.h:90
void vl_set_global_memory_size(u64 size)
u32 vl_api_get_msg_index(u8 *name_and_crc)
int our_pid
Current process PID.
Definition: api_common.h:248
static void * svm_push_data_heap(svm_region_t *rp)
Definition: svm.h:86
vl_api_registration_t ** vl_clients
vlib/vpp only: vector of client registrations
Definition: api_common.h:264
void * svm_region_find_or_create(svm_map_region_args_t *a)
Definition: svm.c:857
volatile void * user_ctx
Definition: svm_common.h:47
const char * root_path
Chroot path to the shared memory API files.
Definition: api_common.h:330
svm_region_t * vlib_rp
Current binary api segment descriptor.
Definition: api_common.h:251
int unix_shared_memory_queue_add_nolock(unix_shared_memory_queue_t *q, u8 *elem)
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
Definition: api_common.h:261
#define VL_SHM_VERSION
Definition: api_common.h:88
vl_shmem_hdr_t * shmem_hdr
int unix_shared_memory_queue_add(unix_shared_memory_queue_t *q, u8 *elem, int nowait)
void vl_set_memory_root_path(const char *name)
#define SVM_FLAGS_MHEAP
Definition: svm_common.h:27
volatile int vl_pid
Definition: api_common.h:65
void vl_register_mapped_shmem_region(svm_region_t *rp)
#define foreach_vl_aring_size
Definition: api_common.h:50
vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
void(** msg_print_handlers)(void *, void *)
Message print function vector.
Definition: api_common.h:212
void vl_msg_api_send_shmem_nolock(unix_shared_memory_queue_t *q, u8 *elem)
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
#define PREDICT_FALSE(x)
Definition: clib.h:105
void svm_region_exit()
Definition: svm.c:1117
static u32 vl_msg_api_handle_get_index(u32 index)
Definition: api.h:37
void vl_set_api_pvt_heap_size(u64 size)
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:198
u64 global_size
size of the global VM region
Definition: api_common.h:288
u8 enabled
trace is enabled
Definition: api_common.h:90
An API client registration, only in vpp/vlib.
Definition: api_common.h:44
int unix_shared_memory_queue_sub(unix_shared_memory_queue_t *q, u8 *elem, int nowait)
api_main_t api_main
Definition: api_shared.c:35
ring_alloc_t * vl_rings
Definition: api_common.h:73
void vl_init_shmem(svm_region_t *vlib_rp, int is_vlib, int is_private_region)
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:221
static void * clib_mem_alloc_or_null(uword size)
Definition: mem.h:128
u64 global_baseva
base virtual address for global VM region
Definition: api_common.h:285
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
unix_shared_memory_queue_t * vl_input_queue
shared memory only: pointer to client input queue
Definition: api_common.h:59
unix_shared_memory_queue_t * q
message allocated in this shmem ring
Definition: api_common.h:136
#define clib_warning(format, args...)
Definition: error.h:59
void vl_msg_api_trace(api_main_t *am, vl_api_trace_t *tp, void *msg)
Definition: api_shared.c:66
void vl_set_memory_gid(int gid)
u32 garbage_collects
Definition: api_common.h:85
static void vl_msg_api_free_nolock(void *a)
void vl_msg_api_free(void *a)
const char ** msg_names
Message name vector.
Definition: api_common.h:215
void vl_msg_api_increment_missing_client_counter(void)
Definition: api_shared.c:44
vl_api_trace_t * tx_trace
Sent message trace configuration.
Definition: api_common.h:239
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u32 data_len
message length not including header
Definition: api_common.h:137
Message header structure.
Definition: api_common.h:134
unix_shared_memory_queue_t * unix_shared_memory_queue_init(int nels, int elsize, int consumer_pid, int signal_when_queue_non_empty)
u64 size
Definition: vhost-user.h:76
static void clib_mem_free(void *p)
Definition: mem.h:179
socket_main_t socket_main
Definition: memory_shared.c:42
u64 global_pvt_heap_size
size of the global VM private mheap
Definition: api_common.h:294
static void * clib_mem_alloc(uword size)
Definition: mem.h:112
vl_api_registration_t * current_rp
Definition: api_common.h:173
u32 restart_reclaims
Definition: api_common.h:82
i32 vlib_signal
(Historical) signal-based queue non-empty signal, to be removed
Definition: api_common.h:315
u64 uword
Definition: types.h:112
unsigned short u16
Definition: types.h:57
void(** msg_endian_handlers)(void *)
Message endian handler vector.
Definition: api_common.h:209
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
const char * name
Definition: svm_common.h:68
void svm_region_unmap(void *rp_arg)
Definition: svm.c:1000
void svm_client_scan_this_region_nolock(svm_region_t *rp)
Definition: svm.c:1168
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
static void * vl_msg_api_alloc_internal(int nbytes, int pool, int may_return_null)
Definition: memory_shared.c:47
unix_shared_memory_queue_t * rp
Definition: api_common.h:39
void * vl_msg_api_alloc_as_if_client_or_null(int nbytes)
#define hash_get_mem(h, key)
Definition: hash.h:268
void(** msg_handlers)(void *)
Message handler vector.
Definition: api_common.h:201
void vl_set_api_memory_size(u64 size)
void * vl_msg_api_alloc_as_if_client(int nbytes)
static u32 vl_msg_api_handle_get_epoch(u32 index)
Definition: api.h:31
void * vl_msg_api_alloc_or_null(int nbytes)
svm_region_t ** mapped_shmem_regions
Definition: api_common.h:258
uword * msg_index_by_name_and_crc
client message index hash table
Definition: api_common.h:321
u32 vlib_input_queue_length
vpp/vlib input queue length
Definition: api_common.h:318
pthread_mutex_t mutex
Definition: svm_common.h:37
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static svm_region_t * root_rp
Definition: svm.c:46
int svm_region_init_chroot(const char *root_path)
Definition: svm.c:817