FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
vppcom.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <signal.h>
19 #include <svm/svm_fifo_segment.h>
20 #include <vlibmemory/api.h>
21 #include <vpp/api/vpe_msg_enum.h>
23 #include <uri/vppcom.h>
24 #include <vlib/unix/unix.h>
25 #include <vppinfra/vec_bootstrap.h>
26 
27 #define vl_typedefs /* define message structures */
28 #include <vpp/api/vpe_all_api_h.h>
29 #undef vl_typedefs
30 
31 /* declare message handlers for each api */
32 
33 #define vl_endianfun /* define message structures */
34 #include <vpp/api/vpe_all_api_h.h>
35 #undef vl_endianfun
36 
37 /* instantiate all the print functions we know about */
38 #define vl_print(handle, ...)
39 #define vl_printfun
40 #include <vpp/api/vpe_all_api_h.h>
41 #undef vl_printfun
42 
43 #if (CLIB_DEBUG > 0)
44 /* Set VPPCOM_DEBUG 2 for connection debug, 3 for read/write debug output */
45 #define VPPCOM_DEBUG 1
46 #else
47 #define VPPCOM_DEBUG 0
48 #endif
49 
50 /*
51  * VPPCOM Private definitions and functions.
52  */
53 typedef enum
54 {
59 } app_state_t;
60 
61 typedef enum
62 {
70 
71 typedef struct
72 {
74 
75  svm_fifo_t *server_rx_fifo;
76  svm_fifo_t *server_tx_fifo;
78  u64 vpp_session_handle;
80 
81  /* Socket configuration state */
88  u8 ip[16];
92  u64 options[16];
93 } session_t;
94 
95 typedef struct vppcom_cfg_t_
96 {
109 } vppcom_cfg_t;
110 
111 typedef struct vppcom_main_t_
112 {
117  int main_cpu;
118 
119  /* vpe input queue */
121 
122  /* API client handle */
124 
125  /* Session pool */
128 
129  /* Hash table for disconnect processing */
131 
132  /* Select bitmaps */
136 
137  /* Our event queue */
139 
140  /* unique segment name counter */
142 
143  pid_t my_pid;
144 
145  /* For deadman timers */
147 
148  /* State of the connection, shared between msg RX thread and main thread */
150 
152 
153  /* VNET_API_ERROR_FOO -> "Foo" hash table */
155 } vppcom_main_t;
156 
157 vppcom_main_t vppcom_main = {.my_client_index = ~0 };
158 
159 static const char *
161 {
162  char *st;
163 
164  switch (state)
165  {
166  case STATE_APP_START:
167  st = "STATE_APP_START";
168  break;
169 
170  case STATE_APP_CONN_VPP:
171  st = "STATE_APP_CONN_VPP";
172  break;
173 
174  case STATE_APP_ENABLED:
175  st = "STATE_APP_ENABLED";
176  break;
177 
178  case STATE_APP_ATTACHED:
179  st = "STATE_APP_ATTACHED";
180  break;
181 
182  default:
183  st = "UNKNOWN_APP_STATE";
184  break;
185  }
186 
187  return st;
188 }
189 
190 static const char *
192 {
193  char *st;
194 
195  switch (state)
196  {
197  case STATE_START:
198  st = "STATE_START";
199  break;
200 
201  case STATE_CONNECT:
202  st = "STATE_CONNECT";
203  break;
204 
205  case STATE_LISTEN:
206  st = "STATE_LISTEN";
207  break;
208 
209  case STATE_ACCEPT:
210  st = "STATE_ACCEPT";
211  break;
212 
213  case STATE_DISCONNECT:
214  st = "STATE_DISCONNECT";
215  break;
216 
217  case STATE_FAILED:
218  st = "STATE_FAILED";
219  break;
220 
221  default:
222  st = "UNKNOWN_STATE";
223  break;
224  }
225 
226  return st;
227 }
228 
229 /*
230  * VPPCOM Utility Functions
231  */
232 static inline int
233 vppcom_session_at_index (u32 session_index, session_t * volatile *sess)
234 {
235  vppcom_main_t *vcm = &vppcom_main;
236 
237  /* Assumes that caller has acquired spinlock: vcm->sessions_lockp */
238  if (PREDICT_FALSE ((session_index == ~0) ||
239  pool_is_free_index (vcm->sessions, session_index)))
240  {
241  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
242  vcm->my_pid, session_index);
243  return VPPCOM_EBADFD;
244  }
245  *sess = pool_elt_at_index (vcm->sessions, session_index);
246  return VPPCOM_OK;
247 }
248 
249 static int
250 vppcom_connect_to_vpp (char *app_name)
251 {
252  api_main_t *am = &api_main;
253  vppcom_main_t *vcm = &vppcom_main;
254 
255  if (VPPCOM_DEBUG > 0)
256  printf ("\nConnecting to VPP api...");
257  if (vl_client_connect_to_vlib ("/vpe-api", app_name, 32) < 0)
258  {
259  clib_warning ("[%d] connect to vpp (%s) failed!",
260  vcm->my_pid, app_name);
261  return VPPCOM_ECONNREFUSED;
262  }
263 
265  vcm->my_client_index = am->my_client_index;
266  if (VPPCOM_DEBUG > 0)
267  printf (" connected!\n");
268 
270  return VPPCOM_OK;
271 }
272 
273 static u8 *
274 format_api_error (u8 * s, va_list * args)
275 {
276  vppcom_main_t *vcm = &vppcom_main;
277  i32 error = va_arg (*args, u32);
278  uword *p;
279 
280  p = hash_get (vcm->error_string_by_error_number, -error);
281 
282  if (p)
283  s = format (s, "%s (%d)", p[0], error);
284  else
285  s = format (s, "%d", error);
286  return s;
287 }
288 
289 static void
291 {
292  vppcom_main_t *vcm = &vppcom_main;
293 
294  vcm->error_string_by_error_number = hash_create (0, sizeof (uword));
295 
296 #define _(n,v,s) hash_set (vcm->error_string_by_error_number, -v, s);
298 #undef _
299 
300  hash_set (vcm->error_string_by_error_number, 99, "Misc");
301 }
302 
303 static inline int
305 {
306  vppcom_main_t *vcm = &vppcom_main;
307  f64 timeout = clib_time_now (&vcm->clib_time) + vcm->cfg.app_timeout;
308 
309  while (clib_time_now (&vcm->clib_time) < timeout)
310  {
311  if (vcm->app_state == app_state)
312  return VPPCOM_OK;
313  }
314  if (VPPCOM_DEBUG > 0)
315  clib_warning ("[%d] timeout waiting for state %s (%d)", vcm->my_pid,
316  vppcom_app_state_str (app_state), app_state);
317  return VPPCOM_ETIMEDOUT;
318 }
319 
320 static inline int
323  f64 wait_for_time)
324 {
325  vppcom_main_t *vcm = &vppcom_main;
326  f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
327  session_t *volatile session;
328  int rv;
329 
330  do
331  {
333  rv = vppcom_session_at_index (session_index, &session);
334  if (PREDICT_FALSE (rv))
335  {
337  return rv;
338  }
339  if (session->state == state)
340  {
342  return VPPCOM_OK;
343  }
345  }
346  while (clib_time_now (&vcm->clib_time) < timeout);
347 
348  if (VPPCOM_DEBUG > 0)
349  clib_warning ("[%d] timeout waiting for state %s (%d)", vcm->my_pid,
350  vppcom_session_state_str (state), state);
351  return VPPCOM_ETIMEDOUT;
352 }
353 
354 static inline int
356 {
357  vppcom_main_t *vcm = &vppcom_main;
358  f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
359 
360  do
361  {
363  return VPPCOM_OK;
364  }
365  while (clib_time_now (&vcm->clib_time) < timeout);
366 
367  if (wait_for_time == 0)
368  return VPPCOM_EAGAIN;
369 
370  if (VPPCOM_DEBUG > 0)
371  clib_warning ("[%d] timeout waiting for client_session_index",
372  vcm->my_pid);
373  return VPPCOM_ETIMEDOUT;
374 }
375 
376 /*
377  * VPP-API message functions
378  */
379 static void
381 {
382  vppcom_main_t *vcm = &vppcom_main;
384  bmp = vl_msg_api_alloc (sizeof (*bmp));
385  memset (bmp, 0, sizeof (*bmp));
386 
387  bmp->_vl_msg_id = ntohs (VL_API_SESSION_ENABLE_DISABLE);
388  bmp->client_index = vcm->my_client_index;
389  bmp->context = htonl (0xfeedface);
390  bmp->is_enable = is_enable;
391  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
392 }
393 
394 static int
396 {
397  vppcom_main_t *vcm = &vppcom_main;
398  int rv;
399 
400  if (vcm->app_state != STATE_APP_ENABLED)
401  {
402  vppcom_send_session_enable_disable (1 /* is_enabled == TRUE */ );
404  if (PREDICT_FALSE (rv))
405  {
406  if (VPPCOM_DEBUG > 0)
407  clib_warning ("[%d] Session enable timed out, rv = %s (%d)",
408  vcm->my_pid, vppcom_retval_str (rv), rv);
409  return rv;
410  }
411  }
412  return VPPCOM_OK;
413 }
414 
415 static void
417  (vl_api_session_enable_disable_reply_t * mp)
418 {
419  vppcom_main_t *vcm = &vppcom_main;
420 
421  if (mp->retval)
422  {
423  clib_warning ("[%d] session_enable_disable failed: %U", vcm->my_pid,
424  format_api_error, ntohl (mp->retval));
425  }
426  else
428 }
429 
430 static void
432 {
433  vppcom_main_t *vcm = &vppcom_main;
435  bmp = vl_msg_api_alloc (sizeof (*bmp));
436  memset (bmp, 0, sizeof (*bmp));
437 
438  bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
439  bmp->client_index = vcm->my_client_index;
440  bmp->context = htonl (0xfeedface);
441  bmp->options[APP_OPTIONS_FLAGS] =
442  APP_OPTIONS_FLAGS_USE_FIFO | APP_OPTIONS_FLAGS_ADD_SEGMENT;
447  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
448 }
449 
450 static int
452 {
453  vppcom_main_t *vcm = &vppcom_main;
454  int rv;
455 
458  if (PREDICT_FALSE (rv))
459  {
460  if (VPPCOM_DEBUG > 0)
461  clib_warning ("[%d] application attach timed out, rv = %s (%d)",
462  vcm->my_pid, vppcom_retval_str (rv), rv);
463  return rv;
464  }
465  return VPPCOM_OK;
466 }
467 
468 static void
470 {
471  vppcom_main_t *vcm = &vppcom_main;
473  bmp = vl_msg_api_alloc (sizeof (*bmp));
474  memset (bmp, 0, sizeof (*bmp));
475 
476  bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
477  bmp->client_index = vcm->my_client_index;
478  bmp->context = htonl (0xfeedface);
479  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
480 }
481 
482 static void
484  mp)
485 {
486  vppcom_main_t *vcm = &vppcom_main;
489  int rv;
490 
491  memset (a, 0, sizeof (*a));
492  if (mp->retval)
493  {
494  clib_warning ("[%d] attach failed: %U", vcm->my_pid,
495  format_api_error, ntohl (mp->retval));
496  return;
497  }
498 
499  if (mp->segment_name_length == 0)
500  {
501  clib_warning ("[%d] segment_name_length zero", vcm->my_pid);
502  return;
503  }
504 
505  a->segment_name = (char *) mp->segment_name;
506  a->segment_size = mp->segment_size;
507 
509 
510  /* Attach to the segment vpp created */
511  rv = svm_fifo_segment_attach (a);
513  if (PREDICT_FALSE (rv))
514  {
515  clib_warning ("[%d] svm_fifo_segment_attach ('%s') failed", vcm->my_pid,
516  mp->segment_name);
517  return;
518  }
519 
520  vcm->app_event_queue =
523 
525 }
526 
527 static void
528 vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t *
529  mp)
530 {
531  vppcom_main_t *vcm = &vppcom_main;
532 
533  if (mp->retval)
534  clib_warning ("[%d] detach failed: %U", vcm->my_pid, format_api_error,
535  ntohl (mp->retval));
536 
538 }
539 
540 static void
542  mp)
543 {
544  vppcom_main_t *vcm = &vppcom_main;
545  uword *p;
546 
548  if (p)
549  {
550  session_t *session = 0;
551  int rv;
553  rv = vppcom_session_at_index (p[0], &session);
554  if (PREDICT_FALSE (rv))
555  {
556  if (VPPCOM_DEBUG > 1)
557  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
558  vcm->my_pid, p[0]);
559  }
561  session->state = STATE_DISCONNECT;
563  }
564  else
565  {
566  if (VPPCOM_DEBUG > 1)
567  clib_warning ("[%d] couldn't find session key %llx", vcm->my_pid,
568  mp->handle);
569  }
570 
571  if (mp->retval)
572  clib_warning ("[%d] disconnect_session failed: %U", vcm->my_pid,
573  format_api_error, ntohl (mp->retval));
574 }
575 
576 static void
578 {
579  vppcom_main_t *vcm = &vppcom_main;
582  int rv;
583 
584  memset (a, 0, sizeof (*a));
585  a->segment_name = (char *) mp->segment_name;
586  a->segment_size = mp->segment_size;
587  /* Attach to the segment vpp created */
588  rv = svm_fifo_segment_attach (a);
590  if (PREDICT_FALSE (rv))
591  {
592  clib_warning ("[%d] svm_fifo_segment_attach ('%s') failed",
593  vcm->my_pid, mp->segment_name);
594  return;
595  }
596  if (VPPCOM_DEBUG > 1)
597  clib_warning ("[%d] mapped new segment '%s' size %d", vcm->my_pid,
598  mp->segment_name, mp->segment_size);
599 }
600 
601 static void
603 {
604  vppcom_main_t *vcm = &vppcom_main;
605  session_t *session = 0;
607  uword *p;
608  int rv = 0;
609 
611  if (p)
612  {
613  int rval;
615  rval = vppcom_session_at_index (p[0], &session);
616  if (PREDICT_FALSE (rval))
617  {
618  if (VPPCOM_DEBUG > 1)
619  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
620  vcm->my_pid, p[0]);
621  }
622  else
623  pool_put (vcm->sessions, session);
626  }
627  else
628  {
629  clib_warning ("[%d] couldn't find session key %llx", vcm->my_pid,
630  mp->handle);
631  rv = -11;
632  }
633 
634  rmp = vl_msg_api_alloc (sizeof (*rmp));
635  memset (rmp, 0, sizeof (*rmp));
636 
637  rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY);
638  rmp->retval = htonl (rv);
639  rmp->handle = mp->handle;
640  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
641 }
642 
643 static void
645 {
646  vppcom_main_t *vcm = &vppcom_main;
647  session_t *session = 0;
649  uword *p;
650  int rv = 0;
651 
653  if (p)
654  {
655  int rval;
657  rval = vppcom_session_at_index (p[0], &session);
658  if (PREDICT_FALSE (rval))
659  {
660  if (VPPCOM_DEBUG > 1)
661  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
662  vcm->my_pid, p[0]);
663  }
664  else
665  pool_put (vcm->sessions, session);
668  }
669  else
670  {
671  clib_warning ("[%d] couldn't find session key %llx", vcm->my_pid,
672  mp->handle);
673  rv = -11;
674  }
675 
676  rmp = vl_msg_api_alloc (sizeof (*rmp));
677  memset (rmp, 0, sizeof (*rmp));
678  rmp->_vl_msg_id = ntohs (VL_API_RESET_SESSION_REPLY);
679  rmp->retval = htonl (rv);
680  rmp->handle = mp->handle;
681  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
682 }
683 
684 static void
686 {
687  vppcom_main_t *vcm = &vppcom_main;
688  session_t *session;
689  u32 session_index;
690  svm_fifo_t *rx_fifo, *tx_fifo;
691  u8 is_cut_thru = 0;
692  int rv;
693 
694  if (mp->retval)
695  {
696  clib_warning ("[%d] connect failed: %U", vcm->my_pid, format_api_error,
697  ntohl (mp->retval));
698  return;
699  }
700 
701  session_index = mp->context;
702  if (VPPCOM_DEBUG > 1)
703  clib_warning ("[%d] session_index = %d 0x%08x", vcm->my_pid,
704  session_index, session_index);
705 
707  if (pool_is_free_index (vcm->sessions, session_index))
708  {
710  if (VPPCOM_DEBUG > 1)
711  clib_warning ("[%d] invalid session, sid %d is closed!",
712  vcm->my_pid, session_index);
713  return;
714  }
715 
716  /* We've been redirected */
717  if (mp->segment_name_length > 0)
718  {
721 
722  is_cut_thru = 1;
723  memset (a, 0, sizeof (*a));
724  a->segment_name = (char *) mp->segment_name;
725  if (VPPCOM_DEBUG > 1)
726  clib_warning ("[%d] cut-thru segment: %s", vcm->my_pid,
727  a->segment_name);
728  rv = svm_fifo_segment_attach (a);
730  if (PREDICT_FALSE (rv))
731  {
732  clib_warning ("[%d] sm_fifo_segment_attach ('%s') failed",
733  vcm->my_pid, a->segment_name);
734  return;
735  }
736  }
737 
738  /*
739  * Setup session
740  */
741  if (VPPCOM_DEBUG > 1)
742  clib_warning ("[%d] client sid %d", vcm->my_pid, session_index);
743 
744  session = pool_elt_at_index (vcm->sessions, session_index);
745  session->is_cut_thru = is_cut_thru;
748 
749  rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
750  rx_fifo->client_session_index = session_index;
751  tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
752  tx_fifo->client_session_index = session_index;
753 
754  session->server_rx_fifo = rx_fifo;
755  session->server_tx_fifo = tx_fifo;
756  session->vpp_session_handle = mp->handle;
757  session->state = STATE_CONNECT;
758 
759  /* Add it to lookup table */
760  hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
762 }
763 
764 static void
765 vppcom_send_connect_sock (session_t * session, u32 session_index)
766 {
767  vppcom_main_t *vcm = &vppcom_main;
769 
770  /* Assumes caller as acquired the spinlock: vcm->sessions_lockp */
771  session->is_server = 0;
772  cmp = vl_msg_api_alloc (sizeof (*cmp));
773  memset (cmp, 0, sizeof (*cmp));
774  cmp->_vl_msg_id = ntohs (VL_API_CONNECT_SOCK);
775  cmp->client_index = vcm->my_client_index;
776  cmp->context = session_index;
777 
778  if (VPPCOM_DEBUG > 1)
779  clib_warning ("[%d] session_index = %d 0x%08x",
780  vcm->my_pid, session_index, session_index);
781 
782  cmp->vrf = session->vrf;
783  cmp->is_ip4 = session->is_ip4;
784  clib_memcpy (cmp->ip, session->ip, sizeof (cmp->ip));
785  cmp->port = session->port;
786  cmp->proto = session->proto;
787  clib_memcpy (cmp->options, session->options, sizeof (cmp->options));
788  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & cmp);
789 }
790 
791 static int
793 {
794  vppcom_main_t *vcm = &vppcom_main;
796  session_t *session = 0;
797  int rv;
798 
800  rv = vppcom_session_at_index (session_index, &session);
801  if (PREDICT_FALSE (rv))
802  {
804  if (VPPCOM_DEBUG > 1)
805  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
806  vcm->my_pid, session_index);
807  return rv;
808  }
809 
810  dmp = vl_msg_api_alloc (sizeof (*dmp));
811  memset (dmp, 0, sizeof (*dmp));
812  dmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION);
813  dmp->client_index = vcm->my_client_index;
814  dmp->handle = session->vpp_session_handle;
816  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & dmp);
817  return VPPCOM_OK;
818 }
819 
820 static void
822 {
823  vppcom_main_t *vcm = &vppcom_main;
824  session_t *session = 0;
825  int rv;
826 
827  if (mp->retval)
828  clib_warning ("[%d] bind failed: %U", vcm->my_pid, format_api_error,
829  ntohl (mp->retval));
830 
831  ASSERT (vcm->bind_session_index != ~0);
832 
834  rv = vppcom_session_at_index (vcm->bind_session_index, &session);
835  if (rv == VPPCOM_OK)
836  {
837  session->vpp_session_handle = mp->handle;
839  vcm->bind_session_index);
840  session->state = mp->retval ? STATE_FAILED : STATE_LISTEN;
841  vcm->bind_session_index = ~0;
842  }
844 }
845 
846 static void
847 vl_api_unbind_sock_reply_t_handler (vl_api_unbind_sock_reply_t * mp)
848 {
849  vppcom_main_t *vcm = &vppcom_main;
850  session_t *session = 0;
851  int rv;
852 
854  rv = vppcom_session_at_index (vcm->bind_session_index, &session);
855  if (rv == VPPCOM_OK)
856  {
857  if ((VPPCOM_DEBUG > 1) && (mp->retval))
858  clib_warning ("[%d] unbind failed: %U", vcm->my_pid, format_api_error,
859  ntohl (mp->retval));
860 
861  vcm->bind_session_index = ~0;
862  session->state = STATE_START;
863  }
865 }
866 
867 u8 *
868 format_ip4_address (u8 * s, va_list * args)
869 {
870  u8 *a = va_arg (*args, u8 *);
871  return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
872 }
873 
874 u8 *
875 format_ip6_address (u8 * s, va_list * args)
876 {
877  ip6_address_t *a = va_arg (*args, ip6_address_t *);
878  u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
879 
880  i_max_n_zero = ARRAY_LEN (a->as_u16);
881  max_n_zeros = 0;
882  i_first_zero = i_max_n_zero;
883  n_zeros = 0;
884  for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
885  {
886  u32 is_zero = a->as_u16[i] == 0;
887  if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
888  {
889  i_first_zero = i;
890  n_zeros = 0;
891  }
892  n_zeros += is_zero;
893  if ((!is_zero && n_zeros > max_n_zeros)
894  || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
895  {
896  i_max_n_zero = i_first_zero;
897  max_n_zeros = n_zeros;
898  i_first_zero = ARRAY_LEN (a->as_u16);
899  n_zeros = 0;
900  }
901  }
902 
903  last_double_colon = 0;
904  for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
905  {
906  if (i == i_max_n_zero && max_n_zeros > 1)
907  {
908  s = format (s, "::");
909  i += max_n_zeros - 1;
910  last_double_colon = 1;
911  }
912  else
913  {
914  s = format (s, "%s%x",
915  (last_double_colon || i == 0) ? "" : ":",
916  clib_net_to_host_u16 (a->as_u16[i]));
917  last_double_colon = 0;
918  }
919  }
920 
921  return s;
922 }
923 
924 /* Format an IP46 address. */
925 u8 *
926 format_ip46_address (u8 * s, va_list * args)
927 {
928  ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
929  ip46_type_t type = va_arg (*args, ip46_type_t);
930  int is_ip4 = 1;
931 
932  switch (type)
933  {
934  case IP46_TYPE_ANY:
935  is_ip4 = ip46_address_is_ip4 (ip46);
936  break;
937  case IP46_TYPE_IP4:
938  is_ip4 = 1;
939  break;
940  case IP46_TYPE_IP6:
941  is_ip4 = 0;
942  break;
943  }
944 
945  return is_ip4 ?
946  format (s, "%U", format_ip4_address, &ip46->ip4) :
947  format (s, "%U", format_ip6_address, &ip46->ip6);
948 }
949 
950 static void
952 {
953  vppcom_main_t *vcm = &vppcom_main;
955  svm_fifo_t *rx_fifo, *tx_fifo;
956  session_t *session;
957  u32 session_index;
958  int rv = 0;
959 
961  {
962  clib_warning ("[%d] client session queue is full!", vcm->my_pid);
963  rv = VNET_API_ERROR_QUEUE_FULL;
964  goto send_reply;
965  }
966 
967  if (VPPCOM_DEBUG > 1)
968  {
969  u8 *ip_str = format (0, "%U", format_ip46_address, &mp->ip, mp->is_ip4);
970  clib_warning ("[%d] accepted session from: %s:%d", vcm->my_pid, ip_str,
971  clib_net_to_host_u16 (mp->port));
972  vec_free (ip_str);
973  }
974 
976  /* Allocate local session and set it up */
977  pool_get (vcm->sessions, session);
978  memset (session, 0, sizeof (*session));
979  session_index = session - vcm->sessions;
980 
981  rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
982  rx_fifo->client_session_index = session_index;
983  tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
984  tx_fifo->client_session_index = session_index;
985 
986  session->server_rx_fifo = rx_fifo;
987  session->server_tx_fifo = tx_fifo;
990  session->state = STATE_ACCEPT;
991  session->is_cut_thru = 0;
992  session->is_server = 1;
993  session->port = ntohs (mp->port);
994  session->is_ip4 = mp->is_ip4;
995  clib_memcpy (session->ip, mp->ip, sizeof (session->ip));
997 
998  /* Add it to lookup table */
999  hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
1000 
1001  clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
1002 
1003  /*
1004  * Send accept reply to vpp
1005  */
1006 send_reply:
1007  rmp = vl_msg_api_alloc (sizeof (*rmp));
1008  memset (rmp, 0, sizeof (*rmp));
1009  rmp->_vl_msg_id = ntohs (VL_API_ACCEPT_SESSION_REPLY);
1010  rmp->retval = htonl (rv);
1011  rmp->handle = mp->handle;
1012  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
1013 }
1014 
1015 /*
1016  * Acting as server for redirected connect requests
1017  */
1018 static void
1020 {
1023  vppcom_main_t *vcm = &vppcom_main;
1024  u32 session_index;
1026  unix_shared_memory_queue_t *client_q;
1028  session_t *session = 0;
1029  int rv = 0;
1030  svm_fifo_t *rx_fifo;
1031  svm_fifo_t *tx_fifo;
1032  unix_shared_memory_queue_t *event_q = 0;
1033 
1035  {
1036  if (VPPCOM_DEBUG > 1)
1037  clib_warning ("[%d] client session queue is full!", vcm->my_pid);
1038  rv = VNET_API_ERROR_QUEUE_FULL;
1039  goto send_reply;
1040  }
1041 
1042  /* Create the segment */
1043  memset (a, 0, sizeof (*a));
1044  a->segment_name = (char *) format ((u8 *) a->segment_name, "%d:segment%d%c",
1045  vcm->my_pid, vcm->unique_segment_index++,
1046  0);
1047  a->segment_size = vcm->cfg.segment_size;
1049  a->rx_fifo_size = vcm->cfg.rx_fifo_size;
1050  a->tx_fifo_size = vcm->cfg.tx_fifo_size;
1051 
1052  rv = svm_fifo_segment_create (a);
1053  if (PREDICT_FALSE (rv))
1054  {
1055  if (VPPCOM_DEBUG > 1)
1056  clib_warning ("[%d] svm_fifo_segment_create ('%s') failed",
1057  vcm->my_pid, a->segment_name);
1059  rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
1060  goto send_reply;
1061  }
1062 
1063  if (VPPCOM_DEBUG > 1)
1064  clib_warning ("[%d] created segment '%s'", vcm->my_pid, a->segment_name);
1065 
1067  pool_get (vcm->sessions, session);
1068  memset (session, 0, sizeof (*session));
1069  session_index = session - vcm->sessions;
1070 
1071  session->sm_seg_index = a->new_segment_indices[0];
1073 
1074  seg = svm_fifo_segment_get_segment (session->sm_seg_index);
1075  rx_fifo = session->server_rx_fifo =
1078  if (PREDICT_FALSE (!session->server_rx_fifo))
1079  {
1081  clib_warning ("[%d] rx fifo alloc failed, size %ld (0x%lx)",
1082  vcm->my_pid, vcm->cfg.rx_fifo_size,
1083  vcm->cfg.rx_fifo_size);
1084  rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
1086  goto send_reply;
1087  }
1088 
1089  tx_fifo = session->server_tx_fifo =
1092  if (PREDICT_FALSE (!session->server_tx_fifo))
1093  {
1095  if (VPPCOM_DEBUG > 1)
1096  clib_warning ("[%d] tx fifo alloc failed, size %ld (0x%lx)",
1097  vcm->my_pid, vcm->cfg.tx_fifo_size,
1098  vcm->cfg.tx_fifo_size);
1099  rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
1101  goto send_reply;
1102  }
1103 
1104  session->server_rx_fifo->master_session_index = session_index;
1105  session->server_tx_fifo->master_session_index = session_index;
1107  session->is_cut_thru = 1;
1108  session->is_server = 1;
1109  session->is_ip4 = mp->is_ip4;
1110  session->port = mp->port;
1111  {
1112  void *oldheap;
1113  ssvm_shared_header_t *sh = seg->ssvm.sh;
1114 
1115  ssvm_lock_non_recursive (sh, 1);
1116  oldheap = ssvm_push_heap (sh);
1117  event_q = session->vpp_event_queue =
1119  sizeof (session_fifo_event_t),
1120  vcm->my_pid, 0 /* signal not sent */ );
1121  ssvm_pop_heap (oldheap);
1123  }
1124  clib_memcpy (session->ip, mp->ip, sizeof (session->ip));
1125 
1126  session->state = STATE_ACCEPT;
1127  if (VPPCOM_DEBUG > 1)
1128  clib_warning ("[%d] Connected cut-thru to client: sid %d",
1129  vcm->my_pid, session_index);
1131  clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
1132 
1133 send_reply:
1134  rmp = vl_msg_api_alloc (sizeof (*rmp));
1135  memset (rmp, 0, sizeof (*rmp));
1136 
1137  rmp->_vl_msg_id = ntohs (VL_API_CONNECT_SESSION_REPLY);
1138  rmp->context = mp->context;
1139  rmp->retval = htonl (rv);
1143 
1144  if (event_q)
1145  {
1146  rmp->vpp_event_queue_address = pointer_to_uword (event_q);
1147  rmp->server_rx_fifo = pointer_to_uword (rx_fifo);
1148  rmp->server_tx_fifo = pointer_to_uword (tx_fifo);
1149  }
1150  client_q =
1152 
1153  ASSERT (client_q);
1154  vl_msg_api_send_shmem (client_q, (u8 *) & rmp);
1155 }
1156 
1157 static void
1159 {
1160  vppcom_main_t *vcm = &vppcom_main;
1161  vl_api_bind_sock_t *bmp;
1162 
1163  /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
1164  session->is_server = 1;
1165  bmp = vl_msg_api_alloc (sizeof (*bmp));
1166  memset (bmp, 0, sizeof (*bmp));
1167 
1168  bmp->_vl_msg_id = ntohs (VL_API_BIND_SOCK);
1169  bmp->client_index = vcm->my_client_index;
1170  bmp->context = htonl (0xfeedface);
1171  bmp->vrf = session->vrf;
1172  bmp->is_ip4 = session->is_ip4;
1173  clib_memcpy (bmp->ip, session->ip, sizeof (bmp->ip));
1174  bmp->port = session->port;
1175  bmp->proto = session->proto;
1176  clib_memcpy (bmp->options, session->options, sizeof (bmp->options));
1177  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
1178 }
1179 
1180 static void
1182 {
1183  vppcom_main_t *vcm = &vppcom_main;
1184  vl_api_unbind_sock_t *ump;
1185  session_t *session = 0;
1186  int rv;
1187 
1189  rv = vppcom_session_at_index (session_index, &session);
1190  if (PREDICT_FALSE (rv))
1191  {
1193  if (VPPCOM_DEBUG > 0)
1194  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
1195  vcm->my_pid, session_index);
1196  return;
1197  }
1198 
1199  ump = vl_msg_api_alloc (sizeof (*ump));
1200  memset (ump, 0, sizeof (*ump));
1201 
1202  ump->_vl_msg_id = ntohs (VL_API_UNBIND_SOCK);
1203  ump->client_index = vcm->my_client_index;
1204  ump->handle = session->vpp_session_handle;
1206  vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & ump);
1207 }
1208 
1209 static int
1211 {
1214  int rv = VPPCOM_OK;
1215 
1216  seg = vec_elt_at_index (sm->segments, session->sm_seg_index);
1222 
1223  return rv;
1224 }
1225 
1226 static int
1228 {
1229  vppcom_main_t *vcm = &vppcom_main;
1230  int rv;
1231 
1233  if (PREDICT_FALSE (pool_is_free_index (vcm->sessions, session_index)))
1234  {
1236  if (VPPCOM_DEBUG > 1)
1237  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
1238  vcm->my_pid, session_index);
1239  return VPPCOM_EBADFD;
1240  }
1242 
1243  vcm->bind_session_index = session_index;
1244  vppcom_send_unbind_sock (session_index);
1246  vcm->cfg.session_timeout);
1247  if (PREDICT_FALSE (rv))
1248  {
1249  vcm->bind_session_index = ~0;
1250  if (VPPCOM_DEBUG > 0)
1251  clib_warning ("[%d] server unbind timed out, rv = %s (%d)",
1252  vcm->my_pid, vppcom_retval_str (rv), rv);
1253  return rv;
1254  }
1255  return VPPCOM_OK;
1256 }
1257 
1258 static int
1260 {
1261  vppcom_main_t *vcm = &vppcom_main;
1262  int rv;
1263 
1264  rv = vppcom_send_disconnect (session_index);
1265  if (PREDICT_FALSE (rv))
1266  return rv;
1267 
1269  vcm->cfg.session_timeout);
1270  if (PREDICT_FALSE (rv))
1271  {
1272  if (VPPCOM_DEBUG > 0)
1273  clib_warning ("[%d] client disconnect timed out, rv = %s (%d)",
1274  vcm->my_pid, vppcom_retval_str (rv), rv);
1275  return rv;
1276  }
1277  return VPPCOM_OK;
1278 }
1279 
1280 #define foreach_sock_msg \
1281 _(SESSION_ENABLE_DISABLE_REPLY, session_enable_disable_reply) \
1282 _(BIND_SOCK_REPLY, bind_sock_reply) \
1283 _(UNBIND_SOCK_REPLY, unbind_sock_reply) \
1284 _(ACCEPT_SESSION, accept_session) \
1285 _(CONNECT_SOCK, connect_sock) \
1286 _(CONNECT_SESSION_REPLY, connect_session_reply) \
1287 _(DISCONNECT_SESSION, disconnect_session) \
1288 _(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \
1289 _(RESET_SESSION, reset_session) \
1290 _(APPLICATION_ATTACH_REPLY, application_attach_reply) \
1291 _(APPLICATION_DETACH_REPLY, application_detach_reply) \
1292 _(MAP_ANOTHER_SEGMENT, map_another_segment)
1293 
1294 static void
1296 {
1297 #define _(N,n) \
1298  vl_msg_api_set_handlers(VL_API_##N, #n, \
1299  vl_api_##n##_t_handler, \
1300  vl_noop_handler, \
1301  vl_api_##n##_t_endian, \
1302  vl_api_##n##_t_print, \
1303  sizeof(vl_api_##n##_t), 1);
1305 #undef _
1306 }
1307 
1308 static void
1310 {
1311  ASSERT (vcl_cfg);
1312 
1313  vcl_cfg->heapsize = (256ULL << 20);
1314  vcl_cfg->segment_baseva = 0x200000000ULL;
1315  vcl_cfg->segment_size = (256 << 20);
1316  vcl_cfg->add_segment_size = (128 << 20);
1317  vcl_cfg->preallocated_fifo_pairs = 8;
1318  vcl_cfg->rx_fifo_size = (1 << 20);
1319  vcl_cfg->tx_fifo_size = (1 << 20);
1320  vcl_cfg->event_queue_size = 2048;
1321  vcl_cfg->listen_queue_size = CLIB_CACHE_LINE_BYTES / sizeof (u32);
1322  vcl_cfg->app_timeout = 10 * 60.0;
1323  vcl_cfg->session_timeout = 10 * 60.0;
1324  vcl_cfg->accept_timeout = 60.0;
1325 }
1326 
1327 static void
1328 vppcom_cfg_heapsize (char *conf_fname)
1329 {
1330  vppcom_main_t *vcm = &vppcom_main;
1331  vppcom_cfg_t *vcl_cfg = &vcm->cfg;
1332  FILE *fp;
1333  char inbuf[4096];
1334  int argc = 1;
1335  char **argv = NULL;
1336  char *arg = NULL;
1337  char *p;
1338  int i;
1339  u8 *sizep;
1340  u32 size;
1341 
1342  fp = fopen (conf_fname, "r");
1343  if (fp == NULL)
1344  {
1345  if (VPPCOM_DEBUG > 0)
1346  fprintf (stderr, "open configuration file '%s' failed\n", conf_fname);
1347  goto defaulted;
1348  }
1349  argv = calloc (1, sizeof (char *));
1350  if (argv == NULL)
1351  goto defaulted;
1352 
1353  while (1)
1354  {
1355  if (fgets (inbuf, 4096, fp) == 0)
1356  break;
1357  p = strtok (inbuf, " \t\n");
1358  while (p != NULL)
1359  {
1360  if (*p == '#')
1361  break;
1362  argc++;
1363  char **tmp = realloc (argv, argc * sizeof (char *));
1364  if (tmp == NULL)
1365  goto defaulted;
1366  argv = tmp;
1367  arg = strndup (p, 1024);
1368  if (arg == NULL)
1369  goto defaulted;
1370  argv[argc - 1] = arg;
1371  p = strtok (NULL, " \t\n");
1372  }
1373  }
1374 
1375  fclose (fp);
1376  fp = NULL;
1377 
1378  char **tmp = realloc (argv, (argc + 1) * sizeof (char *));
1379  if (tmp == NULL)
1380  goto defaulted;
1381  argv = tmp;
1382  argv[argc] = NULL;
1383 
1384  /*
1385  * Look for and parse the "heapsize" config parameter.
1386  * Manual since none of the clib infra has been bootstrapped yet.
1387  *
1388  * Format: heapsize <nn>[mM][gG]
1389  */
1390 
1391  for (i = 1; i < (argc - 1); i++)
1392  {
1393  if (!strncmp (argv[i], "heapsize", 8))
1394  {
1395  sizep = (u8 *) argv[i + 1];
1396  size = 0;
1397  while (*sizep >= '0' && *sizep <= '9')
1398  {
1399  size *= 10;
1400  size += *sizep++ - '0';
1401  }
1402  if (size == 0)
1403  {
1404  if (VPPCOM_DEBUG > 0)
1405  clib_warning ("[%d] parse error '%s %s', "
1406  "using default heapsize %lld (0x%llx)",
1407  vcm->my_pid, argv[i], argv[i + 1],
1408  vcl_cfg->heapsize, vcl_cfg->heapsize);
1409  goto defaulted;
1410  }
1411 
1412  if (*sizep == 'g' || *sizep == 'G')
1413  vcl_cfg->heapsize = size << 30;
1414  else if (*sizep == 'm' || *sizep == 'M')
1415  vcl_cfg->heapsize = size << 20;
1416  else
1417  {
1418  if (VPPCOM_DEBUG > 0)
1419  clib_warning ("[%d] parse error '%s %s', "
1420  "using default heapsize %lld (0x%llx)",
1421  vcm->my_pid, argv[i], argv[i + 1],
1422  vcl_cfg->heapsize, vcl_cfg->heapsize);
1423  goto defaulted;
1424  }
1425  }
1426  }
1427 
1428 defaulted:
1429  if (fp != NULL)
1430  fclose (fp);
1431  if (argv != NULL)
1432  free (argv);
1433  if (!clib_mem_init (0, vcl_cfg->heapsize))
1434  clib_warning ("[%d] vppcom heap allocation failure!", vcm->my_pid);
1435  else if (VPPCOM_DEBUG > 0)
1436  clib_warning ("[%d] allocated vppcom heapsize %lld (0x%llx)",
1437  vcm->my_pid, vcl_cfg->heapsize, vcl_cfg->heapsize);
1438 }
1439 
1440 static void
1441 vppcom_cfg_read (char *conf_fname)
1442 {
1443  vppcom_main_t *vcm = &vppcom_main;
1444  vppcom_cfg_t *vcl_cfg = &vcm->cfg;
1445  int fd;
1446  unformat_input_t _input, *input = &_input;
1447  unformat_input_t _line_input, *line_input = &_line_input;
1448  u8 vc_cfg_input = 0;
1449  u8 *chroot_path;
1450  struct stat s;
1451  u32 uid, gid;
1452 
1453  fd = open (conf_fname, O_RDONLY);
1454  if (fd < 0)
1455  {
1456  if (VPPCOM_DEBUG > 0)
1457  clib_warning ("[%d] open configuration file '%s' failed!",
1458  vcm->my_pid, conf_fname);
1459  goto file_done;
1460  }
1461 
1462  if (fstat (fd, &s) < 0)
1463  {
1464  if (VPPCOM_DEBUG > 0)
1465  clib_warning ("[%d] failed to stat `%s'", vcm->my_pid, conf_fname);
1466  goto file_done;
1467  }
1468 
1469  if (!(S_ISREG (s.st_mode) || S_ISLNK (s.st_mode)))
1470  {
1471  if (VPPCOM_DEBUG > 0)
1472  clib_warning ("[%d] not a regular file `%s'", vcm->my_pid,
1473  conf_fname);
1474  goto file_done;
1475  }
1476 
1477  unformat_init_unix_file (input, fd);
1478 
1479  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1480  {
1481  (void) unformat_user (input, unformat_line_input, line_input);
1482  unformat_skip_white_space (line_input);
1483 
1484  if (unformat (line_input, "vppcom {"))
1485  {
1486  vc_cfg_input = 1;
1487  continue;
1488  }
1489 
1490  if (vc_cfg_input)
1491  {
1492  if (unformat (line_input, "heapsize %s", &chroot_path))
1493  {
1494  vec_terminate_c_string (chroot_path);
1495  if (VPPCOM_DEBUG > 0)
1496  clib_warning ("[%d] configured heapsize %s, "
1497  "actual heapsize %lld (0x%llx)",
1498  vcm->my_pid, chroot_path, vcl_cfg->heapsize,
1499  vcl_cfg->heapsize);
1500  vec_free (chroot_path);
1501  }
1502  else if (unformat (line_input, "api-prefix %s", &chroot_path))
1503  {
1504  vec_terminate_c_string (chroot_path);
1505  vl_set_memory_root_path ((char *) chroot_path);
1506  if (VPPCOM_DEBUG > 0)
1507  clib_warning ("[%d] configured api-prefix %s",
1508  vcm->my_pid, chroot_path);
1509  chroot_path = 0; /* Don't vec_free() it! */
1510  }
1511  else if (unformat (line_input, "uid %d", &uid))
1512  {
1513  vl_set_memory_uid (uid);
1514  if (VPPCOM_DEBUG > 0)
1515  clib_warning ("[%d] configured uid %d", vcm->my_pid, uid);
1516  }
1517  else if (unformat (line_input, "gid %d", &gid))
1518  {
1519  vl_set_memory_gid (gid);
1520  if (VPPCOM_DEBUG > 0)
1521  clib_warning ("[%d] configured gid %d", vcm->my_pid, gid);
1522  }
1523  else if (unformat (line_input, "segment-baseva 0x%llx",
1524  &vcl_cfg->segment_baseva))
1525  {
1526  if (VPPCOM_DEBUG > 0)
1527  clib_warning ("[%d] configured segment_baseva 0x%llx",
1528  vcm->my_pid, vcl_cfg->segment_baseva);
1529  }
1530  else if (unformat (line_input, "segment-size 0x%lx",
1531  &vcl_cfg->segment_size))
1532  {
1533  if (VPPCOM_DEBUG > 0)
1534  clib_warning ("[%d] configured segment_size 0x%lx (%ld)",
1535  vcm->my_pid, vcl_cfg->segment_size,
1536  vcl_cfg->segment_size);
1537  }
1538  else if (unformat (line_input, "segment-size %ld",
1539  &vcl_cfg->segment_size))
1540  {
1541  if (VPPCOM_DEBUG > 0)
1542  clib_warning ("[%d] configured segment_size %ld (0x%lx)",
1543  vcm->my_pid, vcl_cfg->segment_size,
1544  vcl_cfg->segment_size);
1545  }
1546  else if (unformat (line_input, "add-segment-size 0x%lx",
1547  &vcl_cfg->add_segment_size))
1548  {
1549  if (VPPCOM_DEBUG > 0)
1550  clib_warning
1551  ("[%d] configured add_segment_size 0x%lx (%ld)",
1552  vcm->my_pid, vcl_cfg->add_segment_size,
1553  vcl_cfg->add_segment_size);
1554  }
1555  else if (unformat (line_input, "add-segment-size %ld",
1556  &vcl_cfg->add_segment_size))
1557  {
1558  if (VPPCOM_DEBUG > 0)
1559  clib_warning
1560  ("[%d] configured add_segment_size %ld (0x%lx)",
1561  vcm->my_pid, vcl_cfg->add_segment_size,
1562  vcl_cfg->add_segment_size);
1563  }
1564  else if (unformat (line_input, "preallocated-fifo-pairs %d",
1565  &vcl_cfg->preallocated_fifo_pairs))
1566  {
1567  if (VPPCOM_DEBUG > 0)
1568  clib_warning ("[%d] configured preallocated_fifo_pairs "
1569  "%d (0x%x)", vcm->my_pid,
1570  vcl_cfg->preallocated_fifo_pairs,
1571  vcl_cfg->preallocated_fifo_pairs);
1572  }
1573  else if (unformat (line_input, "rx-fifo-size 0x%lx",
1574  &vcl_cfg->rx_fifo_size))
1575  {
1576  if (VPPCOM_DEBUG > 0)
1577  clib_warning ("[%d] configured rx_fifo_size 0x%lx (%ld)",
1578  vcm->my_pid, vcl_cfg->rx_fifo_size,
1579  vcl_cfg->rx_fifo_size);
1580  }
1581  else if (unformat (line_input, "rx-fifo-size %ld",
1582  &vcl_cfg->rx_fifo_size))
1583  {
1584  if (VPPCOM_DEBUG > 0)
1585  clib_warning ("[%d] configured rx_fifo_size %ld (0x%lx)",
1586  vcm->my_pid, vcl_cfg->rx_fifo_size,
1587  vcl_cfg->rx_fifo_size);
1588  }
1589  else if (unformat (line_input, "tx-fifo-size 0x%lx",
1590  &vcl_cfg->tx_fifo_size))
1591  {
1592  if (VPPCOM_DEBUG > 0)
1593  clib_warning ("[%d] configured tx_fifo_size 0x%lx (%ld)",
1594  vcm->my_pid, vcl_cfg->tx_fifo_size,
1595  vcl_cfg->tx_fifo_size);
1596  }
1597  else if (unformat (line_input, "tx-fifo-size %ld",
1598  &vcl_cfg->tx_fifo_size))
1599  {
1600  if (VPPCOM_DEBUG > 0)
1601  clib_warning ("[%d] configured tx_fifo_size %ld (0x%lx)",
1602  vcm->my_pid, vcl_cfg->tx_fifo_size,
1603  vcl_cfg->tx_fifo_size);
1604  }
1605  else if (unformat (line_input, "event-queue-size 0x%lx",
1606  &vcl_cfg->event_queue_size))
1607  {
1608  if (VPPCOM_DEBUG > 0)
1609  clib_warning ("[%d] configured event_queue_size 0x%lx (%ld)",
1610  vcm->my_pid, vcl_cfg->event_queue_size,
1611  vcl_cfg->event_queue_size);
1612  }
1613  else if (unformat (line_input, "event-queue-size %ld",
1614  &vcl_cfg->event_queue_size))
1615  {
1616  if (VPPCOM_DEBUG > 0)
1617  clib_warning ("[%d] configured event_queue_size %ld (0x%lx)",
1618  vcm->my_pid, vcl_cfg->event_queue_size,
1619  vcl_cfg->event_queue_size);
1620  }
1621  else if (unformat (line_input, "listen-queue-size 0x%lx",
1622  &vcl_cfg->listen_queue_size))
1623  {
1624  if (VPPCOM_DEBUG > 0)
1625  clib_warning ("[%d] configured listen_queue_size 0x%lx (%ld)",
1626  vcm->my_pid, vcl_cfg->listen_queue_size,
1627  vcl_cfg->listen_queue_size);
1628  }
1629  else if (unformat (line_input, "listen-queue-size %ld",
1630  &vcl_cfg->listen_queue_size))
1631  {
1632  if (VPPCOM_DEBUG > 0)
1633  clib_warning ("[%d] configured listen_queue_size %ld (0x%lx)",
1634  vcm->my_pid, vcl_cfg->listen_queue_size,
1635  vcl_cfg->listen_queue_size);
1636  }
1637  else if (unformat (line_input, "app-timeout %f",
1638  &vcl_cfg->app_timeout))
1639  {
1640  if (VPPCOM_DEBUG > 0)
1641  clib_warning ("[%d] configured app_timeout %f",
1642  vcm->my_pid, vcl_cfg->app_timeout);
1643  }
1644  else if (unformat (line_input, "session-timeout %f",
1645  &vcl_cfg->session_timeout))
1646  {
1647  if (VPPCOM_DEBUG > 0)
1648  clib_warning ("[%d] configured session_timeout %f",
1649  vcm->my_pid, vcl_cfg->session_timeout);
1650  }
1651  else if (unformat (line_input, "accept-timeout %f",
1652  &vcl_cfg->accept_timeout))
1653  {
1654  if (VPPCOM_DEBUG > 0)
1655  clib_warning ("[%d] configured accept_timeout %f",
1656  vcm->my_pid, vcl_cfg->accept_timeout);
1657  }
1658  else if (unformat (line_input, "}"))
1659  {
1660  vc_cfg_input = 0;
1661  if (VPPCOM_DEBUG > 0)
1662  clib_warning ("[%d] completed parsing vppcom config!",
1663  vcm->my_pid);
1664  goto input_done;
1665  }
1666  else
1667  {
1668  if (line_input->buffer[line_input->index] != '#')
1669  {
1670  clib_warning ("[%d] Unknown vppcom config option: '%s'",
1671  vcm->my_pid, (char *)
1672  &line_input->buffer[line_input->index]);
1673  }
1674  }
1675  }
1676  }
1677 
1678 input_done:
1679  unformat_free (input);
1680 
1681 file_done:
1682  if (fd >= 0)
1683  close (fd);
1684 }
1685 
1686 /*
1687  * VPPCOM Public API functions
1688  */
1689 int
1690 vppcom_app_create (char *app_name)
1691 {
1692  vppcom_main_t *vcm = &vppcom_main;
1693  vppcom_cfg_t *vcl_cfg = &vcm->cfg;
1694  u8 *heap;
1695  mheap_t *h;
1696  int rv;
1697 
1698  if (!vcm->init)
1699  {
1700  char *conf_fname;
1701 
1702  vcm->init = 1;
1703  vcm->my_pid = getpid ();
1705  vcm->cfg.listen_queue_size);
1706  vppcom_cfg_init (vcl_cfg);
1707  conf_fname = getenv (VPPCOM_CONF_ENV);
1708  if (!conf_fname)
1709  {
1710  conf_fname = VPPCOM_CONF_DEFAULT;
1711  if (VPPCOM_DEBUG > 0)
1712  clib_warning ("[%d] getenv '%s' failed!", vcm->my_pid,
1713  VPPCOM_CONF_ENV);
1714  }
1715  vppcom_cfg_heapsize (conf_fname);
1716  vppcom_cfg_read (conf_fname);
1717  vcm->bind_session_index = ~0;
1718  vcm->main_cpu = os_get_thread_index ();
1719  heap = clib_mem_get_per_cpu_heap ();
1720  h = mheap_header (heap);
1721 
1722  /* make the main heap thread-safe */
1724 
1725  vcm->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
1726 
1727  clib_time_init (&vcm->clib_time);
1730  20 /* timeout in secs */ );
1732  vppcom_api_hookup ();
1733  }
1734 
1735  if (vcm->my_client_index == ~0)
1736  {
1737  vcm->app_state = STATE_APP_START;
1738  rv = vppcom_connect_to_vpp (app_name);
1739  if (rv)
1740  {
1741  clib_warning ("[%s] couldn't connect to VPP.", vcm->my_pid);
1742  return rv;
1743  }
1744 
1745  if (VPPCOM_DEBUG > 0)
1746  clib_warning ("[%d] sending session enable", vcm->my_pid);
1747 
1748  rv = vppcom_app_session_enable ();
1749  if (rv)
1750  {
1751  clib_warning ("[%d] vppcom_app_session_enable() failed!",
1752  vcm->my_pid);
1753  return rv;
1754  }
1755 
1756  if (VPPCOM_DEBUG > 0)
1757  clib_warning ("[%d] sending app attach", vcm->my_pid);
1758 
1759  rv = vppcom_app_attach ();
1760  if (rv)
1761  {
1762  clib_warning ("[%d] vppcom_app_attach() failed!", vcm->my_pid);
1763  return rv;
1764  }
1765  }
1766 
1767  if (VPPCOM_DEBUG > 0)
1768  clib_warning ("[%d] app_name '%s', my_client_index %d (0x%x)",
1769  vcm->my_pid, app_name, vcm->my_client_index,
1770  vcm->my_client_index);
1771 
1772  return VPPCOM_OK;
1773 }
1774 
1775 void
1777 {
1778  vppcom_main_t *vcm = &vppcom_main;
1779  int rv;
1780 
1781  if (vcm->my_client_index == ~0)
1782  return;
1783 
1784  if (VPPCOM_DEBUG > 0)
1785  clib_warning ("[%d] detaching from VPP, my_client_index %d (0x%x)",
1786  vcm->my_pid, vcm->my_client_index, vcm->my_client_index);
1787 
1788  vppcom_app_detach ();
1790  if (PREDICT_FALSE (rv))
1791  {
1792  if (VPPCOM_DEBUG > 0)
1793  clib_warning ("[%d] application detach timed out, rv = %s (%d)",
1794  vcm->my_pid, vppcom_retval_str (rv), rv);
1795  }
1797  vcm->my_client_index = ~0;
1798  vcm->app_state = STATE_APP_START;
1799 }
1800 
1801 int
1802 vppcom_session_create (u32 vrf, u8 proto, u8 is_nonblocking)
1803 {
1804  vppcom_main_t *vcm = &vppcom_main;
1805  session_t *session;
1806  u32 session_index;
1807 
1809  pool_get (vcm->sessions, session);
1810  session_index = session - vcm->sessions;
1811 
1812  session->vrf = vrf;
1813  session->proto = proto;
1814  session->state = STATE_START;
1815  session->is_nonblocking = is_nonblocking;
1817 
1818  if (VPPCOM_DEBUG > 0)
1819  clib_warning ("[%d] sid %d", vcm->my_pid, session_index);
1820 
1821  return (int) session_index;
1822 }
1823 
1824 int
1825 vppcom_session_close (uint32_t session_index)
1826 {
1827  vppcom_main_t *vcm = &vppcom_main;
1828  session_t *session = 0;
1829  int rv;
1830 
1832  rv = vppcom_session_at_index (session_index, &session);
1833  if (PREDICT_FALSE (rv))
1834  {
1836  if (VPPCOM_DEBUG > 0)
1837  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
1838  vcm->my_pid, session_index);
1839  return rv;
1840  }
1842 
1843  if (VPPCOM_DEBUG > 0)
1844  clib_warning ("[%d] sid %d", vcm->my_pid, session_index);
1845 
1846  if (session->is_cut_thru)
1847  {
1848  if (session->is_server)
1849  {
1850  rv = vppcom_session_unbind_cut_thru (session);
1851  if ((VPPCOM_DEBUG > 0) && (rv < 0))
1852  clib_warning ("[%d] unbind cut-thru (session %d) failed, "
1853  "rv = %s (%d)",
1854  vcm->my_pid, session_index,
1855  vppcom_retval_str (rv), rv);
1856  }
1857  }
1858  else if (session->is_server)
1859  {
1860  rv = vppcom_session_unbind (session_index);
1861  if ((VPPCOM_DEBUG > 0) && (rv < 0))
1862  clib_warning ("[%d] unbind (session %d) failed, rv = %s (%d)",
1863  vcm->my_pid, session_index, vppcom_retval_str (rv), rv);
1864  }
1865  else
1866  {
1867  rv = vppcom_session_disconnect (session_index);
1868  if ((VPPCOM_DEBUG > 0) && (rv < 0))
1869  clib_warning ("[%d] disconnect (session %d) failed, rv = %s (%d)",
1870  vcm->my_pid, session_index, vppcom_retval_str (rv), rv);
1871  }
1872  if (rv < 0)
1873  return rv;
1874 
1876  pool_put_index (vcm->sessions, session_index);
1878  return rv;
1879 }
1880 
1881 int
1882 vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep)
1883 {
1884  vppcom_main_t *vcm = &vppcom_main;
1885  session_t *session = 0;
1886  int rv;
1887  ip46_address_t *ip46;
1888 
1889  if (!ep || !ep->ip)
1890  return VPPCOM_EINVAL;
1891 
1893  rv = vppcom_session_at_index (session_index, &session);
1894  if (PREDICT_FALSE (rv))
1895  {
1897  if (VPPCOM_DEBUG > 0)
1898  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
1899  vcm->my_pid, session_index);
1900  return rv;
1901  }
1902 
1903  if (VPPCOM_DEBUG > 0)
1904  clib_warning ("[%d] sid %d", vcm->my_pid, session_index);
1905 
1906  session->vrf = ep->vrf;
1907  session->is_ip4 = ep->is_ip4;
1908  memset (session->ip, 0, sizeof (session->ip));
1909  ip46 = (ip46_address_t *) session->ip;
1910  *ip46 = to_ip46 (!ep->is_ip4, ep->ip);
1911  session->port = ep->port;
1912 
1914  return VPPCOM_OK;
1915 }
1916 
1917 int
1918 vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len)
1919 {
1920  vppcom_main_t *vcm = &vppcom_main;
1921  session_t *listen_session = 0;
1922  int rv;
1923 
1925  rv = vppcom_session_at_index (listen_session_index, &listen_session);
1926  if (PREDICT_FALSE (rv))
1927  {
1929  if (VPPCOM_DEBUG > 0)
1930  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
1931  vcm->my_pid, listen_session_index);
1932  return rv;
1933  }
1934 
1935  if (VPPCOM_DEBUG > 0)
1936  clib_warning ("[%d] sid %d", vcm->my_pid, listen_session_index);
1937 
1938  ASSERT (vcm->bind_session_index == ~0);
1939  vcm->bind_session_index = listen_session_index;
1940  vppcom_send_bind_sock (listen_session);
1942  rv =
1943  vppcom_wait_for_session_state_change (listen_session_index, STATE_LISTEN,
1944  vcm->cfg.session_timeout);
1945  if (PREDICT_FALSE (rv))
1946  {
1947  vcm->bind_session_index = ~0;
1948  if (VPPCOM_DEBUG > 0)
1949  clib_warning ("[%d] server listen timed out, rv = %d (%d)",
1950  vcm->my_pid, vppcom_retval_str (rv), rv);
1951  return rv;
1952  }
1953 
1955  rv = vppcom_session_at_index (listen_session_index, &listen_session);
1956  if (PREDICT_FALSE (rv))
1957  {
1959  if (VPPCOM_DEBUG > 0)
1960  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
1961  vcm->my_pid, listen_session_index);
1962  return rv;
1963  }
1964  listen_session->is_listen = 1;
1967 
1968  return VPPCOM_OK;
1969 }
1970 
1971 int
1972 vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep,
1973  double wait_for_time)
1974 {
1975  vppcom_main_t *vcm = &vppcom_main;
1976  session_t *listen_session = 0;
1977  session_t *client_session = 0;
1978  u32 client_session_index;
1979  int rv;
1980  f64 wait_for;
1981 
1983  rv = vppcom_session_at_index (listen_session_index, &listen_session);
1984  if (PREDICT_FALSE (rv))
1985  {
1987  if (VPPCOM_DEBUG > 0)
1988  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
1989  vcm->my_pid, listen_session_index);
1990  return rv;
1991  }
1992 
1993  if (listen_session->state != STATE_LISTEN)
1994  {
1996  if (VPPCOM_DEBUG > 0)
1997  clib_warning ("[%d] session not in listen state, state = %s",
1998  vcm->my_pid,
1999  vppcom_session_state_str (listen_session->state));
2000  return VPPCOM_EBADFD;
2001  }
2002  wait_for = listen_session->is_nonblocking ? 0 :
2003  (wait_for_time < 0) ? vcm->cfg.accept_timeout : wait_for_time;
2004 
2005  if (VPPCOM_DEBUG > 0)
2006  clib_warning ("[%d] sid %d: %s (%d)", vcm->my_pid,
2007  listen_session_index,
2008  vppcom_session_state_str (listen_session->state),
2009  listen_session->state);
2011 
2012  while (1)
2013  {
2014  rv = vppcom_wait_for_client_session_index (wait_for);
2015  if (rv)
2016  {
2017  if ((VPPCOM_DEBUG > 0))
2018  clib_warning ("[%d] sid %d, accept timed out, rv = %s (%d)",
2019  vcm->my_pid, listen_session_index,
2020  vppcom_retval_str (rv), rv);
2021  if ((wait_for == 0) || (wait_for_time > 0))
2022  return rv;
2023  }
2024  else
2025  break;
2026  }
2027 
2028  clib_fifo_sub1 (vcm->client_session_index_fifo, client_session_index);
2029 
2031  rv = vppcom_session_at_index (client_session_index, &client_session);
2032  ASSERT (rv == VPPCOM_OK);
2033  ASSERT (client_session->is_ip4 == listen_session->is_ip4);
2034 
2035  if (VPPCOM_DEBUG > 0)
2036  clib_warning ("[%d] Got a request: client sid %d", vcm->my_pid,
2037  client_session_index);
2038 
2039  ep->vrf = client_session->vrf;
2040  ep->is_cut_thru = client_session->is_cut_thru;
2041  ep->is_ip4 = client_session->is_ip4;
2042  ep->port = client_session->port;
2043  if (client_session->is_ip4)
2044  clib_memcpy (ep->ip, client_session->ip, sizeof (ip4_address_t));
2045  else
2046  clib_memcpy (ep->ip, client_session->ip, sizeof (ip6_address_t));
2048  return (int) client_session_index;
2049 }
2050 
2051 int
2052 vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep)
2053 {
2054  vppcom_main_t *vcm = &vppcom_main;
2055  session_t *session = 0;
2056  int rv;
2057  ip46_address_t *ip46;
2058 
2060  rv = vppcom_session_at_index (session_index, &session);
2061  if (PREDICT_FALSE (rv))
2062  {
2064  if (VPPCOM_DEBUG > 0)
2065  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
2066  vcm->my_pid, session_index);
2067  return rv;
2068  }
2069 
2070  if (session->state == STATE_CONNECT)
2071  {
2073  if (VPPCOM_DEBUG > 0)
2074  clib_warning ("[%d] session, sid (%d) already connected!",
2075  vcm->my_pid, session_index);
2076  return VPPCOM_OK;
2077  }
2078 
2079  session->vrf = server_ep->vrf;
2080  session->is_ip4 = server_ep->is_ip4;
2081  memset (session->ip, 0, sizeof (session->ip));
2082  ip46 = (ip46_address_t *) session->ip;
2083  *ip46 = to_ip46 (!server_ep->is_ip4, server_ep->ip);
2084  session->port = server_ep->port;
2085 
2086  if (VPPCOM_DEBUG > 0)
2087  {
2088  u8 *ip_str = format (0, "%U", format_ip46_address,
2089  &session->ip, session->is_ip4);
2090  clib_warning ("[%d] connect sid %d to %s server port %d",
2091  vcm->my_pid, session_index, ip_str,
2092  clib_net_to_host_u16 (session->port));
2093  vec_free (ip_str);
2094  }
2095 
2096  vppcom_send_connect_sock (session, session_index);
2099  vcm->cfg.session_timeout);
2100  if (PREDICT_FALSE (rv))
2101  {
2102  if (VPPCOM_DEBUG > 0)
2103  clib_warning ("[%d] connect timed out, rv = %s (%d)",
2104  vcm->my_pid, vppcom_retval_str (rv), rv);
2105  return rv;
2106  }
2107  return VPPCOM_OK;
2108 }
2109 
2110 int
2111 vppcom_session_read (uint32_t session_index, void *buf, int n)
2112 {
2113  vppcom_main_t *vcm = &vppcom_main;
2114  session_t *session = 0;
2115  svm_fifo_t *rx_fifo;
2116  int n_read = 0;
2117  int rv;
2118  int max_dequeue;
2119  char *fifo_str;
2120 
2121  ASSERT (buf);
2122 
2124  rv = vppcom_session_at_index (session_index, &session);
2125  if (PREDICT_FALSE (rv))
2126  {
2128  if (VPPCOM_DEBUG > 0)
2129  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
2130  vcm->my_pid, session_index);
2131  return rv;
2132  }
2133 
2134  if (session->state == STATE_DISCONNECT)
2135  {
2137  if (VPPCOM_DEBUG > 0)
2138  clib_warning ("[%d] sid (%d) has been closed by remote peer!",
2139  vcm->my_pid, session_index);
2140  return VPPCOM_ECONNRESET;
2141  }
2142 
2143  rx_fifo = ((!session->is_cut_thru || session->is_server) ?
2144  session->server_rx_fifo : session->server_tx_fifo);
2145  fifo_str = ((!session->is_cut_thru || session->is_server) ?
2146  "server_rx_fifo" : "server_tx_fifo");
2148 
2149  max_dequeue = (int) svm_fifo_max_dequeue (rx_fifo);
2150  n_read = svm_fifo_dequeue_nowait (rx_fifo, clib_min (n, max_dequeue), buf);
2151 
2152  if (VPPCOM_DEBUG > 2)
2153  clib_warning ("[%d] sid %d, read %d bytes from %s (%p)", vcm->my_pid,
2154  session_index, n_read, fifo_str, rx_fifo);
2155 
2156  return (n_read <= 0) ? VPPCOM_EAGAIN : n_read;
2157 }
2158 
2159 static inline int
2160 vppcom_session_read_ready (session_t * session, u32 session_index)
2161 {
2162  vppcom_main_t *vcm = &vppcom_main;
2163  svm_fifo_t *rx_fifo;
2164  int ready = 0;
2165 
2166  /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
2167  if (session->state == STATE_DISCONNECT)
2168  {
2169  if (VPPCOM_DEBUG > 0)
2170  clib_warning ("[%d] sid (%d) has been closed by remote peer!",
2171  vcm->my_pid, session_index);
2172  return VPPCOM_ECONNRESET;
2173  }
2174 
2175  if (session->is_listen)
2177  else
2178  {
2179  rx_fifo = ((!session->is_cut_thru || session->is_server) ?
2180  session->server_rx_fifo : session->server_tx_fifo);
2181 
2182  ready = svm_fifo_max_dequeue (rx_fifo);
2183  }
2184 
2185  if (VPPCOM_DEBUG > 3)
2186  clib_warning ("[%d] sid %d, peek %s (%p), ready = %d", vcm->my_pid,
2187  session_index,
2188  session->is_server ? "server_rx_fifo" : "server_tx_fifo",
2189  rx_fifo, ready);
2190  return ready;
2191 }
2192 
2193 int
2194 vppcom_session_write (uint32_t session_index, void *buf, int n)
2195 {
2196  vppcom_main_t *vcm = &vppcom_main;
2197  session_t *session = 0;
2198  svm_fifo_t *tx_fifo;
2200  session_fifo_event_t evt;
2201  int rv;
2202  char *fifo_str;
2203  u8 is_nonblocking;
2204 
2205  ASSERT (buf);
2206 
2208  rv = vppcom_session_at_index (session_index, &session);
2209  if (PREDICT_FALSE (rv))
2210  {
2212  if (VPPCOM_DEBUG > 0)
2213  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
2214  vcm->my_pid, session_index);
2215  return rv;
2216  }
2217 
2218  if (session->state == STATE_DISCONNECT)
2219  {
2221  if (VPPCOM_DEBUG > 0)
2222  clib_warning ("[%d] sid (%d) has been closed by remote peer!",
2223  vcm->my_pid, session_index);
2224  return VPPCOM_ECONNRESET;
2225  }
2226 
2227  tx_fifo = ((!session->is_cut_thru || session->is_server) ?
2228  session->server_tx_fifo : session->server_rx_fifo);
2229  fifo_str = ((!session->is_cut_thru || session->is_server) ?
2230  "server_tx_fifo" : "server_rx_fifo");
2231 
2232  is_nonblocking = session->is_nonblocking;
2234 
2235  do
2236  {
2237  rv = svm_fifo_enqueue_nowait (tx_fifo, n, buf);
2238  }
2239  while (!is_nonblocking && (rv <= 0));
2240 
2241  /* If event wasn't set, add one */
2242  if (!session->is_cut_thru && (rv > 0) && svm_fifo_set_event (tx_fifo))
2243  {
2244  int rval;
2245 
2246  /* Fabricate TX event, send to vpp */
2247  evt.fifo = tx_fifo;
2248  evt.event_type = FIFO_EVENT_APP_TX;
2249  evt.event_id = vcm->tx_event_id++;
2250 
2252  rval = vppcom_session_at_index (session_index, &session);
2253  if (PREDICT_FALSE (rval))
2254  {
2256  if (VPPCOM_DEBUG > 1)
2257  clib_warning ("[%d] invalid session, sid (%d) has been closed!",
2258  vcm->my_pid, session_index);
2259  return rval;
2260  }
2261  q = session->vpp_event_queue;
2263  ASSERT (q);
2264  unix_shared_memory_queue_add (q, (u8 *) & evt,
2265  0 /* do wait for mutex */ );
2266  }
2267 
2268  if (VPPCOM_DEBUG > 2)
2269  clib_warning ("[%d] sid %d, wrote %d bytes to %s (%p)", vcm->my_pid,
2270  session_index, rv, fifo_str, tx_fifo);
2271 
2272  return rv;
2273 }
2274 
2275 static inline int
2276 vppcom_session_write_ready (session_t * session, u32 session_index)
2277 {
2278  vppcom_main_t *vcm = &vppcom_main;
2279  svm_fifo_t *tx_fifo;
2280  char *fifo_str;
2281  int rv;
2282 
2283  /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
2284  if (session->state == STATE_DISCONNECT)
2285  {
2286  if (VPPCOM_DEBUG > 0)
2287  clib_warning ("[%d] sid (%d) has been closed by remote peer!",
2288  vcm->my_pid, session_index);
2289  return VPPCOM_ECONNRESET;
2290  }
2291 
2292  tx_fifo = ((!session->is_cut_thru || session->is_server) ?
2293  session->server_tx_fifo : session->server_rx_fifo);
2294  fifo_str = ((!session->is_cut_thru || session->is_server) ?
2295  "server_tx_fifo" : "server_rx_fifo");
2296 
2297  rv = svm_fifo_max_enqueue (tx_fifo);
2298 
2299  if (VPPCOM_DEBUG > 3)
2300  clib_warning ("[%d] sid %d, peek %s (%p), ready = %d", vcm->my_pid,
2301  session_index, fifo_str, tx_fifo, rv);
2302  return rv;
2303 }
2304 
2305 int
2306 vppcom_select (unsigned long n_bits, unsigned long *read_map,
2307  unsigned long *write_map, unsigned long *except_map,
2308  double time_to_wait)
2309 {
2310  vppcom_main_t *vcm = &vppcom_main;
2311  u32 session_index;
2312  session_t *session = 0;
2313  int rv, bits_set = 0;
2314  f64 timeout = clib_time_now (&vcm->clib_time) + time_to_wait;
2315  u32 minbits = clib_max (n_bits, BITS (uword));
2316 
2317  ASSERT (sizeof (clib_bitmap_t) == sizeof (long int));
2318 
2319  if (read_map)
2320  {
2321  clib_bitmap_validate (vcm->rd_bitmap, minbits);
2322  clib_memcpy (vcm->rd_bitmap, read_map, vec_len (vcm->rd_bitmap));
2323  memset (read_map, 0, vec_len (vcm->rd_bitmap));
2324  }
2325  if (write_map)
2326  {
2327  clib_bitmap_validate (vcm->wr_bitmap, minbits);
2328  clib_memcpy (vcm->wr_bitmap, write_map, vec_len (vcm->wr_bitmap));
2329  memset (write_map, 0, vec_len (vcm->wr_bitmap));
2330  }
2331  if (except_map)
2332  {
2333  clib_bitmap_validate (vcm->ex_bitmap, minbits);
2334  clib_memcpy (vcm->ex_bitmap, except_map, vec_len (vcm->ex_bitmap));
2335  memset (except_map, 0, vec_len (vcm->ex_bitmap));
2336  }
2337 
2338  do
2339  {
2340  /* *INDENT-OFF* */
2341  clib_bitmap_foreach (session_index, vcm->rd_bitmap,
2342  ({
2343  clib_spinlock_lock (&vcm->sessions_lockp);
2344  rv = vppcom_session_at_index (session_index, &session);
2345  if (rv < 0)
2346  {
2347  clib_spinlock_unlock (&vcm->sessions_lockp);
2348  if (VPPCOM_DEBUG > 1)
2349  clib_warning ("[%d] session %d specified in "
2350  "read_map is closed.", vcm->my_pid,
2351  session_index);
2352  bits_set = VPPCOM_EBADFD;
2353  goto select_done;
2354  }
2355 
2356  rv = vppcom_session_read_ready (session, session_index);
2358  if (vcm->ex_bitmap &&
2359  clib_bitmap_get (vcm->ex_bitmap, session_index) && (rv < 0))
2360  {
2361  // TBD: clib_warning
2362  /* coverity[FORWARD_NULL] */
2363  clib_bitmap_set_no_check (except_map, session_index, 1);
2364  bits_set++;
2365  }
2366  else if (rv > 0)
2367  {
2368  // TBD: clib_warning
2369  /* coverity[FORWARD_NULL] */
2370  clib_bitmap_set_no_check (read_map, session_index, 1);
2371  bits_set++;
2372  }
2373  }));
2374 
2375  clib_bitmap_foreach (session_index, vcm->wr_bitmap,
2376  ({
2377  clib_spinlock_lock (&vcm->sessions_lockp);
2378  rv = vppcom_session_at_index (session_index, &session);
2379  if (rv < 0)
2380  {
2381  clib_spinlock_unlock (&vcm->sessions_lockp);
2382  if (VPPCOM_DEBUG > 0)
2383  clib_warning ("[%d] session %d specified in "
2384  "write_map is closed.", vcm->my_pid,
2385  session_index);
2386  bits_set = VPPCOM_EBADFD;
2387  goto select_done;
2388  }
2389 
2390  rv = vppcom_session_write_ready (session, session_index);
2392  if (rv > 0 )
2393  {
2394  // TBD: clib_warning
2395  /* coverity[FORWARD_NULL] */
2396  clib_bitmap_set_no_check (write_map, session_index, 1);
2397  bits_set++;
2398  }
2399  }));
2400 
2401  clib_bitmap_foreach (session_index, vcm->ex_bitmap,
2402  ({
2403  clib_spinlock_lock (&vcm->sessions_lockp);
2404  rv = vppcom_session_at_index (session_index, &session);
2405  if (rv < 0)
2406  {
2407  clib_spinlock_unlock (&vcm->sessions_lockp);
2408  if (VPPCOM_DEBUG > 1)
2409  clib_warning ("[%d] session %d specified in "
2410  "except_map is closed.", vcm->my_pid,
2411  session_index);
2412  bits_set = VPPCOM_EBADFD;
2413  goto select_done;
2414  }
2415 
2416  rv = vppcom_session_read_ready (session, session_index);
2417  clib_spinlock_unlock (&vcm->sessions_lockp);
2418  if (rv < 0)
2419  {
2420  // TBD: clib_warning
2421  /* coverity[FORWARD_NULL] */
2422  clib_bitmap_set_no_check (except_map, session_index, 1);
2423  bits_set++;
2424  }
2425  }));
2426  /* *INDENT-ON* */
2427  }
2428  while (clib_time_now (&vcm->clib_time) < timeout);
2429 
2430 select_done:
2431  return (bits_set);
2432 }
2433 
2434 /*
2435  * fd.io coding-style-patch-verification: ON
2436  *
2437  * Local Variables:
2438  * eval: (c-set-style "gnu")
2439  * End:
2440  */
static int vppcom_app_session_enable(void)
Definition: vppcom.c:395
static void vl_api_connect_sock_t_handler(vl_api_connect_sock_t *mp)
Definition: vppcom.c:1019
u64 heapsize
Definition: vppcom.c:97
u32 * client_session_index_fifo
Definition: vppcom.c:114
#define hash_set(h, key, value)
Definition: hash.h:254
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
int vppcom_app_create(char *app_name)
Definition: vppcom.c:1690
#define clib_min(x, y)
Definition: clib.h:332
uint8_t * ip
Definition: vppcom.h:47
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:72
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:50
ip46_type_t
Definition: format.h:63
vpp->client reset session API
Definition: session.api:186
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
clib_bitmap_t * wr_bitmap
Definition: vppcom.c:134
static uword clib_fifo_elts(void *v)
Definition: fifo.h:66
static int vppcom_app_attach(void)
Definition: vppcom.c:451
int vppcom_session_create(u32 vrf, u8 proto, u8 is_nonblocking)
Definition: vppcom.c:1802
void vl_set_memory_gid(int gid)
u32 segment_size
Definition: vppcom.c:99
int vppcom_session_bind(uint32_t session_index, vppcom_endpt_t *ep)
Definition: vppcom.c:1882
pid_t my_pid
Definition: vppcom.c:143
u32 add_segment_size
Definition: vppcom.c:100
static void vppcom_send_unbind_sock(u32 session_index)
Definition: vppcom.c:1181
unix_shared_memory_queue_t * vl_input_queue
Definition: api_common.h:68
int my_client_index
All VLIB-side message handlers use my_client_index to identify the queue / client.
Definition: api_common.h:286
#define NULL
Definition: clib.h:55
u64 client_queue_address
Definition: vppcom.c:91
u64 options[16]
Definition: vppcom.c:92
static f64 clib_time_now(clib_time_t *c)
Definition: time.h:202
static void vppcom_send_bind_sock(session_t *session)
Definition: vppcom.c:1158
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
Definition: vec.h:990
Bind to an ip:port pair for a given transport protocol.
Definition: session.api:216
client->vpp, reply to an accept message
Definition: session.api:148
volatile u32 bind_session_index
Definition: vppcom.c:115
static u8 * format_api_error(u8 *s, va_list *args)
Definition: vppcom.c:274
static mheap_t * mheap_header(u8 *v)
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
f64 app_timeout
Definition: vppcom.c:106
static u32 svm_fifo_max_enqueue(svm_fifo_t *f)
Definition: svm_fifo.h:106
ssvm_shared_header_t * sh
Definition: ssvm.h:76
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static void vl_api_disconnect_session_reply_t_handler(vl_api_disconnect_session_reply_t *mp)
Definition: vppcom.c:541
#define VPPCOM_CONF_DEFAULT
Definition: vppcom.h:28
#define MHEAP_FLAG_THREAD_SAFE
static void vl_api_reset_session_t_handler(vl_api_reset_session_t *mp)
Definition: vppcom.c:644
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:225
u32 rx_fifo_size
Definition: vppcom.c:102
u64 segment_baseva
Definition: vppcom.c:98
svm_fifo_t * server_rx_fifo
int vppcom_session_connect(uint32_t session_index, vppcom_endpt_t *server_ep)
Definition: vppcom.c:2052
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
svm_fifo_segment_main_t svm_fifo_segment_main
struct _svm_fifo svm_fifo_t
static uword clib_bitmap_set_no_check(uword *a, uword i, uword new_value)
Sets the ith bit of a bitmap to new_value.
Definition: bitmap.h:141
#define clib_bitmap_validate(v, n_bits)
Definition: bitmap.h:115
u8 is_nonblocking
Definition: vppcom.c:85
struct vppcom_cfg_t_ vppcom_cfg_t
int main_cpu
Definition: vppcom.c:117
void vl_set_memory_uid(int uid)
static int vppcom_wait_for_session_state_change(u32 session_index, session_state_t state, f64 wait_for_time)
Definition: vppcom.c:321
unix_shared_memory_queue_t * vpp_event_queue
Definition: vppcom.c:79
#define VPPCOM_CONF_ENV
Definition: vppcom.h:27
u8 is_ip4
Definition: vppcom.c:87
u32 sm_seg_index
Definition: vppcom.c:77
#define VPPCOM_DEBUG
Definition: vppcom.c:45
static u32 svm_fifo_max_dequeue(svm_fifo_t *f)
Definition: svm_fifo.h:100
static uword clib_fifo_free_elts(void *v)
Definition: fifo.h:82
u16 port
Definition: vppcom.c:89
u8 is_cut_thru
Definition: vppcom.c:84
vpp/server->client, connect reply – used for all connect_* messages
Definition: session.api:303
int i32
Definition: types.h:81
int vl_client_connect_to_vlib(const char *svm_name, const char *client_name, int rx_queue_size)
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static void * ssvm_push_heap(ssvm_shared_header_t *sh)
Definition: ssvm.h:134
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
Definition: api_common.h:241
int vppcom_session_accept(uint32_t listen_session_index, vppcom_endpt_t *ep, double wait_for_time)
Definition: vppcom.c:1972
static void vl_api_unbind_sock_reply_t_handler(vl_api_unbind_sock_reply_t *mp)
Definition: vppcom.c:847
static void ssvm_pop_heap(void *oldheap)
Definition: ssvm.h:142
static uword pointer_to_uword(const void *p)
Definition: types.h:131
void * vl_msg_api_alloc(int nbytes)
void vppcom_app_destroy(void)
Definition: vppcom.c:1776
unformat_function_t unformat_line_input
Definition: format.h:281
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:33
int unix_shared_memory_queue_add(unix_shared_memory_queue_t *q, u8 *elem, int nowait)
clib_time_t clib_time
Definition: vppcom.c:146
static void vl_api_connect_session_reply_t_handler(vl_api_connect_session_reply_t *mp)
Definition: vppcom.c:685
#define hash_get(h, key)
Definition: hash.h:248
#define clib_bitmap_foreach(i, ai, body)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:458
static void vppcom_send_session_enable_disable(u8 is_enable)
Definition: vppcom.c:380
#define clib_fifo_sub1(f, e)
Definition: fifo.h:224
int vppcom_session_listen(uint32_t listen_session_index, uint32_t q_len)
Definition: vppcom.c:1918
static const char * vppcom_retval_str(int retval)
Definition: vppcom.h:67
client->vpp, attach application to session layer
Definition: session.api:23
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:270
static void * clib_mem_get_per_cpu_heap(void)
Definition: mem.h:58
static void vl_api_application_attach_reply_t_handler(vl_api_application_attach_reply_t *mp)
Definition: vppcom.c:483
u32 listen_queue_size
Definition: vppcom.c:105
void svm_fifo_segment_init(u64 baseva, u32 timeout_in_seconds)
#define PREDICT_FALSE(x)
Definition: clib.h:97
uint8_t is_ip4
Definition: vppcom.h:46
struct vppcom_main_t_ vppcom_main_t
u8 is_server
Definition: vppcom.c:82
vppcom_main_t vppcom_main
Definition: vppcom.c:157
void clib_time_init(clib_time_t *c)
Definition: time.c:175
static int vppcom_session_unbind_cut_thru(session_t *session)
Definition: vppcom.c:1210
vpp->client, accept this session
Definition: session.api:128
uword * session_index_by_vpp_handles
Definition: vppcom.c:130
#define uword_to_pointer(u, type)
Definition: types.h:136
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:182
static void vppcom_app_detach(void)
Definition: vppcom.c:469
#define ip46_address_is_ip4(ip46)
Definition: ip6_packet.h:76
void * clib_mem_init(void *heap, uword size)
Definition: mem_mheap.c:60
static int vppcom_send_disconnect(u32 session_index)
Definition: vppcom.c:792
static u8 svm_fifo_set_event(svm_fifo_t *f)
Sets fifo event flag.
Definition: svm_fifo.h:123
api_main_t api_main
Definition: api_shared.c:35
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
#define foreach_sock_msg
Definition: vppcom.c:1280
static void vl_api_map_another_segment_t_handler(vl_api_map_another_segment_t *mp)
Definition: vppcom.c:577
vec_header_t h
Definition: buffer.c:282
int vppcom_select(unsigned long n_bits, unsigned long *read_map, unsigned long *write_map, unsigned long *except_map, double time_to_wait)
Definition: vppcom.c:2306
clib_bitmap_t * rd_bitmap
Definition: vppcom.c:133
volatile session_state_t state
Definition: vppcom.c:73
session_state_t
Definition: vppcom.c:61
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
u32 vrf
Definition: vppcom.c:86
#define clib_warning(format, args...)
Definition: error.h:59
#define clib_memcpy(a, b, c)
Definition: string.h:69
clib_bitmap_t * ex_bitmap
Definition: vppcom.c:135
session_t * sessions
Definition: vppcom.c:127
static void vl_api_disconnect_session_t_handler(vl_api_disconnect_session_t *mp)
Definition: vppcom.c:602
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:267
static void vppcom_app_send_attach(void)
Definition: vppcom.c:431
static void vppcom_api_hookup(void)
Definition: vppcom.c:1295
static const char * vppcom_session_state_str(session_state_t state)
Definition: vppcom.c:191
#define ARRAY_LEN(x)
Definition: clib.h:59
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
int svm_fifo_enqueue_nowait(svm_fifo_t *f, u32 max_bytes, u8 *copy_from_here)
Definition: svm_fifo.c:533
svm_fifo_t * server_tx_fifo
static int vppcom_connect_to_vpp(char *app_name)
Definition: vppcom.c:250
Application attach reply.
Definition: session.api:39
static svm_fifo_segment_private_t * svm_fifo_segment_get_segment(u32 segment_index)
f64 accept_timeout
Definition: vppcom.c:108
#define foreach_vnet_api_error
Definition: api_errno.h:18
#define hash_create(elts, value_bytes)
Definition: hash.h:658
static ip46_address_t to_ip46(u32 is_ipv6, u8 *buf)
Definition: ip6_packet.h:86
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:293
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
enable/disable session layer
Definition: session.api:321
static int vppcom_session_unbind(u32 session_index)
Definition: vppcom.c:1227
static void vppcom_cfg_read(char *conf_fname)
Definition: vppcom.c:1441
static int vppcom_session_read_ready(session_t *session, u32 session_index)
Definition: vppcom.c:2160
client->vpp, attach application to session layer
Definition: session.api:52
unix_shared_memory_queue_t * unix_shared_memory_queue_init(int nels, int elsize, int consumer_pid, int signal_when_queue_non_empty)
unix_shared_memory_queue_t * app_event_queue
Definition: vppcom.c:138
vhost_vring_state_t state
Definition: vhost-user.h:82
u64 size
Definition: vhost-user.h:76
vpp->client, please map an additional shared memory segment
Definition: session.api:62
static void vppcom_send_connect_sock(session_t *session, u32 session_index)
Definition: vppcom.c:765
u8 ip[16]
Definition: vppcom.c:88
uint16_t port
Definition: vppcom.h:48
u32 unique_segment_index
Definition: vppcom.c:141
Connect to a remote peer.
Definition: session.api:251
void svm_fifo_segment_free_fifo(svm_fifo_segment_private_t *s, svm_fifo_t *f, svm_fifo_segment_freelist_t list_index)
clib_spinlock_t sessions_lockp
Definition: vppcom.c:126
u8 is_listen
Definition: vppcom.c:83
#define clib_max(x, y)
Definition: clib.h:325
int svm_fifo_segment_create(svm_fifo_segment_create_args_t *a)
(master) create an svm fifo segment
u64 uword
Definition: types.h:112
u8 * format_ip6_address(u8 *s, va_list *args)
Definition: vppcom.c:875
static void vl_api_application_detach_reply_t_handler(vl_api_application_detach_reply_t *mp)
Definition: vppcom.c:528
bidirectional disconnect API
Definition: session.api:160
#define clib_fifo_add1(f, e)
Definition: fifo.h:192
unsigned short u16
Definition: types.h:57
svm_fifo_segment_private_t * segments
pool of segments
u32 tx_event_id
Definition: vppcom.c:116
uword * error_string_by_error_number
Definition: vppcom.c:154
static void vppcom_cfg_init(vppcom_cfg_t *vcl_cfg)
Definition: vppcom.c:1309
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
u8 * format_ip4_address(u8 *s, va_list *args)
Definition: vppcom.c:868
#define clib_fifo_validate(f, n_elts)
Definition: fifo.h:112
u32 preallocated_fifo_pairs
Definition: vppcom.c:101
void vl_client_disconnect_from_vlib(void)
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
static int vppcom_wait_for_client_session_index(f64 wait_for_time)
Definition: vppcom.c:355
vppcom_cfg_t cfg
Definition: vppcom.c:151
static void vppcom_cfg_heapsize(char *conf_fname)
Definition: vppcom.c:1328
int vppcom_session_read(uint32_t session_index, void *buf, int n)
Definition: vppcom.c:2111
static_always_inline uword os_get_thread_index(void)
Definition: os.h:62
u8 * format_ip46_address(u8 *s, va_list *args)
Definition: vppcom.c:926
u32 tx_fifo_size
Definition: vppcom.c:103
app_state_t
Definition: vppcom.c:53
u64 vpp_session_handle
u32 my_client_index
Definition: vppcom.c:123
uint32_t vrf
Definition: vppcom.h:44
static int vppcom_wait_for_app_state_change(app_state_t app_state)
Definition: vppcom.c:304
static void vl_api_session_enable_disable_reply_t_handler(vl_api_session_enable_disable_reply_t *mp)
Definition: vppcom.c:417
static int vppcom_session_at_index(u32 session_index, session_t *volatile *sess)
Definition: vppcom.c:233
u8 proto
Definition: vppcom.c:90
client->vpp reset session reply
Definition: session.api:199
uword clib_bitmap_t
Definition: bitmap.h:50
static const char * vppcom_app_state_str(app_state_t state)
Definition: vppcom.c:160
Vector bootsrap header file.
int vppcom_session_close(uint32_t session_index)
Definition: vppcom.c:1825
void unformat_init_unix_file(unformat_input_t *input, int file_descriptor)
Definition: unformat.c:1058
f64 session_timeout
Definition: vppcom.c:107
u16 as_u16[8]
Definition: ip6_packet.h:49
static void ssvm_unlock_non_recursive(ssvm_shared_header_t *h)
Definition: ssvm.h:126
static void vl_api_bind_sock_reply_t_handler(vl_api_bind_sock_reply_t *mp)
Definition: vppcom.c:821
unix_shared_memory_queue_t * vl_input_queue
Definition: vppcom.c:120
void vl_set_memory_root_path(const char *root_path)
bidirectional disconnect reply API
Definition: session.api:173
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
#define BITS(x)
Definition: clib.h:58
int svm_fifo_segment_attach(svm_fifo_segment_create_args_t *a)
(slave) attach to an svm fifo segment
volatile app_state_t app_state
Definition: vppcom.c:149
int svm_fifo_dequeue_nowait(svm_fifo_t *f, u32 max_bytes, u8 *copy_here)
Definition: svm_fifo.c:690
uword unformat_skip_white_space(unformat_input_t *input)
Definition: unformat.c:815
static void vppcom_init_error_string_table(void)
Definition: vppcom.c:290
static int vppcom_session_disconnect(u32 session_index)
Definition: vppcom.c:1259
int vppcom_session_write(uint32_t session_index, void *buf, int n)
Definition: vppcom.c:2194
u32 event_queue_size
Definition: vppcom.c:104
static void vl_api_accept_session_t_handler(vl_api_accept_session_t *mp)
Definition: vppcom.c:951
static int vppcom_session_write_ready(session_t *session, u32 session_index)
Definition: vppcom.c:2276
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static void ssvm_lock_non_recursive(ssvm_shared_header_t *h, u32 tag)
Definition: ssvm.h:105
void svm_fifo_segment_delete(svm_fifo_segment_private_t *s)
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
struct _unix_shared_memory_queue unix_shared_memory_queue_t
svm_fifo_t * svm_fifo_segment_alloc_fifo(svm_fifo_segment_private_t *s, u32 data_size_in_bytes, svm_fifo_segment_freelist_t list_index)
uint8_t is_cut_thru
Definition: vppcom.h:45