FD.io VPP  v19.04-6-g6f05f72
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 
29 #include <vppinfra/format.h>
30 #include <vppinfra/byte_order.h>
31 #include <vppinfra/error.h>
32 #include <svm/queue.h>
33 #include <vlib/vlib.h>
34 #include <vlib/unix/unix.h>
35 #include <vlibmemory/memory_api.h>
37 
38 #define vl_typedefs
40 #undef vl_typedefs
41 
42 #define DEBUG_MESSAGE_BUFFER_OVERRUN 0
43 
44 static inline void *
45 vl_msg_api_alloc_internal (int nbytes, int pool, int may_return_null)
46 {
47  int i;
48  msgbuf_t *rv;
49  ring_alloc_t *ap;
50  svm_queue_t *q;
51  void *oldheap;
52  vl_shmem_hdr_t *shmem_hdr;
53  api_main_t *am = &api_main;
54 
55  shmem_hdr = am->shmem_hdr;
56 
57 #if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
58  nbytes += 4;
59 #endif
60 
61  ASSERT (pool == 0 || vlib_get_thread_index () == 0);
62 
63  if (shmem_hdr == 0)
64  {
65  clib_warning ("shared memory header NULL");
66  return 0;
67  }
68 
69  /* account for the msgbuf_t header */
70  nbytes += sizeof (msgbuf_t);
71 
72  if (shmem_hdr->vl_rings == 0)
73  {
74  clib_warning ("vl_rings NULL");
75  ASSERT (0);
76  abort ();
77  }
78 
79  if (shmem_hdr->client_rings == 0)
80  {
81  clib_warning ("client_rings NULL");
82  ASSERT (0);
83  abort ();
84  }
85 
86  ap = pool ? shmem_hdr->vl_rings : shmem_hdr->client_rings;
87  for (i = 0; i < vec_len (ap); i++)
88  {
89  /* Too big? */
90  if (nbytes > ap[i].size)
91  {
92  continue;
93  }
94 
95  q = ap[i].rp;
96  if (pool == 0)
97  {
98  pthread_mutex_lock (&q->mutex);
99  }
100  rv = (msgbuf_t *) (&q->data[0] + q->head * q->elsize);
101  /*
102  * Is this item still in use?
103  */
104  if (rv->q)
105  {
106  u32 now = (u32) time (0);
107 
108  if (PREDICT_TRUE (rv->gc_mark_timestamp == 0))
109  rv->gc_mark_timestamp = now;
110  else
111  {
112  if (now - rv->gc_mark_timestamp > 10)
113  {
114  if (CLIB_DEBUG > 0)
115  {
116  u16 *msg_idp, msg_id;
118  ("garbage collect pool %d ring %d index %d", pool, i,
119  q->head);
120  msg_idp = (u16 *) (rv->data);
121  msg_id = clib_net_to_host_u16 (*msg_idp);
122  if (msg_id < vec_len (api_main.msg_names))
123  clib_warning ("msg id %d name %s", (u32) msg_id,
124  api_main.msg_names[msg_id]);
125  }
126  shmem_hdr->garbage_collects++;
127  goto collected;
128  }
129  }
130 
131 
132  /* yes, loser; try next larger pool */
133  ap[i].misses++;
134  if (pool == 0)
135  pthread_mutex_unlock (&q->mutex);
136  continue;
137  }
138  collected:
139 
140  /* OK, we have a winner */
141  ap[i].hits++;
142  /*
143  * Remember the source queue, although we
144  * don't need to know the queue to free the item.
145  */
146  rv->q = q;
147  rv->gc_mark_timestamp = 0;
148  q->head++;
149  if (q->head == q->maxsize)
150  q->head = 0;
151 
152  if (pool == 0)
153  pthread_mutex_unlock (&q->mutex);
154  goto out;
155  }
156 
157  /*
158  * Request too big, or head element of all size-compatible rings
159  * still in use. Fall back to shared-memory malloc.
160  */
161  am->ring_misses++;
162 
163  pthread_mutex_lock (&am->vlib_rp->mutex);
164  oldheap = svm_push_data_heap (am->vlib_rp);
165  if (may_return_null)
166  {
167  rv = clib_mem_alloc_or_null (nbytes);
168  if (PREDICT_FALSE (rv == 0))
169  {
170  svm_pop_heap (oldheap);
171  pthread_mutex_unlock (&am->vlib_rp->mutex);
172  return 0;
173  }
174  }
175  else
176  rv = clib_mem_alloc (nbytes);
177 
178  rv->q = 0;
179  rv->gc_mark_timestamp = 0;
180  svm_pop_heap (oldheap);
181  pthread_mutex_unlock (&am->vlib_rp->mutex);
182 
183 out:
184 #if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
185  {
186  nbytes -= 4;
187  u32 *overrun;
188  overrun = (u32 *) (rv->data + nbytes - sizeof (msgbuf_t));
189  *overrun = 0x1badbabe;
190  }
191 #endif
192  rv->data_len = htonl (nbytes - sizeof (msgbuf_t));
193 
194  return (rv->data);
195 }
196 
197 void *
198 vl_msg_api_alloc (int nbytes)
199 {
200  int pool;
201  api_main_t *am = &api_main;
202  vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr;
203 
204  /*
205  * Clients use pool-0, vlib proc uses pool 1
206  */
207  pool = (am->our_pid == shmem_hdr->vl_pid);
208  return vl_msg_api_alloc_internal (nbytes, pool, 0 /* may_return_null */ );
209 }
210 
211 void *
213 {
214  int pool;
215  api_main_t *am = &api_main;
216  vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr;
217 
218  pool = (am->our_pid == shmem_hdr->vl_pid);
219  return vl_msg_api_alloc_internal (nbytes, pool, 1 /* may_return_null */ );
220 }
221 
222 void *
224 {
225  return vl_msg_api_alloc_internal (nbytes, 0, 0 /* may_return_null */ );
226 }
227 
228 void *
230 {
231  return vl_msg_api_alloc_internal (nbytes, 0, 1 /* may_return_null */ );
232 }
233 
234 void *
236 {
237  api_main_t *am = &api_main;
238  vl_shmem_hdr_t *save_shmem_hdr = am->shmem_hdr;
239  svm_region_t *vlib_rp, *save_vlib_rp = am->vlib_rp;
240  void *msg;
241 
242  vlib_rp = am->vlib_rp = reg->vlib_rp;
243  am->shmem_hdr = (void *) vlib_rp->user_ctx;
244 
245  msg = vl_msg_api_alloc_internal (nbytes, 0, 0 /* may_return_null */ );
246 
247  am->shmem_hdr = save_shmem_hdr;
248  am->vlib_rp = save_vlib_rp;
249 
250  return msg;
251 }
252 
253 void
255 {
256  msgbuf_t *rv;
257  void *oldheap;
258  api_main_t *am = &api_main;
259 
260  rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data));
261 
262  /*
263  * Here's the beauty of the scheme. Only one proc/thread has
264  * control of a given message buffer. To free a buffer, we just clear the
265  * queue field, and leave. No locks, no hits, no errors...
266  */
267  if (rv->q)
268  {
269  rv->q = 0;
270  rv->gc_mark_timestamp = 0;
271 #if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
272  {
273  u32 *overrun;
274  overrun = (u32 *) (rv->data + ntohl (rv->data_len));
275  ASSERT (*overrun == 0x1badbabe);
276  }
277 #endif
278  return;
279  }
280 
281  pthread_mutex_lock (&am->vlib_rp->mutex);
282  oldheap = svm_push_data_heap (am->vlib_rp);
283 
284 #if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
285  {
286  u32 *overrun;
287  overrun = (u32 *) (rv->data + ntohl (rv->data_len));
288  ASSERT (*overrun == 0x1badbabe);
289  }
290 #endif
291 
292  clib_mem_free (rv);
293  svm_pop_heap (oldheap);
294  pthread_mutex_unlock (&am->vlib_rp->mutex);
295 }
296 
297 static void
299 {
300  msgbuf_t *rv;
301  void *oldheap;
302  api_main_t *am = &api_main;
303 
304  rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data));
305  /*
306  * Here's the beauty of the scheme. Only one proc/thread has
307  * control of a given message buffer. To free a buffer, we just clear the
308  * queue field, and leave. No locks, no hits, no errors...
309  */
310  if (rv->q)
311  {
312  rv->q = 0;
313  return;
314  }
315 
316  oldheap = svm_push_data_heap (am->vlib_rp);
317  clib_mem_free (rv);
318  svm_pop_heap (oldheap);
319 }
320 
321 void
323 {
324  api_main_t *am = &api_main;
325 
326  am->root_path = name;
327 }
328 
329 void
331 {
332  api_main_t *am = &api_main;
333 
334  am->api_uid = uid;
335 }
336 
337 void
339 {
340  api_main_t *am = &api_main;
341 
342  am->api_gid = gid;
343 }
344 
345 void
347 {
348  api_main_t *am = &api_main;
349 
350  am->global_baseva = baseva;
351 }
352 
353 void
355 {
356  api_main_t *am = &api_main;
357 
358  am->global_size = size;
359 }
360 
361 void
363 {
364  api_main_t *am = &api_main;
365 
366  am->api_size = size;
367 }
368 
369 void
371 {
372  api_main_t *am = &api_main;
373 
375 }
376 
377 void
379 {
380  api_main_t *am = &api_main;
381 
382  am->api_pvt_heap_size = size;
383 }
384 
385 static void
387 {
388  api_main_t *am = &api_main;
389  u32 vlib_input_queue_length;
390 
391  /* vlib main input queue */
392  vlib_input_queue_length = 1024;
393  if (am->vlib_input_queue_length)
394  vlib_input_queue_length = am->vlib_input_queue_length;
395 
396  shmem_hdr->vl_input_queue =
397  svm_queue_alloc_and_init (vlib_input_queue_length, sizeof (uword),
398  getpid ());
399 
400 #define _(sz,n) \
401  do { \
402  ring_alloc_t _rp; \
403  _rp.rp = svm_queue_alloc_and_init ((n), (sz), 0); \
404  _rp.size = (sz); \
405  _rp.nitems = n; \
406  _rp.hits = 0; \
407  _rp.misses = 0; \
408  vec_add1(shmem_hdr->vl_rings, _rp); \
409  } while (0);
410 
412 #undef _
413 
414 #define _(sz,n) \
415  do { \
416  ring_alloc_t _rp; \
417  _rp.rp = svm_queue_alloc_and_init ((n), (sz), 0); \
418  _rp.size = (sz); \
419  _rp.nitems = n; \
420  _rp.hits = 0; \
421  _rp.misses = 0; \
422  vec_add1(shmem_hdr->client_rings, _rp); \
423  } while (0);
424 
426 #undef _
427 }
428 
429 void
431 {
433  ring_alloc_t *rp;
434  u32 size;
435 
436  if (!config)
437  {
439  return;
440  }
441 
442  vec_foreach (c, config)
443  {
444  switch (c->type)
445  {
446  case VL_API_QUEUE:
448  getpid ());
449  continue;
450  case VL_API_VLIB_RING:
451  vec_add2 (hdr->vl_rings, rp, 1);
452  break;
453  case VL_API_CLIENT_RING:
454  vec_add2 (hdr->client_rings, rp, 1);
455  break;
456  default:
457  clib_warning ("unknown config type: %d", c->type);
458  continue;
459  }
460 
461  size = sizeof (ring_alloc_t) + c->size;
462  rp->rp = svm_queue_alloc_and_init (c->count, size, 0);
463  rp->size = size;
464  rp->nitems = c->count;
465  rp->hits = 0;
466  rp->misses = 0;
467  }
468 }
469 
470 void
472  int is_vlib, int is_private_region)
473 {
474  api_main_t *am = &api_main;
475  vl_shmem_hdr_t *shmem_hdr = 0;
476  void *oldheap;
477  ASSERT (vlib_rp);
478 
479  /* $$$$ need private region config parameters */
480 
481  oldheap = svm_push_data_heap (vlib_rp);
482 
483  vec_validate (shmem_hdr, 0);
484  shmem_hdr->version = VL_SHM_VERSION;
485  shmem_hdr->clib_file_index = VL_API_INVALID_FI;
486 
487  /* Set up the queue and msg ring allocator */
488  vl_api_mem_config (shmem_hdr, config);
489 
490  if (is_private_region == 0)
491  {
492  am->shmem_hdr = shmem_hdr;
493  am->vlib_rp = vlib_rp;
494  am->our_pid = getpid ();
495  if (is_vlib)
496  am->shmem_hdr->vl_pid = am->our_pid;
497  }
498  else
499  shmem_hdr->vl_pid = am->our_pid;
500 
501  svm_pop_heap (oldheap);
502 
503  /*
504  * After absolutely everything that a client might see is set up,
505  * declare the shmem region valid
506  */
507  vlib_rp->user_ctx = shmem_hdr;
508 
509  pthread_mutex_unlock (&vlib_rp->mutex);
510 }
511 
512 int
513 vl_map_shmem (const char *region_name, int is_vlib)
514 {
515  svm_map_region_args_t _a, *a = &_a;
516  svm_region_t *vlib_rp, *root_rp;
517  api_main_t *am = &api_main;
518  int i;
519  struct timespec ts, tsrem;
520  char *vpe_api_region_suffix = "-vpe-api";
521 
522  clib_memset (a, 0, sizeof (*a));
523 
524  if (strstr (region_name, vpe_api_region_suffix))
525  {
526  u8 *root_path = format (0, "%s", region_name);
527  _vec_len (root_path) = (vec_len (root_path) -
528  strlen (vpe_api_region_suffix));
529  vec_terminate_c_string (root_path);
530  a->root_path = (const char *) root_path;
531  am->root_path = (const char *) root_path;
532  }
533 
534  if (is_vlib == 0)
535  {
536  int tfd;
537  u8 *api_name;
538  /*
539  * Clients wait for vpp to set up the root / API regioins
540  */
541  if (am->root_path)
542  api_name = format (0, "/dev/shm/%s-%s%c", am->root_path,
543  region_name + 1, 0);
544  else
545  api_name = format (0, "/dev/shm%s%c", region_name, 0);
546 
547  /* Wait up to 100 seconds... */
548  for (i = 0; i < 10000; i++)
549  {
550  ts.tv_sec = 0;
551  ts.tv_nsec = 10000 * 1000; /* 10 ms */
552  while (nanosleep (&ts, &tsrem) < 0)
553  ts = tsrem;
554  tfd = open ((char *) api_name, O_RDWR);
555  if (tfd >= 0)
556  break;
557  }
558  vec_free (api_name);
559  if (tfd < 0)
560  {
561  clib_warning ("region init fail");
562  return -2;
563  }
564  close (tfd);
565  svm_region_init_chroot_uid_gid (am->root_path, getuid (), getgid ());
566  }
567 
568  if (a->root_path != NULL)
569  {
570  a->name = "/vpe-api";
571  }
572  else
573  a->name = region_name;
574  a->size = am->api_size ? am->api_size : (16 << 20);
575  a->flags = SVM_FLAGS_MHEAP;
576  a->uid = am->api_uid;
577  a->gid = am->api_gid;
579 
580  vlib_rp = svm_region_find_or_create (a);
581 
582  if (vlib_rp == 0)
583  return (-2);
584 
585  pthread_mutex_lock (&vlib_rp->mutex);
586  /* Has someone else set up the shared-memory variable table? */
587  if (vlib_rp->user_ctx)
588  {
589  am->shmem_hdr = (void *) vlib_rp->user_ctx;
590  am->our_pid = getpid ();
591  if (is_vlib)
592  {
593  svm_queue_t *q;
594  uword old_msg;
595  /*
596  * application restart. Reset cached pids, API message
597  * rings, list of clients; otherwise, various things
598  * fail. (e.g. queue non-empty notification)
599  */
600 
601  /* ghosts keep the region from disappearing properly */
604  q = am->shmem_hdr->vl_input_queue;
605  am->shmem_hdr->vl_pid = getpid ();
606  q->consumer_pid = am->shmem_hdr->vl_pid;
607  /* Drain the input queue, freeing msgs */
608  for (i = 0; i < 10; i++)
609  {
610  if (pthread_mutex_trylock (&q->mutex) == 0)
611  {
612  pthread_mutex_unlock (&q->mutex);
613  goto mutex_ok;
614  }
615  ts.tv_sec = 0;
616  ts.tv_nsec = 10000 * 1000; /* 10 ms */
617  while (nanosleep (&ts, &tsrem) < 0)
618  ts = tsrem;
619  }
620  /* Mutex buggered, "fix" it */
621  clib_memset (&q->mutex, 0, sizeof (q->mutex));
622  clib_warning ("forcibly release main input queue mutex");
623 
624  mutex_ok:
625  am->vlib_rp = vlib_rp;
626  while (svm_queue_sub (q, (u8 *) & old_msg, SVM_Q_NOWAIT, 0)
627  != -2 /* queue underflow */ )
628  {
629  vl_msg_api_free_nolock ((void *) old_msg);
631  }
632  pthread_mutex_unlock (&vlib_rp->mutex);
633  root_rp = svm_get_root_rp ();
634  ASSERT (root_rp);
635  /* Clean up the root region client list */
636  pthread_mutex_lock (&root_rp->mutex);
638  pthread_mutex_unlock (&root_rp->mutex);
639  }
640  else
641  {
642  pthread_mutex_unlock (&vlib_rp->mutex);
643  }
644  am->vlib_rp = vlib_rp;
645  vec_add1 (am->mapped_shmem_regions, vlib_rp);
646  return 0;
647  }
648  /* Clients simply have to wait... */
649  if (!is_vlib)
650  {
651  pthread_mutex_unlock (&vlib_rp->mutex);
652 
653  /* Wait up to 100 seconds... */
654  for (i = 0; i < 10000; i++)
655  {
656  ts.tv_sec = 0;
657  ts.tv_nsec = 10000 * 1000; /* 10 ms */
658  while (nanosleep (&ts, &tsrem) < 0)
659  ts = tsrem;
660  if (vlib_rp->user_ctx)
661  goto ready;
662  }
663  /* Clean up and leave... */
664  svm_region_unmap (vlib_rp);
665  clib_warning ("region init fail");
666  return (-2);
667 
668  ready:
669  am->shmem_hdr = (void *) vlib_rp->user_ctx;
670  am->our_pid = getpid ();
671  am->vlib_rp = vlib_rp;
672  vec_add1 (am->mapped_shmem_regions, vlib_rp);
673  return 0;
674  }
675 
676  /* Nope, it's our problem... */
677  vl_init_shmem (vlib_rp, 0 /* default config */ , 1 /* is vlib */ ,
678  0 /* is_private_region */ );
679 
680  vec_add1 (am->mapped_shmem_regions, vlib_rp);
681  return 0;
682 }
683 
684 void
686 {
687  api_main_t *am = &api_main;
688 
689  vec_add1 (am->mapped_shmem_regions, rp);
690 }
691 
692 static void
694 {
695  svm_region_t *rp;
696  int i;
697  api_main_t *am = &api_main;
698 
699  if (!svm_get_root_rp ())
700  return;
701 
702  for (i = 0; i < vec_len (am->mapped_shmem_regions); i++)
703  {
704  rp = am->mapped_shmem_regions[i];
705  is_client ? svm_region_unmap_client (rp) : svm_region_unmap (rp);
706  }
707 
709  am->shmem_hdr = 0;
710 
711  is_client ? svm_region_exit_client () : svm_region_exit ();
712 
713  /* $$$ more careful cleanup, valgrind run... */
714  vec_free (am->msg_handlers);
717 }
718 
719 void
721 {
723 }
724 
725 void
727 {
729 }
730 
731 void
733 {
734  api_main_t *am = &api_main;
735  uword *trace = (uword *) elem;
736 
737  if (am->tx_trace && am->tx_trace->enabled)
738  vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]);
739 
740  /*
741  * Announce a probable binary API client bug:
742  * some client's input queue is stuffed.
743  * The situation may be recoverable, or not.
744  */
745  if (PREDICT_FALSE
746  (am->vl_clients /* vpp side */ && (q->cursize == q->maxsize)))
747  clib_warning ("WARNING: client input queue at %llx is stuffed...", q);
748  (void) svm_queue_add (q, elem, 0 /* nowait */ );
749 }
750 
751 int
753 {
754  return (q->cursize < q->maxsize);
755 }
756 
757 void
759 {
760  api_main_t *am = &api_main;
761  uword *trace = (uword *) elem;
762 
763  if (am->tx_trace && am->tx_trace->enabled)
764  vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]);
765 
766  (void) svm_queue_add_nolock (q, elem);
767 }
768 
769 /*
770  * fd.io coding-style-patch-verification: ON
771  *
772  * Local Variables:
773  * eval: (c-set-style "gnu")
774  * End:
775  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
u64 api_pvt_heap_size
size of the api private mheap
Definition: api_common.h:301
void svm_region_init_chroot_uid_gid(const char *root_path, int uid, int gid)
Definition: svm.c:899
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:862
svm_region_t * svm_get_root_rp(void)
Definition: svm.c:54
const char * root_path
Definition: svm_common.h:67
static void svm_pop_heap(void *oldheap)
Definition: svm.h:94
int svm_queue_add(svm_queue_t *q, u8 *elem, int nowait)
Definition: queue.c:239
a
Definition: bitmap.h:538
void vl_set_global_memory_baseva(u64 baseva)
int vl_map_shmem(const char *region_name, int is_vlib)
u64 api_size
size of the API region
Definition: api_common.h:295
Optimized string handling code, including c11-compliant "safe C library" variants.
u32 application_restarts
Definition: memory_shared.h:95
#define PREDICT_TRUE(x)
Definition: clib.h:112
void vl_set_memory_uid(int uid)
unsigned long u64
Definition: types.h:89
void vl_set_global_pvt_heap_size(u64 size)
#define NULL
Definition: clib.h:58
void vl_unmap_shmem(void)
u32 gc_mark_timestamp
message garbage collector mark TS
Definition: api_common.h:140
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
Definition: vec.h:1014
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
static void vl_unmap_shmem_internal(u8 is_client)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:560
int i
int api_uid
uid for the api shared memory region
Definition: api_common.h:283
void svm_region_unmap_client(void *rp_arg)
Definition: svm.c:1190
ring_alloc_t * client_rings
Definition: memory_shared.h:92
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
svm_queue_t * q
message allocated in this shmem ring
Definition: api_common.h:138
int vl_mem_api_can_send(svm_queue_t *q)
void svm_region_exit_client(void)
Definition: svm.c:1256
u8 data[0]
actual message begins here
Definition: api_common.h:141
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u8 data[128]
Definition: ipsec.api:248
struct msgbuf_ msgbuf_t
Message header structure.
void * vl_msg_api_alloc(int nbytes)
int api_gid
gid for the api shared memory region
Definition: api_common.h:286
unsigned char u8
Definition: types.h:56
void vl_set_global_memory_size(u64 size)
int our_pid
Current process PID.
Definition: api_common.h:252
void svm_region_exit(void)
Definition: svm.c:1250
int svm_queue_sub(svm_queue_t *q, u8 *elem, svm_q_conditional_wait_t cond, u32 time)
Definition: queue.c:348
#define foreach_clnt_aring_size
Definition: memory_shared.h:71
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:268
void * svm_region_find_or_create(svm_map_region_args_t *a)
Definition: svm.c:922
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:331
svm_region_t * vlib_rp
Current binary api segment descriptor.
Definition: api_common.h:255
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
Definition: api_common.h:265
unsigned int u32
Definition: types.h:88
svm_queue_t * rp
Definition: memory_shared.h:37
struct ring_alloc_ ring_alloc_t
void vl_set_memory_root_path(const char *name)
#define SVM_FLAGS_MHEAP
Definition: svm_common.h:27
volatile int vl_pid
Definition: memory_shared.h:81
uword size
void vl_register_mapped_shmem_region(svm_region_t *rp)
void vl_init_shmem(svm_region_t *vlib_rp, vl_api_shm_elem_config_t *config, int is_vlib, int is_private_region)
#define VL_API_INVALID_FI
Definition: api_common.h:76
void(** msg_print_handlers)(void *, void *)
Message print function vector.
Definition: api_common.h:216
unsigned short u16
Definition: types.h:57
#define PREDICT_FALSE(x)
Definition: clib.h:111
#define VL_SHM_VERSION
u8 name[64]
Definition: memclnt.api:152
void vl_set_api_pvt_heap_size(u64 size)
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:202
u64 global_size
size of the global VM region
Definition: api_common.h:292
u8 enabled
trace is enabled
Definition: api_common.h:92
An API client registration, only in vpp/vlib.
Definition: api_common.h:45
void vl_msg_api_send_shmem(svm_queue_t *q, u8 *elem)
ring_alloc_t * vl_rings
Definition: memory_shared.h:89
svmdb_client_t * c
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:212
static void * clib_mem_alloc_or_null(uword size)
Definition: mem.h:148
u64 global_baseva
base virtual address for global VM region
Definition: api_common.h:289
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
#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)
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:219
svm_queue_t * vl_input_queue
Definition: memory_shared.h:84
void vl_unmap_shmem_client(void)
vl_api_trace_t * tx_trace
Sent message trace configuration.
Definition: api_common.h:243
#define ASSERT(truth)
u32 data_len
message length not including header
Definition: api_common.h:139
Message header structure.
Definition: api_common.h:136
svm_queue_t * svm_queue_alloc_and_init(int nels, int elsize, int consumer_pid)
Allocate and initialize svm queue.
Definition: queue.c:72
static void clib_mem_free(void *p)
Definition: mem.h:205
u64 global_pvt_heap_size
size of the global VM private mheap
Definition: api_common.h:298
static void vl_api_default_mem_config(vl_shmem_hdr_t *shmem_hdr)
static void * clib_mem_alloc(uword size)
Definition: mem.h:132
#define foreach_vl_aring_size
Definition: memory_shared.h:66
void vl_api_mem_config(vl_shmem_hdr_t *hdr, vl_api_shm_elem_config_t *config)
void(** msg_endian_handlers)(void *)
Message endian handler vector.
Definition: api_common.h:213
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
const char * name
Definition: svm_common.h:68
u64 uword
Definition: types.h:112
void svm_region_unmap(void *rp_arg)
Definition: svm.c:1184
void svm_client_scan_this_region_nolock(svm_region_t *rp)
Definition: svm.c:1262
int svm_queue_add_nolock(svm_queue_t *q, u8 *elem)
Definition: queue.c:192
static void * vl_msg_api_alloc_internal(int nbytes, int pool, int may_return_null)
Definition: memory_shared.c:45
struct _svm_queue svm_queue_t
void * vl_msg_api_alloc_as_if_client_or_null(int nbytes)
void * vl_mem_api_alloc_as_if_client_w_reg(vl_api_registration_t *reg, int nbytes)
void(** msg_handlers)(void *)
Message handler vector.
Definition: api_common.h:205
void vl_set_api_memory_size(u64 size)
#define vec_foreach(var, vec)
Vector iterator.
void * vl_msg_api_alloc_as_if_client(int nbytes)
void * vl_msg_api_alloc_or_null(int nbytes)
svm_region_t ** mapped_shmem_regions
Definition: api_common.h:262
api_main_t api_main
Definition: api_shared.c:35
void vl_msg_api_send_shmem_nolock(svm_queue_t *q, u8 *elem)
svm_region_t * vlib_rp
Definition: api_common.h:61
u32 vlib_input_queue_length
vpp/vlib input queue length
Definition: api_common.h:319
pthread_mutex_t mutex
Definition: svm_common.h:37
non-blocking call - works with both condvar and eventfd signaling
Definition: queue.h:44
static svm_region_t * root_rp
Definition: svm.c:46