FD.io VPP  v19.01.2-3-gf61a1a8
Vector Packet Processing
application.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 file except in compliance with the License.
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 
19 #include <vnet/session/session.h>
20 
22 
23 static app_listener_t *
25 {
26  app_listener_t *app_listener;
27  pool_get (app->listeners, app_listener);
28  clib_memset (app_listener, 0, sizeof (*app_listener));
29  app_listener->al_index = app_listener - app->listeners;
30  return app_listener;
31 }
32 
33 static app_listener_t *
34 app_listener_get (application_t * app, u32 app_listener_index)
35 {
36  return pool_elt_at_index (app->listeners, app_listener_index);
37 }
38 
39 static void
41 {
42  clib_bitmap_free (app_listener->workers);
43  pool_put (app->listeners, app_listener);
44  if (CLIB_DEBUG)
45  clib_memset (app_listener, 0xfa, sizeof (*app_listener));
46 }
47 
48 static app_listener_t *
50 {
51  app_listener_t *app_listener;
52  pool_get (app->local_listeners, app_listener);
53  clib_memset (app_listener, 0, sizeof (*app_listener));
54  app_listener->al_index = app_listener - app->local_listeners;
55  return app_listener;
56 }
57 
58 static app_listener_t *
59 app_local_listener_get (application_t * app, u32 app_listener_index)
60 {
61  return pool_elt_at_index (app->local_listeners, app_listener_index);
62 }
63 
64 static void
66 {
67  clib_bitmap_free (app_listener->workers);
68  pool_put (app->local_listeners, app_listener);
69  if (CLIB_DEBUG)
70  clib_memset (app_listener, 0xfa, sizeof (*app_listener));
71 }
72 
73 static app_worker_map_t *
75 {
76  app_worker_map_t *map;
77  pool_get (app->worker_maps, map);
78  clib_memset (map, 0, sizeof (*map));
79  return map;
80 }
81 
82 static u32
84 {
85  return (map - app->worker_maps);
86 }
87 
88 static void
90 {
91  pool_put (app->worker_maps, map);
92 }
93 
94 static app_worker_map_t *
96 {
97  if (pool_is_free_index (app->worker_maps, map_index))
98  return 0;
99  return pool_elt_at_index (app->worker_maps, map_index);
100 }
101 
102 static const u8 *
104 {
105  return app->name;
106 }
107 
108 u32
110 {
111  app_namespace_t *app_ns;
112  app_ns = app_namespace_get (app->ns_index);
113  if (!application_has_global_scope (app))
114  return APP_INVALID_INDEX;
115  if (fib_proto == FIB_PROTOCOL_IP4)
116  return session_lookup_get_index_for_fib (fib_proto,
117  app_ns->ip4_fib_index);
118  else
119  return session_lookup_get_index_for_fib (fib_proto,
120  app_ns->ip6_fib_index);
121 }
122 
123 u32
125 {
126  app_namespace_t *app_ns;
127  if (!application_has_local_scope (app))
128  return APP_INVALID_INDEX;
129  app_ns = app_namespace_get (app->ns_index);
130  return app_ns->local_table_index;
131 }
132 
133 static void
135  session_endpoint_t * sep)
136 {
137  sep->transport_proto =
139  sep->port = ll->port;
140  sep->is_ip4 = ll->listener_session_type & 1;
141 }
142 
143 /**
144  * Returns app name for app-index
145  */
146 const u8 *
148 {
149  application_t *app = application_get (app_index);
150  if (!app)
151  return 0;
152  return app_get_name (app);
153 }
154 
155 static void
156 application_api_table_add (u32 app_index, u32 api_client_index)
157 {
158  if (api_client_index != APP_INVALID_INDEX)
159  hash_set (app_main.app_by_api_client_index, api_client_index, app_index);
160 }
161 
162 static void
163 application_api_table_del (u32 api_client_index)
164 {
165  hash_unset (app_main.app_by_api_client_index, api_client_index);
166 }
167 
168 static void
170 {
171  hash_set_mem (app_main.app_by_name, app->name, app->app_index);
172 }
173 
174 static void
176 {
177  hash_unset_mem (app_main.app_by_name, app->name);
178 }
179 
181 application_lookup (u32 api_client_index)
182 {
183  uword *p;
184  p = hash_get (app_main.app_by_api_client_index, api_client_index);
185  if (p)
186  return application_get_if_valid (p[0]);
187 
188  return 0;
189 }
190 
193 {
194  uword *p;
195  p = hash_get_mem (app_main.app_by_name, name);
196  if (p)
197  return application_get (p[0]);
198 
199  return 0;
200 }
201 
204 {
205  application_t *app;
206  pool_get (app_main.app_pool, app);
207  clib_memset (app, 0, sizeof (*app));
208  app->app_index = app - app_main.app_pool;
209  return app;
210 }
211 
213 application_get (u32 app_index)
214 {
215  if (app_index == APP_INVALID_INDEX)
216  return 0;
217  return pool_elt_at_index (app_main.app_pool, app_index);
218 }
219 
222 {
223  if (pool_is_free_index (app_main.app_pool, app_index))
224  return 0;
225 
226  return pool_elt_at_index (app_main.app_pool, app_index);
227 }
228 
229 static void
231 {
232  if (cb_fns->session_accept_callback == 0)
233  clib_warning ("No accept callback function provided");
234  if (cb_fns->session_connected_callback == 0)
235  clib_warning ("No session connected callback function provided");
236  if (cb_fns->session_disconnect_callback == 0)
237  clib_warning ("No session disconnect callback function provided");
238  if (cb_fns->session_reset_callback == 0)
239  clib_warning ("No session reset callback function provided");
240 }
241 
242 /**
243  * Check app config for given segment type
244  *
245  * Returns 1 on success and 0 otherwise
246  */
247 static u8
249 {
250  u8 is_valid;
251  if (st == SSVM_SEGMENT_MEMFD)
252  {
253  is_valid = (session_manager_get_evt_q_segment () != 0);
254  if (!is_valid)
255  clib_warning ("memfd seg: vpp's event qs IN binary api svm region");
256  return is_valid;
257  }
258  else if (st == SSVM_SEGMENT_SHM)
259  {
260  is_valid = (session_manager_get_evt_q_segment () == 0);
261  if (!is_valid)
262  clib_warning ("shm seg: vpp's event qs NOT IN binary api svm region");
263  return is_valid;
264  }
265  else
266  return 1;
267 }
268 
269 int
271 {
275  application_t *app;
276  u64 *options;
277 
278  app = application_alloc ();
279  options = a->options;
280  /*
281  * Make sure we support the requested configuration
282  */
283  if (!(options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_IS_BUILTIN))
284  {
285  reg = vl_api_client_index_to_registration (a->api_client_index);
286  if (!reg)
287  return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
289  seg_type = SSVM_SEGMENT_SHM;
290  }
291  else
292  {
293  if (options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
294  {
295  clib_warning ("mq eventfds can only be used if socket transport is "
296  "used for api");
297  return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
298  }
299  seg_type = SSVM_SEGMENT_PRIVATE;
300  }
301 
302  if (!application_verify_cfg (seg_type))
303  return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
304 
305  /* Check that the obvious things are properly set up */
306  application_verify_cb_fns (a->session_cb_vft);
307 
308  app->flags = options[APP_OPTIONS_FLAGS];
309  app->cb_fns = *a->session_cb_vft;
310  app->ns_index = options[APP_OPTIONS_NAMESPACE];
312  app->name = vec_dup (a->name);
313 
314  /* If no scope enabled, default to global */
316  && !application_has_local_scope (app))
317  app->flags |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
318 
321  props->segment_size = options[APP_OPTIONS_ADD_SEGMENT_SIZE];
322  props->prealloc_fifos = options[APP_OPTIONS_PREALLOC_FIFO_PAIRS];
323  if (options[APP_OPTIONS_ADD_SEGMENT_SIZE])
324  {
325  props->add_segment_size = options[APP_OPTIONS_ADD_SEGMENT_SIZE];
326  props->add_segment = 1;
327  }
328  if (options[APP_OPTIONS_RX_FIFO_SIZE])
329  props->rx_fifo_size = options[APP_OPTIONS_RX_FIFO_SIZE];
330  if (options[APP_OPTIONS_TX_FIFO_SIZE])
331  props->tx_fifo_size = options[APP_OPTIONS_TX_FIFO_SIZE];
332  if (options[APP_OPTIONS_EVT_QUEUE_SIZE])
333  props->evt_q_size = options[APP_OPTIONS_EVT_QUEUE_SIZE];
334  if (options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
335  props->use_mq_eventfd = 1;
336  if (options[APP_OPTIONS_TLS_ENGINE])
337  app->tls_engine = options[APP_OPTIONS_TLS_ENGINE];
338  props->segment_type = seg_type;
339 
340  /* Add app to lookup by api_client_index table */
341  if (!application_is_builtin (app))
342  application_api_table_add (app->app_index, a->api_client_index);
343  else
345 
346  a->app_index = app->app_index;
347 
348  APP_DBG ("New app name: %v api index: %u index %u", app->name,
349  app->api_client_index, app->app_index);
350 
351  return 0;
352 }
353 
354 void
356 {
357  app_worker_map_t *wrk_map;
358  app_worker_t *app_wrk;
359  u32 table_index;
360  local_session_t *ll;
361  session_endpoint_t sep;
362 
363  /*
364  * The app event queue allocated in first segment is cleared with
365  * the segment manager. No need to explicitly free it.
366  */
367  APP_DBG ("Delete app name %v api index: %d index: %d", app->name,
368  app->api_client_index, app->app_index);
369 
370  if (application_is_proxy (app))
372 
373  /*
374  * Free workers
375  */
376 
377  /* *INDENT-OFF* */
378  pool_flush (wrk_map, app->worker_maps, ({
379  app_wrk = app_worker_get (wrk_map->wrk_index);
380  app_worker_free (app_wrk);
381  }));
382  /* *INDENT-ON* */
383  pool_free (app->worker_maps);
384 
385  /*
386  * Free local listeners. Global table unbinds stop local listeners
387  * as well, but if we have only local binds, these won't be cleaned up.
388  * Don't bother with local accepted sessions, we clean them when
389  * cleaning up the worker.
390  */
391  table_index = application_local_session_table (app);
392  /* *INDENT-OFF* */
393  pool_foreach (ll, app->local_listen_sessions, ({
394  application_local_listener_session_endpoint (ll, &sep);
395  session_lookup_del_session_endpoint (table_index, &sep);
396  }));
397  /* *INDENT-ON* */
399 
400  /*
401  * Cleanup remaining state
402  */
403  if (application_is_builtin (app))
405  vec_free (app->name);
406  vec_free (app->tls_cert);
407  vec_free (app->tls_key);
408  pool_put (app_main.app_pool, app);
409 }
410 
411 void
413 {
414  vnet_app_worker_add_del_args_t _args = { 0 }, *args = &_args;
415  app_worker_map_t *wrk_map;
416  u32 *wrks = 0, *wrk_index;
417  app_worker_t *app_wrk;
418 
419  if (api_client_index == ~0)
420  {
421  application_free (app);
422  return;
423  }
424 
425  APP_DBG ("Detaching for app %v index %u api client index %u", app->name,
426  app->app_index, app->api_client_index);
427 
428  /* *INDENT-OFF* */
429  pool_foreach (wrk_map, app->worker_maps, ({
430  app_wrk = app_worker_get (wrk_map->wrk_index);
431  if (app_wrk->api_client_index == api_client_index)
432  vec_add1 (wrks, app_wrk->wrk_index);
433  }));
434  /* *INDENT-ON* */
435 
436  if (!vec_len (wrks))
437  {
438  clib_warning ("no workers for app %u api_index %u", app->app_index,
439  api_client_index);
440  return;
441  }
442 
443  args->app_index = app->app_index;
444  args->api_client_index = api_client_index;
445  vec_foreach (wrk_index, wrks)
446  {
447  app_wrk = app_worker_get (wrk_index[0]);
448  args->wrk_map_index = app_wrk->wrk_map_index;
449  args->is_add = 0;
451  }
452  vec_free (wrks);
453 }
454 
455 app_worker_t *
457 {
458  app_worker_map_t *map;
459  map = app_worker_map_get (app, wrk_map_index);
460  if (!map)
461  return 0;
462  return app_worker_get (map->wrk_index);
463 }
464 
465 app_worker_t *
467 {
468  return application_get_worker (app, 0);
469 }
470 
471 u32
473 {
474  return pool_elts (app->worker_maps);
475 }
476 
477 app_worker_t *
479 {
480  app_listener_t *app_listener;
481  application_t *app;
482  u32 wrk_index;
483 
484  app = application_get (ls->app_index);
485  if (!is_local)
486  app_listener = app_listener_get (app, ls->listener_db_index);
487  else
488  app_listener = app_local_listener_get (app, ls->listener_db_index);
489 
490  wrk_index = clib_bitmap_next_set (app_listener->workers,
491  app_listener->accept_rotor + 1);
492  if (wrk_index == ~0)
493  wrk_index = clib_bitmap_first_set (app_listener->workers);
494 
495  ASSERT (wrk_index != ~0);
496  app_listener->accept_rotor = wrk_index;
497  return application_get_worker (app, wrk_index);
498 }
499 
500 app_worker_t *
502 {
503  app_worker_t *app_wrk;
504  pool_get (app_main.workers, app_wrk);
505  clib_memset (app_wrk, 0, sizeof (*app_wrk));
506  app_wrk->wrk_index = app_wrk - app_main.workers;
507  app_wrk->app_index = app->app_index;
508  app_wrk->wrk_map_index = ~0;
512  APP_DBG ("New app %v worker %u", app_get_name (app), app_wrk->wrk_index);
513  return app_wrk;
514 }
515 
516 app_worker_t *
517 app_worker_get (u32 wrk_index)
518 {
519  return pool_elt_at_index (app_main.workers, wrk_index);
520 }
521 
522 app_worker_t *
524 {
525  if (pool_is_free_index (app_main.workers, wrk_index))
526  return 0;
527  return pool_elt_at_index (app_main.workers, wrk_index);
528 }
529 
530 void
532 {
533  application_t *app = application_get (app_wrk->app_index);
534  vnet_unbind_args_t _a, *a = &_a;
535  u64 handle, *handles = 0;
536  segment_manager_t *sm;
537  u32 sm_index;
538  int i;
539 
540  /*
541  * Listener cleanup
542  */
543 
544  /* *INDENT-OFF* */
545  hash_foreach (handle, sm_index, app_wrk->listeners_table,
546  ({
547  vec_add1 (handles, handle);
548  sm = segment_manager_get (sm_index);
549  sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
550  }));
551  /* *INDENT-ON* */
552 
553  for (i = 0; i < vec_len (handles); i++)
554  {
555  a->app_index = app->app_index;
556  a->wrk_map_index = app_wrk->wrk_map_index;
557  a->handle = handles[i];
558  /* seg manager is removed when unbind completes */
559  vnet_unbind (a);
560  }
561 
562  /*
563  * Connects segment manager cleanup
564  */
565 
567  {
569  sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
571  }
572 
573  /* If first segment manager is used by a listener */
575  && app_wrk->first_segment_manager != app_wrk->connects_seg_manager)
576  {
578  sm->first_is_protected = 0;
579  sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
580  /* .. and has no fifos, e.g. it might be used for redirected sessions,
581  * remove it */
582  if (!segment_manager_has_fifos (sm))
583  segment_manager_del (sm);
584  }
585 
586  /*
587  * Local sessions
588  */
590 
591  pool_put (app_main.workers, app_wrk);
592  if (CLIB_DEBUG)
593  clib_memset (app_wrk, 0xfe, sizeof (*app_wrk));
594 }
595 
596 int
598 {
599  app_worker_map_t *wrk_map;
600  app_worker_t *app_wrk;
601  segment_manager_t *sm;
602  int rv;
603 
604  app_wrk = app_worker_alloc (app);
605  wrk_map = app_worker_map_alloc (app);
606  wrk_map->wrk_index = app_wrk->wrk_index;
607  app_wrk->wrk_map_index = app_worker_map_index (app, wrk_map);
608 
609  /*
610  * Setup first segment manager
611  */
612  sm = segment_manager_new ();
613  sm->app_wrk_index = app_wrk->wrk_index;
614 
615  if ((rv = segment_manager_init (sm, app->sm_properties.segment_size,
616  app->sm_properties.prealloc_fifos)))
617  {
618  app_worker_free (app_wrk);
619  return rv;
620  }
621  sm->first_is_protected = 1;
622 
623  /*
624  * Setup app worker
625  */
627  app_wrk->listeners_table = hash_create (0, sizeof (u64));
629  app_wrk->app_is_builtin = application_is_builtin (app);
630 
631  /*
632  * Segment manager for local sessions
633  */
634  sm = segment_manager_new ();
635  sm->app_wrk_index = app_wrk->wrk_index;
637  app_wrk->local_connects = hash_create (0, sizeof (u64));
638 
639  *wrk = app_wrk;
640 
641  return 0;
642 }
643 
646 {
647  app_worker_t *app_wrk;
648  app_wrk = app_worker_get_if_valid (wrk_index);
649  if (!app_wrk)
650  return 0;
651  return application_get_if_valid (app_wrk->app_index);
652 }
653 
654 static segment_manager_t *
656 {
657  segment_manager_t *sm = 0;
658 
659  /* If the first segment manager is not in use, don't allocate a new one */
661  && app_wrk->first_segment_manager_in_use == 0)
662  {
664  app_wrk->first_segment_manager_in_use = 1;
665  return sm;
666  }
667 
668  sm = segment_manager_new ();
669  sm->app_wrk_index = app_wrk->wrk_index;
670 
671  return sm;
672 }
673 
674 int
676 {
677  segment_manager_t *sm;
678 
679  /* Allocate segment manager. All sessions derived out of a listen session
680  * have fifos allocated by the same segment manager. */
681  if (!(sm = app_worker_alloc_segment_manager (app_wrk)))
682  return -1;
683 
684  /* Add to app's listener table. Useful to find all child listeners
685  * when app goes down, although, just for unbinding this is not needed */
687  segment_manager_index (sm));
688 
689  if (!ls->server_rx_fifo
691  {
692  if (session_alloc_fifos (sm, ls))
693  return -1;
694  }
695  return 0;
696 }
697 
698 int
700 {
701  segment_manager_t *sm;
702  uword *sm_indexp;
703 
704  sm_indexp = hash_get (app_wrk->listeners_table, handle);
705  if (PREDICT_FALSE (!sm_indexp))
706  {
707  clib_warning ("listener handle was removed %llu!", handle);
708  return -1;
709  }
710 
711  sm = segment_manager_get (*sm_indexp);
712  if (app_wrk->first_segment_manager == *sm_indexp)
713  {
714  /* Delete sessions but don't remove segment manager */
715  app_wrk->first_segment_manager_in_use = 0;
717  }
718  else
719  {
721  }
722  hash_unset (app_wrk->listeners_table, handle);
723 
724  return 0;
725 }
726 
727 int
729 {
730  segment_manager_t *sm;
731  svm_fifo_t *rxf, *txf;
732 
733  s->app_wrk_index = app_wrk->wrk_index;
734 
735  rxf = s->server_rx_fifo;
736  txf = s->server_tx_fifo;
737 
738  if (!rxf || !txf)
739  return 0;
740 
741  s->server_rx_fifo = 0;
742  s->server_tx_fifo = 0;
743 
745  if (session_alloc_fifos (sm, s))
746  return -1;
747 
748  if (!svm_fifo_is_empty (rxf))
749  {
750  clib_memcpy_fast (s->server_rx_fifo->data, rxf->data, rxf->nitems);
751  s->server_rx_fifo->head = rxf->head;
752  s->server_rx_fifo->tail = rxf->tail;
753  s->server_rx_fifo->cursize = rxf->cursize;
754  }
755 
756  if (!svm_fifo_is_empty (txf))
757  {
758  clib_memcpy_fast (s->server_tx_fifo->data, txf->data, txf->nitems);
759  s->server_tx_fifo->head = txf->head;
760  s->server_tx_fifo->tail = txf->tail;
761  s->server_tx_fifo->cursize = txf->cursize;
762  }
763 
764  segment_manager_dealloc_fifos (rxf->segment_index, rxf, txf);
765 
766  return 0;
767 }
768 
769 /**
770  * Start listening local transport endpoint for requested transport.
771  *
772  * Creates a 'dummy' stream session with state LISTENING to be used in session
773  * lookups, prior to establishing connection. Requests transport to build
774  * it's own specific listening connection.
775  */
776 int
778  session_endpoint_cfg_t * sep_ext,
779  session_handle_t * res)
780 {
781  app_listener_t *app_listener;
782  u32 table_index, fib_proto;
783  session_endpoint_t *sep;
784  app_worker_t *app_wrk;
785  stream_session_t *ls;
786  session_handle_t lh;
787  session_type_t sst;
788 
789  /*
790  * Check if sep is already listened on
791  */
792  sep = (session_endpoint_t *) sep_ext;
793  fib_proto = session_endpoint_fib_proto (sep);
794  table_index = application_session_table (app, fib_proto);
795  lh = session_lookup_endpoint_listener (table_index, sep, 1);
796  if (lh != SESSION_INVALID_HANDLE)
797  {
799  if (ls->app_index != app->app_index)
800  return VNET_API_ERROR_ADDRESS_IN_USE;
801 
802  app_wrk = app_worker_get (sep_ext->app_wrk_index);
803  if (ls->app_wrk_index == app_wrk->wrk_index)
804  return VNET_API_ERROR_ADDRESS_IN_USE;
805 
806  if (app_worker_start_listen (app_wrk, ls))
807  return -1;
808 
809  app_listener = app_listener_get (app, ls->listener_db_index);
810  app_listener->workers = clib_bitmap_set (app_listener->workers,
811  app_wrk->wrk_map_index, 1);
812 
813  *res = listen_session_get_handle (ls);
814  return 0;
815  }
816 
817  /*
818  * Allocate new listener for application
819  */
820  sst = session_type_from_proto_and_ip (sep_ext->transport_proto,
821  sep_ext->is_ip4);
822  ls = listen_session_new (0, sst);
823  ls->app_index = app->app_index;
824  lh = listen_session_get_handle (ls);
825  if (session_listen (ls, sep_ext))
826  goto err;
827 
828 
830  app_listener = app_listener_alloc (app);
831  ls->listener_db_index = app_listener->al_index;
832 
833  /*
834  * Setup app worker as a listener
835  */
836  app_wrk = app_worker_get (sep_ext->app_wrk_index);
837  ls->app_wrk_index = app_wrk->wrk_index;
838  if (app_worker_start_listen (app_wrk, ls))
839  goto err;
840  app_listener->workers = clib_bitmap_set (app_listener->workers,
841  app_wrk->wrk_map_index, 1);
842 
843  *res = lh;
844  return 0;
845 
846 err:
847  listen_session_del (ls);
848  return -1;
849 }
850 
851 /**
852  * Stop listening on session associated to handle
853  *
854  * @param handle listener handle
855  * @param app_index index of the app owning the handle.
856  * @param app_wrk_index index of the worker requesting the stop
857  */
858 int
859 application_stop_listen (u32 app_index, u32 app_wrk_index,
860  session_handle_t handle)
861 {
862  app_listener_t *app_listener;
864  app_worker_t *app_wrk;
865  application_t *app;
866 
867  listener = listen_session_get_from_handle (handle);
868  app = application_get (app_index);
869  if (PREDICT_FALSE (!app || app->app_index != listener->app_index))
870  {
871  clib_warning ("app doesn't own handle %llu!", handle);
872  return -1;
873  }
874 
875  app_listener = app_listener_get (app, listener->listener_db_index);
876  if (!clib_bitmap_get (app_listener->workers, app_wrk_index))
877  {
878  clib_warning ("worker %u not listening on handle %lu", app_wrk_index,
879  handle);
880  return 0;
881  }
882 
883  app_wrk = application_get_worker (app, app_wrk_index);
884  app_worker_stop_listen (app_wrk, handle);
885  clib_bitmap_set_no_check (app_listener->workers, app_wrk_index, 0);
886 
887  if (clib_bitmap_is_zero (app_listener->workers))
888  {
889  session_stop_listen (listener);
890  app_listener_free (app, app_listener);
891  listen_session_del (listener);
892  }
893 
894  return 0;
895 }
896 
897 int
899  u32 api_context)
900 {
901  int rv;
902 
903  /* Make sure we have a segment manager for connects */
905 
906  if ((rv = session_open (app->wrk_index, sep, api_context)))
907  return rv;
908 
909  return 0;
910 }
911 
912 int
914 {
915  segment_manager_t *sm;
916 
918  {
919  sm = app_worker_alloc_segment_manager (app_wrk);
920  if (sm == 0)
921  return -1;
923  }
924  return 0;
925 }
926 
929 {
930  ASSERT (app->connects_seg_manager != (u32) ~ 0);
932 }
933 
936 {
937  if (app_wrk->connects_seg_manager == (u32) ~ 0)
939  return segment_manager_get (app_wrk->connects_seg_manager);
940 }
941 
945 {
946  uword *smp;
947  smp = hash_get (app->listeners_table, listen_session_get_handle (listener));
948  ASSERT (smp != 0);
949  return segment_manager_get (*smp);
950 }
951 
952 clib_error_t *
954 {
956  app_worker_map_t *wrk_map;
957  app_worker_t *app_wrk;
958  segment_manager_t *sm;
959  application_t *app;
960  int rv;
961 
962  app = application_get (a->app_index);
963  if (!app)
964  return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
965  "App %u does not exist", a->app_index);
966 
967  if (a->is_add)
968  {
969  if ((rv = app_worker_alloc_and_init (app, &app_wrk)))
970  return clib_error_return_code (0, rv, 0, "app wrk init: %d", rv);
971 
972  /* Map worker api index to the app */
973  app_wrk->api_client_index = a->api_client_index;
974  application_api_table_add (app->app_index, a->api_client_index);
975 
978  a->segment = &fs->ssvm;
979  a->segment_handle = segment_manager_segment_handle (sm, fs);
981  a->evt_q = app_wrk->event_queue;
982  a->wrk_map_index = app_wrk->wrk_map_index;
983  }
984  else
985  {
986  wrk_map = app_worker_map_get (app, a->wrk_map_index);
987  if (!wrk_map)
988  return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
989  "App %u does not have worker %u",
990  app->app_index, a->wrk_map_index);
991  app_wrk = app_worker_get (wrk_map->wrk_index);
992  if (!app_wrk)
993  return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
994  "No worker %u", a->wrk_map_index);
996  app_worker_free (app_wrk);
997  app_worker_map_free (app, wrk_map);
998  if (application_n_workers (app) == 0)
999  application_free (app);
1000  }
1001  return 0;
1002 }
1003 
1006 {
1008 }
1009 
1012  local_session_t * ls)
1013 {
1016  {
1017  listener = listen_session_get (ls->listener_index);
1018  return app_worker_get_listen_segment_manager (app, listener);
1019  }
1021 }
1022 
1023 int
1025 {
1026  return (app->flags & APP_OPTIONS_FLAGS_IS_PROXY);
1027 }
1028 
1029 int
1031 {
1032  return (app->flags & APP_OPTIONS_FLAGS_IS_BUILTIN);
1033 }
1034 
1035 int
1037 {
1038  return (application_is_proxy (app) && application_is_builtin (app));
1039 }
1040 
1041 u8
1043 {
1044  return app->flags & APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1045 }
1046 
1047 u8
1049 {
1050  return app->flags & APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1051 }
1052 
1053 u8
1055 {
1056  return app->flags & APP_OPTIONS_FLAGS_USE_MQ_FOR_CTRL_MSGS;
1057 }
1058 
1059 /**
1060  * Send an API message to the external app, to map new segment
1061  */
1062 int
1063 app_worker_add_segment_notify (u32 app_wrk_index, u64 segment_handle)
1064 {
1065  app_worker_t *app_wrk = app_worker_get (app_wrk_index);
1066  application_t *app = application_get (app_wrk->app_index);
1067  return app->cb_fns.add_segment_callback (app_wrk->api_client_index,
1068  segment_handle);
1069 }
1070 
1071 u32
1073 {
1074  return hash_elts (app->listeners_table);
1075 }
1076 
1079  u8 transport_proto)
1080 {
1082  u64 handle;
1083  u32 sm_index;
1084  u8 sst;
1085 
1086  sst = session_type_from_proto_and_ip (transport_proto,
1087  fib_proto == FIB_PROTOCOL_IP4);
1088 
1089  /* *INDENT-OFF* */
1090  hash_foreach (handle, sm_index, app->listeners_table, ({
1091  listener = listen_session_get_from_handle (handle);
1092  if (listener->session_type == sst
1093  && listener->enqueue_epoch != SESSION_PROXY_LISTENER_INDEX)
1094  return listener;
1095  }));
1096  /* *INDENT-ON* */
1097 
1098  return 0;
1099 }
1100 
1101 u8
1103 {
1104  return app_wrk->app_is_builtin;
1105 }
1106 
1109  u8 transport_proto)
1110 {
1112  u64 handle;
1113  u32 sm_index;
1114  u8 sst;
1115 
1116  sst = session_type_from_proto_and_ip (transport_proto,
1117  fib_proto == FIB_PROTOCOL_IP4);
1118 
1119  /* *INDENT-OFF* */
1120  hash_foreach (handle, sm_index, app->listeners_table, ({
1121  listener = listen_session_get_from_handle (handle);
1122  if (listener->session_type == sst
1123  && listener->enqueue_epoch == SESSION_PROXY_LISTENER_INDEX)
1124  return listener;
1125  }));
1126  /* *INDENT-ON* */
1127 
1128  return 0;
1129 }
1130 
1131 static clib_error_t *
1133  u8 transport_proto, u8 is_start)
1134 {
1135  app_namespace_t *app_ns = app_namespace_get (app->ns_index);
1136  u8 is_ip4 = (fib_proto == FIB_PROTOCOL_IP4);
1139  app_worker_t *app_wrk;
1140  stream_session_t *s;
1141  u64 handle;
1142 
1143  /* TODO decide if we want proxy to be enabled for all workers */
1144  app_wrk = application_get_default_worker (app);
1145  if (is_start)
1146  {
1147  s = app_worker_first_listener (app_wrk, fib_proto, transport_proto);
1148  if (!s)
1149  {
1150  sep.is_ip4 = is_ip4;
1151  sep.fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1152  sep.sw_if_index = app_ns->sw_if_index;
1153  sep.transport_proto = transport_proto;
1154  sep.app_wrk_index = app_wrk->wrk_index; /* only default */
1155  application_start_listen (app, &sep, &handle);
1156  s = listen_session_get_from_handle (handle);
1157  s->enqueue_epoch = SESSION_PROXY_LISTENER_INDEX;
1158  }
1159  }
1160  else
1161  {
1162  s = application_proxy_listener (app_wrk, fib_proto, transport_proto);
1163  ASSERT (s);
1164  }
1165 
1167 
1168  if (!ip_is_zero (&tc->lcl_ip, 1))
1169  {
1170  u32 sti;
1171  sep.is_ip4 = is_ip4;
1172  sep.fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1173  sep.transport_proto = transport_proto;
1174  sep.port = 0;
1175  sti = session_lookup_get_index_for_fib (fib_proto, sep.fib_index);
1176  if (is_start)
1178  (session_endpoint_t *) & sep,
1179  s->session_index);
1180  else
1182  (session_endpoint_t *) & sep);
1183  }
1184 
1185  return 0;
1186 }
1187 
1188 static void
1190  u8 transport_proto, u8 is_start)
1191 {
1193  app_namespace_t *app_ns;
1194  app_ns = app_namespace_get (app->ns_index);
1195  sep.is_ip4 = 1;
1196  sep.transport_proto = transport_proto;
1197  sep.port = 0;
1198 
1199  if (is_start)
1200  {
1201  session_lookup_add_session_endpoint (app_ns->local_table_index, &sep,
1202  app->app_index);
1203  sep.is_ip4 = 0;
1204  session_lookup_add_session_endpoint (app_ns->local_table_index, &sep,
1205  app->app_index);
1206  }
1207  else
1208  {
1209  session_lookup_del_session_endpoint (app_ns->local_table_index, &sep);
1210  sep.is_ip4 = 0;
1211  session_lookup_del_session_endpoint (app_ns->local_table_index, &sep);
1212  }
1213 }
1214 
1215 void
1217  transport_proto_t transport_proto, u8 is_start)
1218 {
1219  if (application_has_local_scope (app))
1220  application_start_stop_proxy_local_scope (app, transport_proto, is_start);
1221 
1222  if (application_has_global_scope (app))
1223  {
1225  transport_proto, is_start);
1227  transport_proto, is_start);
1228  }
1229 }
1230 
1231 void
1233 {
1234  u16 transports = app->proxied_transports;
1235  transport_proto_t tp;
1236 
1237  ASSERT (application_is_proxy (app));
1238 
1239  /* *INDENT-OFF* */
1240  transport_proto_foreach (tp, ({
1241  if (transports & (1 << tp))
1242  application_start_stop_proxy (app, tp, 1);
1243  }));
1244  /* *INDENT-ON* */
1245 }
1246 
1247 void
1249 {
1250  u16 transports = app->proxied_transports;
1251  transport_proto_t tp;
1252 
1253  ASSERT (application_is_proxy (app));
1254 
1255  /* *INDENT-OFF* */
1256  transport_proto_foreach (tp, ({
1257  if (transports & (1 << tp))
1258  application_start_stop_proxy (app, tp, 0);
1259  }));
1260  /* *INDENT-ON* */
1261 }
1262 
1265 {
1266  return &app->sm_properties;
1267 }
1268 
1271 {
1272  application_t *app = application_get (app_index);
1273  return &app->sm_properties;
1274 }
1275 
1276 static inline int
1278 {
1279  if (PREDICT_FALSE (svm_msg_q_is_full (mq)))
1280  {
1281  clib_warning ("evt q full");
1282  svm_msg_q_free_msg (mq, msg);
1283  if (lock)
1284  svm_msg_q_unlock (mq);
1285  return -1;
1286  }
1287 
1288  if (lock)
1289  {
1290  svm_msg_q_add_and_unlock (mq, msg);
1291  return 0;
1292  }
1293 
1294  /* Even when not locking the ring, we must wait for queue mutex */
1295  if (svm_msg_q_add (mq, msg, SVM_Q_WAIT))
1296  {
1297  clib_warning ("msg q add returned");
1298  return -1;
1299  }
1300  return 0;
1301 }
1302 
1303 static inline int
1305 {
1306  session_event_t *evt;
1307  svm_msg_q_msg_t msg;
1308  svm_msg_q_t *mq;
1309 
1310  if (PREDICT_FALSE (s->session_state != SESSION_STATE_READY
1311  && s->session_state != SESSION_STATE_LISTENING))
1312  {
1313  /* Session is closed so app will never clean up. Flush rx fifo */
1314  if (s->session_state == SESSION_STATE_CLOSED)
1315  svm_fifo_dequeue_drop_all (s->server_rx_fifo);
1316  return 0;
1317  }
1318 
1319  if (app_worker_application_is_builtin (app_wrk))
1320  {
1321  application_t *app = application_get (app_wrk->app_index);
1322  return app->cb_fns.builtin_app_rx_callback (s);
1323  }
1324 
1325  if (svm_fifo_has_event (s->server_rx_fifo)
1326  || svm_fifo_is_empty (s->server_rx_fifo))
1327  return 0;
1328 
1329  mq = app_wrk->event_queue;
1330  if (lock)
1331  svm_msg_q_lock (mq);
1332 
1334  {
1335  clib_warning ("evt q rings full");
1336  if (lock)
1337  svm_msg_q_unlock (mq);
1338  return -1;
1339  }
1340 
1342  ASSERT (!svm_msg_q_msg_is_invalid (&msg));
1343 
1344  evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
1345  evt->fifo = s->server_rx_fifo;
1346  evt->event_type = FIFO_EVENT_APP_RX;
1347 
1348  (void) svm_fifo_set_event (s->server_rx_fifo);
1349 
1350  if (app_enqueue_evt (mq, &msg, lock))
1351  return -1;
1352  return 0;
1353 }
1354 
1355 static inline int
1357 {
1358  svm_msg_q_t *mq;
1359  session_event_t *evt;
1360  svm_msg_q_msg_t msg;
1361 
1362  if (app_worker_application_is_builtin (app_wrk))
1363  return 0;
1364 
1365  mq = app_wrk->event_queue;
1366  if (lock)
1367  svm_msg_q_lock (mq);
1368 
1370  {
1371  clib_warning ("evt q rings full");
1372  if (lock)
1373  svm_msg_q_unlock (mq);
1374  return -1;
1375  }
1376 
1378  ASSERT (!svm_msg_q_msg_is_invalid (&msg));
1379 
1380  evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
1381  evt->event_type = FIFO_EVENT_APP_TX;
1382  evt->fifo = s->server_tx_fifo;
1383 
1384  return app_enqueue_evt (mq, &msg, lock);
1385 }
1386 
1387 /* *INDENT-OFF* */
1389  stream_session_t *s,
1390  u8 lock);
1393  0,
1395 };
1396 /* *INDENT-ON* */
1397 
1398 /**
1399  * Send event to application
1400  *
1401  * Logic from queue perspective is non-blocking. If there's
1402  * not enough space to enqueue a message, we return.
1403  */
1404 int
1406 {
1407  ASSERT (app && evt_type <= FIFO_EVENT_APP_TX);
1408  return app_send_evt_handler_fns[evt_type] (app, s, 0 /* lock */ );
1409 }
1410 
1411 /**
1412  * Send event to application
1413  *
1414  * Logic from queue perspective is blocking. However, if queue is full,
1415  * we return.
1416  */
1417 int
1419  u8 evt_type)
1420 {
1421  return app_send_evt_handler_fns[evt_type] (app, s, 1 /* lock */ );
1422 }
1423 
1426 {
1427  local_session_t *s;
1428  pool_get (app_wrk->local_sessions, s);
1429  clib_memset (s, 0, sizeof (*s));
1430  s->app_wrk_index = app_wrk->wrk_index;
1431  s->session_index = s - app_wrk->local_sessions;
1433  return s;
1434 }
1435 
1436 void
1438 {
1439  pool_put (app->local_sessions, s);
1440  if (CLIB_DEBUG)
1441  clib_memset (s, 0xfc, sizeof (*s));
1442 }
1443 
1446 {
1447  if (pool_is_free_index (app_wrk->local_sessions, session_index))
1448  return 0;
1449  return pool_elt_at_index (app_wrk->local_sessions, session_index);
1450 }
1451 
1454 {
1455  app_worker_t *server_wrk;
1456  u32 session_index, server_wrk_index;
1457  local_session_parse_handle (handle, &server_wrk_index, &session_index);
1458  server_wrk = app_worker_get_if_valid (server_wrk_index);
1459  if (!server_wrk)
1460  return 0;
1461  return application_get_local_session (server_wrk, session_index);
1462 }
1463 
1466 {
1467  local_session_t *ll;
1468  pool_get (app->local_listen_sessions, ll);
1469  clib_memset (ll, 0, sizeof (*ll));
1470  return ll;
1471 }
1472 
1473 u32
1475 {
1476  return (ll - app->local_listen_sessions);
1477 }
1478 
1479 void
1481  local_session_t * ll)
1482 {
1483  pool_put (app->local_listen_sessions, ll);
1484  if (CLIB_DEBUG)
1485  clib_memset (ll, 0xfb, sizeof (*ll));
1486 }
1487 
1488 int
1490  session_endpoint_cfg_t * sep_ext,
1491  session_handle_t * handle)
1492 {
1493  app_listener_t *app_listener;
1494  session_endpoint_t *sep;
1495  app_worker_t *app_wrk;
1496  session_handle_t lh;
1497  local_session_t *ll;
1498  u32 table_index;
1499 
1500  sep = (session_endpoint_t *) sep_ext;
1501  table_index = application_local_session_table (app);
1502  app_wrk = app_worker_get (sep_ext->app_wrk_index);
1503 
1504  /* An exact sep match, as opposed to session_lookup_local_listener */
1505  lh = session_lookup_endpoint_listener (table_index, sep, 1);
1506  if (lh != SESSION_INVALID_HANDLE)
1507  {
1509  if (ll->app_index != app->app_index)
1510  return VNET_API_ERROR_ADDRESS_IN_USE;
1511 
1512  if (ll->app_wrk_index == app_wrk->wrk_index)
1513  return VNET_API_ERROR_ADDRESS_IN_USE;
1514 
1515  app_listener = app_local_listener_get (app, ll->listener_db_index);
1516  app_listener->workers = clib_bitmap_set (app_listener->workers,
1517  app_wrk->wrk_map_index, 1);
1518  *handle = application_local_session_handle (ll);
1519  return 0;
1520  }
1521 
1524  ll->app_wrk_index = app_wrk->app_index;
1526  ll->port = sep_ext->port;
1527  /* Store the original session type for the unbind */
1528  ll->listener_session_type =
1529  session_type_from_proto_and_ip (sep_ext->transport_proto,
1530  sep_ext->is_ip4);
1531  ll->transport_listener_index = ~0;
1532  ll->app_index = app->app_index;
1533 
1534  app_listener = app_local_listener_alloc (app);
1535  ll->listener_db_index = app_listener->al_index;
1536  app_listener->workers = clib_bitmap_set (app_listener->workers,
1537  app_wrk->wrk_map_index, 1);
1538 
1539  *handle = application_local_session_handle (ll);
1540  session_lookup_add_session_endpoint (table_index, sep, *handle);
1541 
1542  return 0;
1543 }
1544 
1545 /**
1546  * Clean up local session table. If we have a listener session use it to
1547  * find the port and proto. If not, the handle must be a local table handle
1548  * so parse it.
1549  */
1550 int
1551 application_stop_local_listen (u32 app_index, u32 wrk_map_index,
1552  session_handle_t lh)
1553 {
1555  u32 table_index, ll_index, server_index;
1556  app_listener_t *app_listener;
1557  app_worker_t *server_wrk;
1558  stream_session_t *sl = 0;
1559  local_session_t *ll, *ls;
1560  application_t *server;
1561 
1562  server = application_get (app_index);
1563  table_index = application_local_session_table (server);
1564 
1565  /* We have both local and global table binds. Figure from global what
1566  * the sep we should be cleaning up is.
1567  */
1568  if (!session_handle_is_local (lh))
1569  {
1571  if (!sl || listen_session_get_local_session_endpoint (sl, &sep))
1572  {
1573  clib_warning ("broken listener");
1574  return -1;
1575  }
1576  lh = session_lookup_endpoint_listener (table_index, &sep, 0);
1577  if (lh == SESSION_INVALID_HANDLE)
1578  return -1;
1579  }
1580 
1581  local_session_parse_handle (lh, &server_index, &ll_index);
1582  if (PREDICT_FALSE (server_index != app_index))
1583  {
1584  clib_warning ("app %u does not own local handle 0x%lx", app_index, lh);
1585  return -1;
1586  }
1587 
1588  ll = application_get_local_listen_session (server, ll_index);
1589  if (PREDICT_FALSE (!ll))
1590  {
1591  clib_warning ("no local listener");
1592  return -1;
1593  }
1594 
1595  app_listener = app_local_listener_get (server, ll->listener_db_index);
1596  if (!clib_bitmap_get (app_listener->workers, wrk_map_index))
1597  {
1598  clib_warning ("app wrk %u not listening on handle %lu", wrk_map_index,
1599  lh);
1600  return -1;
1601  }
1602 
1603  server_wrk = application_get_worker (server, wrk_map_index);
1604  /* *INDENT-OFF* */
1605  pool_foreach (ls, server_wrk->local_sessions, ({
1606  if (ls->listener_index == ll->session_index)
1607  application_local_session_disconnect (server_wrk->app_index, ls);
1608  }));
1609  /* *INDENT-ON* */
1610 
1611  clib_bitmap_set_no_check (app_listener->workers, wrk_map_index, 0);
1612  if (clib_bitmap_is_zero (app_listener->workers))
1613  {
1614  app_local_listener_free (server, app_listener);
1616  session_lookup_del_session_endpoint (table_index, &sep);
1618  }
1619 
1620  return 0;
1621 }
1622 
1623 static void
1625 {
1626  int fd;
1627 
1628  /*
1629  * segment manager initializes only the producer eventds, since vpp is
1630  * typically the producer. But for local sessions, we also pass to the
1631  * apps the mqs they listen on for events from peer apps, so they are also
1632  * consumer fds.
1633  */
1638 }
1639 
1640 int
1642  app_worker_t * server_wrk,
1643  local_session_t * ll, u32 opaque)
1644 {
1645  u32 seg_size, evt_q_sz, evt_q_elts, margin = 16 << 10;
1646  u32 round_rx_fifo_sz, round_tx_fifo_sz, sm_index;
1647  segment_manager_properties_t *props, *cprops;
1648  int rv, has_transport, seg_index;
1650  application_t *server, *client;
1651  segment_manager_t *sm;
1652  local_session_t *ls;
1653  svm_msg_q_t *sq, *cq;
1654  u64 segment_handle;
1655 
1656  ls = application_local_session_alloc (server_wrk);
1657  server = application_get (server_wrk->app_index);
1658  client = application_get (client_wrk->app_index);
1659 
1660  props = application_segment_manager_properties (server);
1661  cprops = application_segment_manager_properties (client);
1662  evt_q_elts = props->evt_q_size + cprops->evt_q_size;
1663  evt_q_sz = segment_manager_evt_q_expected_size (evt_q_elts);
1664  round_rx_fifo_sz = 1 << max_log2 (props->rx_fifo_size);
1665  round_tx_fifo_sz = 1 << max_log2 (props->tx_fifo_size);
1666  seg_size = round_rx_fifo_sz + round_tx_fifo_sz + evt_q_sz + margin;
1667 
1668  has_transport = session_has_transport ((stream_session_t *) ll);
1669  if (!has_transport)
1670  {
1671  /* Local sessions don't have backing transport */
1672  ls->port = ll->port;
1673  sm = application_get_local_segment_manager (server_wrk);
1674  }
1675  else
1676  {
1677  stream_session_t *sl = (stream_session_t *) ll;
1679  tc = listen_session_get_transport (sl);
1680  ls->port = tc->lcl_port;
1681  sm = app_worker_get_listen_segment_manager (server_wrk, sl);
1682  }
1683 
1684  seg_index = segment_manager_add_segment (sm, seg_size);
1685  if (seg_index < 0)
1686  {
1687  clib_warning ("failed to add new cut-through segment");
1688  return seg_index;
1689  }
1690  seg = segment_manager_get_segment_w_lock (sm, seg_index);
1691  sq = segment_manager_alloc_queue (seg, props);
1692  cq = segment_manager_alloc_queue (seg, cprops);
1693 
1694  if (props->use_mq_eventfd)
1696 
1697  ls->server_evt_q = pointer_to_uword (sq);
1698  ls->client_evt_q = pointer_to_uword (cq);
1699  rv = segment_manager_try_alloc_fifos (seg, props->rx_fifo_size,
1700  props->tx_fifo_size,
1701  &ls->server_rx_fifo,
1702  &ls->server_tx_fifo);
1703  if (rv)
1704  {
1705  clib_warning ("failed to add fifos in cut-through segment");
1707  goto failed;
1708  }
1709  sm_index = segment_manager_index (sm);
1710  ls->server_rx_fifo->ct_session_index = ls->session_index;
1711  ls->server_tx_fifo->ct_session_index = ls->session_index;
1712  ls->server_rx_fifo->segment_manager = sm_index;
1713  ls->server_tx_fifo->segment_manager = sm_index;
1714  ls->server_rx_fifo->segment_index = seg_index;
1715  ls->server_tx_fifo->segment_index = seg_index;
1716  ls->svm_segment_index = seg_index;
1717  ls->listener_index = ll->session_index;
1718  ls->client_wrk_index = client_wrk->wrk_index;
1719  ls->client_opaque = opaque;
1722 
1723  segment_handle = segment_manager_segment_handle (sm, seg);
1724  if ((rv = server->cb_fns.add_segment_callback (server_wrk->api_client_index,
1725  segment_handle)))
1726  {
1727  clib_warning ("failed to notify server of new segment");
1729  goto failed;
1730  }
1732  if ((rv = server->cb_fns.session_accept_callback ((stream_session_t *) ls)))
1733  {
1734  clib_warning ("failed to send accept cut-through notify to server");
1735  goto failed;
1736  }
1737  if (server->flags & APP_OPTIONS_FLAGS_IS_BUILTIN)
1739 
1740  return 0;
1741 
1742 failed:
1743  if (!has_transport)
1744  segment_manager_del_segment (sm, seg);
1745  return rv;
1746 }
1747 
1748 static u64
1750 {
1751  return (((u64) ls->app_wrk_index) << 32 | (u64) ls->session_index);
1752 }
1753 
1754 static void
1756  u32 * session_index)
1757 {
1758  *app_wrk_index = key >> 32;
1759  *session_index = key & 0xFFFFFFFF;
1760 }
1761 
1762 int
1764 {
1766  app_worker_t *client_wrk, *server_wrk;
1767  segment_manager_t *sm;
1768  application_t *client;
1769  int rv, is_fail = 0;
1770  u64 segment_handle;
1771  u64 client_key;
1772 
1773  client_wrk = app_worker_get (ls->client_wrk_index);
1774  server_wrk = app_worker_get (ls->app_wrk_index);
1775  client = application_get (client_wrk->app_index);
1776 
1779  segment_handle = segment_manager_segment_handle (sm, seg);
1780  if ((rv = client->cb_fns.add_segment_callback (client_wrk->api_client_index,
1781  segment_handle)))
1782  {
1783  clib_warning ("failed to notify client %u of new segment",
1784  ls->client_wrk_index);
1787  is_fail = 1;
1788  }
1789  else
1790  {
1792  }
1793 
1794  client->cb_fns.session_connected_callback (client_wrk->wrk_index,
1795  ls->client_opaque,
1796  (stream_session_t *) ls,
1797  is_fail);
1798 
1799  client_key = application_client_local_connect_key (ls);
1800  hash_set (client_wrk->local_connects, client_key, client_key);
1801  return 0;
1802 }
1803 
1804 int
1806  app_worker_t * server_wrk,
1807  local_session_t * ls)
1808 {
1811  segment_manager_t *sm;
1812  u64 client_key;
1813  u8 has_transport;
1814 
1815  /* Retrieve listener transport type as it is the one that decides where
1816  * the fifos are allocated */
1818  if (!has_transport)
1820  else
1821  {
1822  listener = listen_session_get (ls->listener_index);
1823  sm = app_worker_get_listen_segment_manager (server_wrk, listener);
1824  }
1825 
1827  if (client_wrk)
1828  {
1829  client_key = application_client_local_connect_key (ls);
1830  hash_unset (client_wrk->local_connects, client_key);
1831  }
1832 
1833  if (!has_transport)
1834  {
1835  application_t *server = application_get (server_wrk->app_index);
1836  u64 segment_handle = segment_manager_segment_handle (sm, seg);
1837  server->cb_fns.del_segment_callback (server_wrk->api_client_index,
1838  segment_handle);
1839  if (client_wrk)
1840  {
1841  application_t *client = application_get (client_wrk->app_index);
1842  client->cb_fns.del_segment_callback (client_wrk->api_client_index,
1843  segment_handle);
1844  }
1845  segment_manager_del_segment (sm, seg);
1846  }
1847 
1848  application_local_session_free (server_wrk, ls);
1849 
1850  return 0;
1851 }
1852 
1853 int
1855 {
1856  app_worker_t *client_wrk, *server_wrk;
1857  u8 is_server = 0, is_client = 0;
1858  application_t *app;
1859 
1860  app = application_get_if_valid (app_index);
1861  if (!app)
1862  return 0;
1863 
1864  client_wrk = app_worker_get_if_valid (ls->client_wrk_index);
1865  server_wrk = app_worker_get (ls->app_wrk_index);
1866 
1867  if (server_wrk->app_index == app_index)
1868  is_server = 1;
1869  else if (client_wrk && client_wrk->app_index == app_index)
1870  is_client = 1;
1871 
1872  if (!is_server && !is_client)
1873  {
1874  clib_warning ("app %u is neither client nor server for session 0x%lx",
1875  app_index, application_local_session_handle (ls));
1876  return VNET_API_ERROR_INVALID_VALUE;
1877  }
1878 
1880  return application_local_session_cleanup (client_wrk, server_wrk, ls);
1881 
1882  if (app_index == ls->client_wrk_index)
1883  {
1885  }
1886  else
1887  {
1888  if (!client_wrk)
1889  {
1890  return application_local_session_cleanup (client_wrk, server_wrk,
1891  ls);
1892  }
1893  else if (ls->session_state < SESSION_STATE_READY)
1894  {
1895  application_t *client = application_get (client_wrk->app_index);
1896  client->cb_fns.session_connected_callback (client_wrk->wrk_index,
1897  ls->client_opaque,
1898  (stream_session_t *) ls,
1899  1 /* is_fail */ );
1901  return application_local_session_cleanup (client_wrk, server_wrk,
1902  ls);
1903  }
1904  else
1905  {
1907  }
1908  }
1909 
1911 
1912  return 0;
1913 }
1914 
1915 int
1917 {
1918  app_worker_t *app_wrk;
1919  local_session_t *ls;
1920  app_wrk = app_worker_get (app_wrk_index);
1921  ls = application_get_local_session (app_wrk, ls_index);
1922  return application_local_session_disconnect (app_wrk_index, ls);
1923 }
1924 
1925 void
1927 {
1928  u32 index, server_wrk_index, session_index;
1929  u64 handle, *handles = 0;
1930  app_worker_t *server_wrk;
1931  segment_manager_t *sm;
1932  local_session_t *ls;
1933  int i;
1934 
1935  /*
1936  * Local sessions
1937  */
1938  if (app_wrk->local_sessions)
1939  {
1940  /* *INDENT-OFF* */
1941  pool_foreach (ls, app_wrk->local_sessions, ({
1942  application_local_session_disconnect (app_wrk->wrk_index, ls);
1943  }));
1944  /* *INDENT-ON* */
1945  }
1946 
1947  /*
1948  * Local connects
1949  */
1950  vec_reset_length (handles);
1951  /* *INDENT-OFF* */
1952  hash_foreach (handle, index, app_wrk->local_connects, ({
1953  vec_add1 (handles, handle);
1954  }));
1955  /* *INDENT-ON* */
1956 
1957  for (i = 0; i < vec_len (handles); i++)
1958  {
1960  &server_wrk_index,
1961  &session_index);
1962  server_wrk = app_worker_get_if_valid (server_wrk_index);
1963  if (server_wrk)
1964  {
1965  ls = application_get_local_session (server_wrk, session_index);
1967  }
1968  }
1969 
1971  sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
1972  segment_manager_del (sm);
1973 }
1974 
1975 clib_error_t *
1977 {
1978  application_t *app;
1979  app = application_get (a->app_index);
1980  if (!app)
1981  return clib_error_return_code (0, VNET_API_ERROR_APPLICATION_NOT_ATTACHED,
1982  0, "app %u doesn't exist", a->app_index);
1983  app->tls_cert = vec_dup (a->cert);
1984  return 0;
1985 }
1986 
1987 clib_error_t *
1989 {
1990  application_t *app;
1991  app = application_get (a->app_index);
1992  if (!app)
1993  return clib_error_return_code (0, VNET_API_ERROR_APPLICATION_NOT_ATTACHED,
1994  0, "app %u doesn't exist", a->app_index);
1995  app->tls_key = vec_dup (a->key);
1996  return 0;
1997 }
1998 
1999 u8 *
2000 format_app_worker_listener (u8 * s, va_list * args)
2001 {
2002  app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
2003  u64 handle = va_arg (*args, u64);
2004  u32 sm_index = va_arg (*args, u32);
2005  int verbose = va_arg (*args, int);
2007  const u8 *app_name;
2008  u8 *str;
2009 
2010  if (!app_wrk)
2011  {
2012  if (verbose)
2013  s = format (s, "%-40s%-25s%=10s%-15s%-15s%-10s", "Connection", "App",
2014  "Wrk", "API Client", "ListenerID", "SegManager");
2015  else
2016  s = format (s, "%-40s%-25s%=10s", "Connection", "App", "Wrk");
2017 
2018  return s;
2019  }
2020 
2021  app_name = application_name_from_index (app_wrk->app_index);
2022  listener = listen_session_get_from_handle (handle);
2023  str = format (0, "%U", format_stream_session, listener, verbose);
2024 
2025  if (verbose)
2026  {
2027  char buf[32];
2028  sprintf (buf, "%u(%u)", app_wrk->wrk_map_index, app_wrk->wrk_index);
2029  s = format (s, "%-40s%-25s%=10s%-15u%-15u%-10u", str, app_name,
2030  buf, app_wrk->api_client_index, handle, sm_index);
2031  }
2032  else
2033  s = format (s, "%-40s%-25s%=10u", str, app_name, app_wrk->wrk_map_index);
2034 
2035  return s;
2036 }
2037 
2038 static void
2040 {
2042  app_worker_map_t *wrk_map;
2043  app_worker_t *app_wrk;
2044  u32 sm_index;
2045  u64 handle;
2046 
2047  if (!app)
2048  {
2049  vlib_cli_output (vm, "%U", format_app_worker_listener, 0 /* header */ ,
2050  0, 0, verbose);
2051  return;
2052  }
2053 
2054  /* *INDENT-OFF* */
2055  pool_foreach (wrk_map, app->worker_maps, ({
2056  app_wrk = app_worker_get (wrk_map->wrk_index);
2057  if (hash_elts (app_wrk->listeners_table) == 0)
2058  continue;
2059  hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
2060  vlib_cli_output (vm, "%U", format_app_worker_listener, app_wrk,
2061  handle, sm_index, verbose);
2062  }));
2063  }));
2064  /* *INDENT-ON* */
2065 }
2066 
2067 static void
2069 {
2070  svm_fifo_segment_private_t *fifo_segment;
2072  segment_manager_t *sm;
2073  const u8 *app_name;
2074  u8 *s = 0;
2075 
2076  /* Header */
2077  if (!app_wrk)
2078  {
2079  if (verbose)
2080  vlib_cli_output (vm, "%-40s%-20s%-15s%-10s", "Connection", "App",
2081  "API Client", "SegManager");
2082  else
2083  vlib_cli_output (vm, "%-40s%-20s", "Connection", "App");
2084  return;
2085  }
2086 
2087  if (app_wrk->connects_seg_manager == (u32) ~ 0)
2088  return;
2089 
2090  app_name = application_name_from_index (app_wrk->app_index);
2091 
2092  /* Across all fifo segments */
2093  sm = segment_manager_get (app_wrk->connects_seg_manager);
2094 
2095  /* *INDENT-OFF* */
2096  segment_manager_foreach_segment_w_lock (fifo_segment, sm, ({
2097  svm_fifo_t *fifo;
2098  u8 *str;
2099 
2100  fifo = svm_fifo_segment_get_fifo_list (fifo_segment);
2101  while (fifo)
2102  {
2103  u32 session_index, thread_index;
2104  stream_session_t *session;
2105 
2106  session_index = fifo->master_session_index;
2107  thread_index = fifo->master_thread_index;
2108 
2109  session = session_get (session_index, thread_index);
2110  str = format (0, "%U", format_stream_session, session, verbose);
2111 
2112  if (verbose)
2113  s = format (s, "%-40s%-20s%-15u%-10u", str, app_name,
2114  app_wrk->api_client_index, app_wrk->connects_seg_manager);
2115  else
2116  s = format (s, "%-40s%-20s", str, app_name);
2117 
2118  vlib_cli_output (vm, "%v", s);
2119  vec_reset_length (s);
2120  vec_free (str);
2121 
2122  fifo = fifo->next;
2123  }
2124  vec_free (s);
2125  }));
2126  /* *INDENT-ON* */
2127 
2128 }
2129 
2130 static void
2132 {
2133  app_worker_map_t *wrk_map;
2134  app_worker_t *app_wrk;
2135 
2136  if (!app)
2137  {
2138  app_worker_format_connects (0, verbose);
2139  return;
2140  }
2141 
2142  /* *INDENT-OFF* */
2143  pool_foreach (wrk_map, app->worker_maps, ({
2144  app_wrk = app_worker_get (wrk_map->wrk_index);
2145  app_worker_format_connects (app_wrk, verbose);
2146  }));
2147  /* *INDENT-ON* */
2148 }
2149 
2150 static void
2152 {
2154  local_session_t *ls;
2155  transport_proto_t tp;
2156  u8 *conn = 0;
2157 
2158  /* Header */
2159  if (app_wrk == 0)
2160  {
2161  vlib_cli_output (vm, "%-40s%-15s%-20s", "Connection", "ServerApp",
2162  "ClientApp");
2163  return;
2164  }
2165 
2166  if (!pool_elts (app_wrk->local_sessions)
2167  && !pool_elts (app_wrk->local_connects))
2168  return;
2169 
2170  /* *INDENT-OFF* */
2171  pool_foreach (ls, app_wrk->local_sessions, ({
2172  tp = session_type_transport_proto(ls->listener_session_type);
2173  conn = format (0, "[L][%U] *:%u", format_transport_proto_short, tp,
2174  ls->port);
2175  vlib_cli_output (vm, "%-40v%-15u%-20u", conn, ls->app_wrk_index,
2176  ls->client_wrk_index);
2177  vec_reset_length (conn);
2178  }));
2179  /* *INDENT-ON* */
2180 
2181  vec_free (conn);
2182 }
2183 
2184 static void
2186 {
2188  app_worker_map_t *wrk_map;
2189  app_worker_t *app_wrk;
2190  transport_proto_t tp;
2191  local_session_t *ls;
2192  u8 *conn = 0;
2193 
2194  if (!app)
2195  {
2196  app_worker_format_local_sessions (0, verbose);
2197  return;
2198  }
2199 
2200  /*
2201  * Format local listeners
2202  */
2203 
2204  /* *INDENT-OFF* */
2205  pool_foreach (ls, app->local_listen_sessions, ({
2206  tp = session_type_transport_proto (ls->listener_session_type);
2207  conn = format (0, "[L][%U] *:%u", format_transport_proto_short, tp,
2208  ls->port);
2209  vlib_cli_output (vm, "%-40v%-15u%-20s", conn, ls->app_wrk_index, "*");
2210  vec_reset_length (conn);
2211  }));
2212  /* *INDENT-ON* */
2213 
2214  /*
2215  * Format local accepted/connected sessions
2216  */
2217  /* *INDENT-OFF* */
2218  pool_foreach (wrk_map, app->worker_maps, ({
2219  app_wrk = app_worker_get (wrk_map->wrk_index);
2220  app_worker_format_local_sessions (app_wrk, verbose);
2221  }));
2222  /* *INDENT-ON* */
2223 }
2224 
2225 static void
2227 {
2229  u32 app_wrk_index, session_index;
2230  app_worker_t *server_wrk;
2231  local_session_t *ls;
2232  u64 client_key;
2233  u64 value;
2234 
2235  /* Header */
2236  if (app == 0)
2237  {
2238  if (verbose)
2239  vlib_cli_output (vm, "%-40s%-15s%-20s%-10s", "Connection", "App",
2240  "Peer App", "SegManager");
2241  else
2242  vlib_cli_output (vm, "%-40s%-15s%-20s", "Connection", "App",
2243  "Peer App");
2244  return;
2245  }
2246 
2247  if (!app->local_connects)
2248  return;
2249 
2250  /* *INDENT-OFF* */
2251  hash_foreach (client_key, value, app->local_connects, ({
2252  application_client_local_connect_key_parse (client_key, &app_wrk_index,
2253  &session_index);
2254  server_wrk = app_worker_get (app_wrk_index);
2255  ls = application_get_local_session (server_wrk, session_index);
2256  vlib_cli_output (vm, "%-40s%-15s%-20s", "TODO", ls->app_wrk_index,
2257  ls->client_wrk_index);
2258  }));
2259  /* *INDENT-ON* */
2260 }
2261 
2262 static void
2264 {
2265  app_worker_map_t *wrk_map;
2266  app_worker_t *app_wrk;
2267 
2268  if (!app)
2269  {
2270  app_worker_format_local_connects (0, verbose);
2271  return;
2272  }
2273 
2274  /* *INDENT-OFF* */
2275  pool_foreach (wrk_map, app->worker_maps, ({
2276  app_wrk = app_worker_get (wrk_map->wrk_index);
2277  app_worker_format_local_connects (app_wrk, verbose);
2278  }));
2279  /* *INDENT-ON* */
2280 }
2281 
2282 u8 *
2283 format_application_worker (u8 * s, va_list * args)
2284 {
2285  app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
2286  u32 indent = 1;
2287 
2288  s = format (s, "%U wrk-index %u app-index %u map-index %u "
2289  "api-client-index %d\n", format_white_space, indent,
2290  app_wrk->wrk_index, app_wrk->app_index, app_wrk->wrk_map_index,
2291  app_wrk->api_client_index);
2292  return s;
2293 }
2294 
2295 u8 *
2296 format_application (u8 * s, va_list * args)
2297 {
2298  application_t *app = va_arg (*args, application_t *);
2299  CLIB_UNUSED (int verbose) = va_arg (*args, int);
2301  const u8 *app_ns_name, *app_name;
2302  app_worker_map_t *wrk_map;
2303  app_worker_t *app_wrk;
2304 
2305  if (app == 0)
2306  {
2307  if (!verbose)
2308  s = format (s, "%-10s%-20s%-40s", "Index", "Name", "Namespace");
2309  return s;
2310  }
2311 
2312  app_name = app_get_name (app);
2313  app_ns_name = app_namespace_id_from_index (app->ns_index);
2315  if (!verbose)
2316  {
2317  s = format (s, "%-10u%-20s%-40s", app->app_index, app_name,
2318  app_ns_name);
2319  return s;
2320  }
2321 
2322  s = format (s, "app-name %s app-index %u ns-index %u seg-size %U\n",
2323  app_name, app->app_index, app->ns_index,
2324  format_memory_size, props->add_segment_size);
2325  s = format (s, "rx-fifo-size %U tx-fifo-size %U workers:\n",
2326  format_memory_size, props->rx_fifo_size,
2327  format_memory_size, props->tx_fifo_size);
2328 
2329  /* *INDENT-OFF* */
2330  pool_foreach (wrk_map, app->worker_maps, ({
2331  app_wrk = app_worker_get (wrk_map->wrk_index);
2332  s = format (s, "%U", format_application_worker, app_wrk);
2333  }));
2334  /* *INDENT-ON* */
2335 
2336  return s;
2337 }
2338 
2339 void
2340 application_format_all_listeners (vlib_main_t * vm, int do_local, int verbose)
2341 {
2342  application_t *app;
2343 
2344  if (!pool_elts (app_main.app_pool))
2345  {
2346  vlib_cli_output (vm, "No active server bindings");
2347  return;
2348  }
2349 
2350  if (do_local)
2351  {
2352  application_format_local_sessions (0, verbose);
2353  /* *INDENT-OFF* */
2354  pool_foreach (app, app_main.app_pool, ({
2355  application_format_local_sessions (app, verbose);
2356  }));
2357  /* *INDENT-ON* */
2358  }
2359  else
2360  {
2361  application_format_listeners (0, verbose);
2362 
2363  /* *INDENT-OFF* */
2364  pool_foreach (app, app_main.app_pool, ({
2365  application_format_listeners (app, verbose);
2366  }));
2367  /* *INDENT-ON* */
2368  }
2369 }
2370 
2371 void
2372 application_format_all_clients (vlib_main_t * vm, int do_local, int verbose)
2373 {
2374  application_t *app;
2375 
2376  if (!pool_elts (app_main.app_pool))
2377  {
2378  vlib_cli_output (vm, "No active apps");
2379  return;
2380  }
2381 
2382  if (do_local)
2383  {
2384  application_format_local_connects (0, verbose);
2385 
2386  /* *INDENT-OFF* */
2387  pool_foreach (app, app_main.app_pool, ({
2388  application_format_local_connects (app, verbose);
2389  }));
2390  /* *INDENT-ON* */
2391  }
2392  else
2393  {
2394  application_format_connects (0, verbose);
2395 
2396  /* *INDENT-OFF* */
2397  pool_foreach (app, app_main.app_pool, ({
2398  application_format_connects (app, verbose);
2399  }));
2400  /* *INDENT-ON* */
2401  }
2402 }
2403 
2404 static clib_error_t *
2406  vlib_cli_command_t * cmd)
2407 {
2408  int do_server = 0, do_client = 0, do_local = 0;
2409  application_t *app;
2410  u32 app_index = ~0;
2411  int verbose = 0;
2412 
2414 
2415  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2416  {
2417  if (unformat (input, "server"))
2418  do_server = 1;
2419  else if (unformat (input, "client"))
2420  do_client = 1;
2421  else if (unformat (input, "local"))
2422  do_local = 1;
2423  else if (unformat (input, "%u", &app_index))
2424  ;
2425  else if (unformat (input, "verbose"))
2426  verbose = 1;
2427  else
2428  return clib_error_return (0, "unknown input `%U'",
2429  format_unformat_error, input);
2430  }
2431 
2432  if (do_server)
2433  {
2434  application_format_all_listeners (vm, do_local, verbose);
2435  return 0;
2436  }
2437 
2438  if (do_client)
2439  {
2440  application_format_all_clients (vm, do_local, verbose);
2441  return 0;
2442  }
2443 
2444  if (app_index != ~0)
2445  {
2446  app = application_get_if_valid (app_index);
2447  if (!app)
2448  return clib_error_return (0, "No app with index %u", app_index);
2449 
2450  vlib_cli_output (vm, "%U", format_application, app, /* verbose */ 1);
2451  return 0;
2452  }
2453 
2454  /* Print app related info */
2455  if (!do_server && !do_client)
2456  {
2457  vlib_cli_output (vm, "%U", format_application, 0, 0);
2458  /* *INDENT-OFF* */
2459  pool_foreach (app, app_main.app_pool, ({
2460  vlib_cli_output (vm, "%U", format_application, app, 0);
2461  }));
2462  /* *INDENT-ON* */
2463  }
2464 
2465  return 0;
2466 }
2467 
2468 /* *INDENT-OFF* */
2469 VLIB_CLI_COMMAND (show_app_command, static) =
2470 {
2471  .path = "show app",
2472  .short_help = "show app [server|client] [verbose]",
2473  .function = show_app_command_fn,
2474 };
2475 /* *INDENT-ON* */
2476 
2477 /*
2478  * fd.io coding-style-patch-verification: ON
2479  *
2480  * Local Variables:
2481  * eval: (c-set-style "gnu")
2482  * End:
2483  */
static void application_name_table_del(application_t *app)
Definition: application.c:175
u32 flags
Flags.
Definition: application.h:127
static app_listener_t * app_local_listener_alloc(application_t *app)
Definition: application.c:49
int application_stop_listen(u32 app_index, u32 app_wrk_index, session_handle_t handle)
Stop listening on session associated to handle.
Definition: application.c:859
struct _vnet_app_worker_add_del_args vnet_app_worker_add_del_args_t
session_type_t listener_session_type
Has transport embedded when listener not purely local.
app_worker_t * app_worker_get(u32 wrk_index)
Definition: application.c:517
static int app_send_io_evt_rx(app_worker_t *app_wrk, stream_session_t *s, u8 lock)
Definition: application.c:1304
static u8 svm_msg_q_msg_is_invalid(svm_msg_q_msg_t *msg)
Check if message is invalid.
int application_local_session_disconnect_w_index(u32 app_wrk_index, u32 ls_index)
Definition: application.c:1916
#define hash_set(h, key, value)
Definition: hash.h:255
void segment_manager_segment_reader_unlock(segment_manager_t *sm)
void * svm_msg_q_msg_data(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Get data for message in queue.
static u8 svm_msg_q_ring_is_full(svm_msg_q_t *mq, u32 ring_index)
application_t * app_worker_get_app(u32 wrk_index)
Definition: application.c:645
int session_open(u32 app_wrk_index, session_endpoint_t *rmt, u32 opaque)
Ask transport to open connection to remote transport endpoint.
Definition: session.c:1061
#define CLIB_UNUSED(x)
Definition: clib.h:82
static session_handle_t application_local_session_handle(local_session_t *ls)
Definition: application.h:352
int app_worker_alloc_and_init(application_t *app, app_worker_t **wrk)
Definition: application.c:597
#define hash_unset(h, key)
Definition: hash.h:261
a
Definition: bitmap.h:538
u64 session_lookup_endpoint_listener(u32 table_index, session_endpoint_t *sep, u8 use_rules)
Lookup listener for session endpoint in table.
u32 ns_index
Namespace the application belongs to.
Definition: application.h:142
u8 application_has_global_scope(application_t *app)
Definition: application.c:1048
u8 app_worker_application_is_builtin(app_worker_t *app_wrk)
Definition: application.c:1102
int app_worker_add_segment_notify(u32 app_wrk_index, u64 segment_handle)
Send an API message to the external app, to map new segment.
Definition: application.c:1063
struct _transport_connection transport_connection_t
struct _segment_manager_properties segment_manager_properties_t
int app_worker_stop_listen(app_worker_t *app_wrk, session_handle_t handle)
Definition: application.c:699
app_worker_t * app_worker_alloc(application_t *app)
Definition: application.c:501
void app_worker_free(app_worker_t *app_wrk)
Definition: application.c:531
#define session_cli_return_if_not_enabled()
Definition: session.h:720
segment_manager_properties_t * application_get_segment_manager_properties(u32 app_index)
Definition: application.c:1270
static clib_error_t * show_app_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: application.c:2405
unsigned long u64
Definition: types.h:89
clib_error_t * vnet_unbind(vnet_unbind_args_t *a)
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
svm_msg_q_t * segment_manager_alloc_queue(svm_fifo_segment_private_t *segment, segment_manager_properties_t *props)
Allocates shm queue in the first segment.
app_worker_t * application_listener_select_worker(stream_session_t *ls, u8 is_local)
Definition: application.c:478
#define SESSION_PROXY_LISTENER_INDEX
Definition: session.h:27
static app_listener_t * app_listener_get(application_t *app, u32 app_listener_index)
Definition: application.c:34
application_t * application_lookup_name(const u8 *name)
Definition: application.c:192
u32 session_lookup_get_index_for_fib(u32 fib_proto, u32 fib_index)
int app_worker_own_session(app_worker_t *app_wrk, stream_session_t *s)
Definition: application.c:728
local_session_t * local_listen_sessions
Pool of local listen sessions.
Definition: application.h:153
local_session_t * application_get_local_session_from_handle(session_handle_t handle)
Definition: application.c:1453
int application_local_session_connect(app_worker_t *client_wrk, app_worker_t *server_wrk, local_session_t *ll, u32 opaque)
Definition: application.c:1641
static int svm_msg_q_get_producer_eventfd(svm_msg_q_t *mq)
application_t * application_lookup(u32 api_client_index)
Definition: application.c:181
void application_free(application_t *app)
Definition: application.c:355
app_listener_t * listeners
Pool of listeners for the app.
Definition: application.h:147
u32 wrk_map_index
Worker index in app&#39;s map pool.
Definition: application.h:68
int i
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
#define hash_set_mem(h, key, value)
Definition: hash.h:275
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
static app_send_evt_handler_fn *const app_send_evt_handler_fns[3]
Definition: application.c:1391
void svm_fifo_dequeue_drop_all(svm_fifo_t *f)
Definition: svm_fifo.c:774
svm_fifo_t * server_tx_fifo
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
void segment_manager_dealloc_fifos(u32 segment_index, svm_fifo_t *rx_fifo, svm_fifo_t *tx_fifo)
int session_listen(stream_session_t *ls, session_endpoint_cfg_t *sep)
Ask transport to listen on session endpoint.
Definition: session.c:1076
void app_worker_local_sessions_free(app_worker_t *app_wrk)
Definition: application.c:1926
u64 session_handle_t
Definition: session.h:111
segment_manager_properties_t * segment_manager_properties_init(segment_manager_properties_t *props)
uword * listeners_table
Lookup tables for listeners.
Definition: application.h:80
#define segment_manager_foreach_segment_w_lock(VAR, SM, BODY)
struct _vnet_application_add_tls_cert_args_t vnet_app_add_tls_cert_args_t
int app_worker_start_listen(app_worker_t *app_wrk, stream_session_t *ls)
Definition: application.c:675
static void application_client_local_connect_key_parse(u64 key, u32 *app_wrk_index, u32 *session_index)
Definition: application.c:1755
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
u32 connects_seg_manager
Segment manager used for outgoing connects issued by the app.
Definition: application.h:77
u8 application_use_mq_for_ctrl(application_t *app)
Definition: application.c:1054
u32 segment_manager_evt_q_expected_size(u32 q_len)
clib_error_t * vnet_app_add_tls_cert(vnet_app_add_tls_cert_args_t *a)
Definition: application.c:1976
unsigned char u8
Definition: types.h:56
static stream_session_t * listen_session_get_from_handle(session_handle_t handle)
Definition: session.h:672
app_worker_t * application_get_worker(application_t *app, u32 wrk_map_index)
Definition: application.c:456
void application_local_session_free(app_worker_t *app, local_session_t *s)
Definition: application.c:1437
int segment_manager_init(segment_manager_t *sm, u32 first_seg_size, u32 prealloc_fifo_pairs)
Initializes segment manager based on options provided.
application_t * application_get_if_valid(u32 app_index)
Definition: application.c:221
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
#define SESSION_ENDPOINT_NULL
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
segment_manager_t * app_worker_get_listen_segment_manager(app_worker_t *app, stream_session_t *listener)
Definition: application.c:943
static u64 application_client_local_connect_key(local_session_t *ls)
Definition: application.c:1749
int session_stop_listen(stream_session_t *s)
Ask transport to stop listening on local transport endpoint.
Definition: session.c:1106
connectionless service
int application_is_proxy(application_t *app)
Definition: application.c:1024
static int svm_fifo_is_empty(svm_fifo_t *f)
Definition: svm_fifo.h:136
enum ssvm_segment_type_ ssvm_segment_type_t
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:490
u32 first_segment_manager
First segment manager has in the the first segment the application&#39;s event fifo.
Definition: application.h:87
void application_detach_process(application_t *app, u32 api_client_index)
Definition: application.c:412
static uword clib_bitmap_is_zero(uword *ai)
predicate function; is an entire bitmap empty?
Definition: bitmap.h:57
int application_local_session_connect_notify(local_session_t *ls)
Definition: application.c:1763
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
u32 transport_listener_index
Transport listener index.
struct _stream_session_cb_vft session_cb_vft_t
struct _vnet_unbind_args_t vnet_unbind_args_t
svm_fifo_segment_private_t * segment_manager_get_segment_w_lock(segment_manager_t *sm, u32 segment_index)
Reads a segment from the segment manager&#39;s pool and acquires reader lock.
app_listener_t * local_listeners
Pool of local listeners for app.
Definition: application.h:150
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
session_type_t session_type
Type.
u8 * format_memory_size(u8 *s, va_list *va)
Definition: std-formats.c:193
static stream_session_t * listen_session_get(u32 index)
Definition: session.h:695
#define transport_proto_foreach(VAR, BODY)
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
static local_session_t * application_get_local_listen_session(application_t *app, u32 session_index)
Definition: application.h:359
u16 proxied_transports
Definition: application.h:144
struct _stream_session_t stream_session_t
u8 tls_engine
Preferred tls engine.
Definition: application.h:166
segment_manager_t * segment_manager_new()
struct _session_endpoint_cfg session_endpoint_cfg_t
static const u8 * app_get_name(application_t *app)
Definition: application.c:103
#define pool_flush(VAR, POOL, BODY)
Remove all elements from a pool in a safe way.
Definition: pool.h:550
static app_main_t app_main
Definition: application.c:21
static void application_verify_cb_fns(session_cb_vft_t *cb_fns)
Definition: application.c:230
clib_error_t * vnet_app_add_tls_key(vnet_app_add_tls_key_args_t *a)
Definition: application.c:1988
app_worker_t * workers
Pool of workers associated to apps.
Definition: application.h:180
static void listen_session_del(stream_session_t *s)
Definition: session.h:701
static int app_enqueue_evt(svm_msg_q_t *mq, svm_msg_q_msg_t *msg, u8 lock)
Definition: application.c:1277
int application_is_builtin(application_t *app)
Definition: application.c:1030
#define hash_get(h, key)
Definition: hash.h:249
u32 app_namespace_get_fib_index(app_namespace_t *app_ns, u8 fib_proto)
static svm_fifo_t * svm_fifo_segment_get_fifo_list(svm_fifo_segment_private_t *fifo_segment)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:511
#define hash_unset_mem(h, key)
Definition: hash.h:291
#define VL_API_INVALID_FI
Definition: api_common.h:76
struct _session_endpoint session_endpoint_t
static uword clib_bitmap_first_set(uword *ai)
Return the lowest numbered set bit in a bitmap.
Definition: bitmap.h:385
static void application_api_table_del(u32 api_client_index)
Definition: application.c:163
stream_session_t * application_proxy_listener(app_worker_t *app, u8 fib_proto, u8 transport_proto)
Definition: application.c:1108
svm_fifo_t * server_rx_fifo
fifo pointers.
u8 * format_application_worker(u8 *s, va_list *args)
Definition: application.c:2283
app_worker_t * app_worker_get_if_valid(u32 wrk_index)
Definition: application.c:523
static u8 session_handle_is_local(session_handle_t handle)
Definition: session.h:407
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
const u8 * application_name_from_index(u32 app_index)
Returns app name for app-index.
Definition: application.c:147
static u32 app_worker_map_index(application_t *app, app_worker_map_t *map)
Definition: application.c:83
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
#define APP_INVALID_INDEX
Definition: application.h:219
local_session_t * application_local_listen_session_alloc(application_t *app)
Definition: application.c:1465
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:375
u32 application_local_listener_index(application_t *app, local_session_t *ll)
Definition: application.c:1474
svm_fifo_segment_private_t * segment_manager_get_segment(segment_manager_t *sm, u32 segment_index)
Reads a segment from the segment manager&#39;s pool without lock.
u8 segment_manager_has_fifos(segment_manager_t *sm)
#define PREDICT_FALSE(x)
Definition: clib.h:111
u32 svm_segment_index
Segment index where fifos were allocated.
static u8 application_local_session_listener_has_transport(local_session_t *ls)
Definition: application.h:375
app_namespace_t * app_namespace_get(u32 index)
u32 wrk_index
Worker index in global worker pool.
Definition: application.h:65
u32 application_session_table(application_t *app, u8 fib_proto)
Definition: application.c:109
static void application_local_session_fix_eventds(svm_msg_q_t *sq, svm_msg_q_t *cq)
Definition: application.c:1624
stream_session_t * app_worker_first_listener(app_worker_t *app, u8 fib_proto, u8 transport_proto)
Definition: application.c:1078
void segment_manager_del_segment(segment_manager_t *sm, svm_fifo_segment_private_t *fs)
Remove segment without lock.
int segment_manager_add_segment(segment_manager_t *sm, u32 segment_size)
Adds segment to segment manager&#39;s pool.
u8 name[64]
Definition: memclnt.api:152
volatile u8 session_state
State.
static stream_session_t * session_get(u32 si, u32 thread_index)
Definition: session.h:341
app_worker_map_t * worker_maps
Pool of mappings that keep track of workers associated to this app.
Definition: application.h:136
int session_alloc_fifos(segment_manager_t *sm, stream_session_t *s)
Definition: session.c:202
#define SEGMENT_MANAGER_INVALID_APP_INDEX
#define pool_free(p)
Free a pool.
Definition: pool.h:404
static u8 svm_fifo_set_event(svm_fifo_t *f)
Sets fifo event flag.
Definition: svm_fifo.h:167
An API client registration, only in vpp/vlib.
Definition: api_common.h:45
u32 application_local_session_table(application_t *app)
Definition: application.c:124
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
static int app_send_io_evt_tx(app_worker_t *app_wrk, stream_session_t *s, u8 lock)
Definition: application.c:1356
uword * app_by_name
Hash table of builtin apps by name.
Definition: application.h:190
static session_type_t session_type_from_proto_and_ip(transport_proto_t proto, u8 is_ip4)
Definition: session.h:440
vlib_main_t * vm
Definition: buffer.c:301
static void svm_msg_q_unlock(svm_msg_q_t *mq)
Unlock message queue.
static void app_listener_free(application_t *app, app_listener_t *app_listener)
Definition: application.c:40
static transport_proto_t session_type_transport_proto(session_type_t st)
Definition: session.h:415
static segment_manager_t * app_worker_alloc_segment_manager(app_worker_t *app_wrk)
Definition: application.c:655
u8 * format_stream_session(u8 *s, va_list *args)
Format stream session as per the following format.
Definition: session_cli.c:57
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
transport_service_type_t session_transport_service_type(stream_session_t *s)
Definition: session.c:1211
int session_lookup_del_session_endpoint(u32 table_index, session_endpoint_t *sep)
#define clib_warning(format, args...)
Definition: error.h:59
#define SESSION_INVALID_HANDLE
Definition: session_table.h:59
int svm_msg_q_add(svm_msg_q_t *mq, svm_msg_q_msg_t *msg, int nowait)
Producer enqueue one message to queue.
u32 local_segment_manager
Segment manager used for incoming "cut through" connects.
Definition: application.h:95
clib_bitmap_t * workers
workers accepting connections
Definition: application.h:116
segment_manager_properties_t sm_properties
Segment manager properties.
Definition: application.h:133
u16 port
Port for connection.
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
const u8 * app_namespace_id_from_index(u32 index)
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
blocking call - best used in combination with condvars, for eventfds we don&#39;t yield the cpu ...
Definition: queue.h:42
void application_local_listen_session_free(application_t *app, local_session_t *ll)
Definition: application.c:1480
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:56
int session_lookup_add_session_endpoint(u32 table_index, session_endpoint_t *sep, u64 value)
u32 app_wrk_index
Server index.
static u32 vl_api_registration_file_index(vl_api_registration_t *reg)
Definition: api.h:64
static void application_name_table_add(application_t *app)
Definition: application.c:169
static u8 session_has_transport(stream_session_t *s)
Definition: session.h:454
int segment_manager_try_alloc_fifos(svm_fifo_segment_private_t *fifo_segment, u32 rx_fifo_size, u32 tx_fifo_size, svm_fifo_t **rx_fifo, svm_fifo_t **tx_fifo)
struct _app_namespace app_namespace_t
application_t * application_get(u32 app_index)
Definition: application.c:213
application_t * application_alloc(void)
Definition: application.c:203
static u32 segment_manager_index(segment_manager_t *sm)
int app_worker_lock_and_send_event(app_worker_t *app, stream_session_t *s, u8 evt_type)
Send event to application.
Definition: application.c:1418
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
segment_manager_t * app_worker_get_or_alloc_connect_segment_manager(app_worker_t *app_wrk)
Definition: application.c:935
#define hash_create(elts, value_bytes)
Definition: hash.h:696
ssvm_private_t * session_manager_get_evt_q_segment(void)
Definition: session.c:1305
void segment_manager_init_del(segment_manager_t *sm)
local_session_t * application_local_session_alloc(app_worker_t *app_wrk)
Definition: application.c:1425
static void app_local_listener_free(application_t *app, app_listener_t *app_listener)
Definition: application.c:65
static uword hash_elts(void *v)
Definition: hash.h:118
#define ASSERT(truth)
u32 client_wrk_index
Client data.
void svm_msg_q_add_and_unlock(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Producer enqueue one message to queue with mutex held.
u8 session_type_t
static local_session_t * application_get_local_listener_w_handle(session_handle_t handle)
Definition: application.h:365
static void application_format_local_connects(application_t *app, int verbose)
Definition: application.c:2263
static u8 session_endpoint_fib_proto(session_endpoint_t *sep)
uword * app_by_api_client_index
Hash table of apps by api client index.
Definition: application.h:185
static app_listener_t * app_local_listener_get(application_t *app, u32 app_listener_index)
Definition: application.c:59
void application_remove_proxy(application_t *app)
Definition: application.c:1248
session_cb_vft_t cb_fns
Callbacks: shoulder-taps for the server/client.
Definition: application.h:130
struct _vnet_application_add_tls_key_args_t vnet_app_add_tls_key_args_t
int app_worker_alloc_connects_segment_manager(app_worker_t *app_wrk)
Definition: application.c:913
int listen_session_get_local_session_endpoint(stream_session_t *listener, session_endpoint_t *sep)
Definition: session.c:1378
u8 * tls_key
PEM encoded key.
Definition: application.h:163
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
int application_local_session_disconnect(u32 app_index, local_session_t *ls)
Definition: application.c:1854
void application_format_all_listeners(vlib_main_t *vm, int do_local, int verbose)
Definition: application.c:2340
segment_manager_t * application_get_local_segment_manager(app_worker_t *app)
Definition: application.c:1005
u32 accept_rotor
last worker to accept a connection
Definition: application.h:117
static svm_msg_q_t * segment_manager_event_queue(segment_manager_t *sm)
static uword pointer_to_uword(const void *p)
Definition: types.h:131
int application_alloc_and_init(app_init_args_t *a)
Definition: application.c:270
void svm_msg_q_set_consumer_eventfd(svm_msg_q_t *mq, int fd)
Set event fd for queue consumer.
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u8 * format_app_worker_listener(u8 *s, va_list *args)
Definition: application.c:2000
static void app_worker_format_connects(app_worker_t *app_wrk, int verbose)
Definition: application.c:2068
static void app_worker_format_local_sessions(app_worker_t *app_wrk, int verbose)
Definition: application.c:2151
u8 ip_is_zero(ip46_address_t *ip46_address, u8 is_ip4)
Definition: ip.c:20
u32 application_n_listeners(app_worker_t *app)
Definition: application.c:1072
u32 app_index
App index in app pool.
Definition: application.h:124
void segment_manager_del(segment_manager_t *sm)
Removes segment manager.
int application_start_listen(application_t *app, session_endpoint_cfg_t *sep_ext, session_handle_t *res)
Start listening local transport endpoint for requested transport.
Definition: application.c:777
int application_local_session_cleanup(app_worker_t *client_wrk, app_worker_t *server_wrk, local_session_t *ls)
Definition: application.c:1805
local_session_t * application_get_local_session(app_worker_t *app_wrk, u32 session_index)
Definition: application.c:1445
application_t * app_pool
Pool from which we allocate all applications.
Definition: application.h:175
u64 segment_manager_segment_handle(segment_manager_t *sm, svm_fifo_segment_private_t *segment)
void svm_msg_q_free_msg(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Free message buffer.
enum _transport_proto transport_proto_t
transport_connection_t * listen_session_get_transport(stream_session_t *s)
Definition: session.c:1371
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define SESSION_ENDPOINT_CFG_NULL
u8 * format_application(u8 *s, va_list *args)
Definition: application.c:2296
u8 * name
Name registered by builtin apps.
Definition: application.h:139
static uword max_log2(uword x)
Definition: clib.h:191
static stream_session_t * listen_session_new(u8 thread_index, session_type_t type)
Definition: session.h:685
u64 uword
Definition: types.h:112
u32 session_index
Session index.
void segment_manager_del_sessions(segment_manager_t *sm)
Initiate disconnects for all sessions &#39;owned&#39; by a segment manager.
static app_worker_map_t * app_worker_map_alloc(application_t *app)
Definition: application.c:74
int app_worker_open_session(app_worker_t *app, session_endpoint_t *sep, u32 api_context)
Definition: application.c:898
app_worker_t * application_get_default_worker(application_t *app)
Definition: application.c:466
struct _segment_manager segment_manager_t
u32 application_n_workers(application_t *app)
Definition: application.c:472
static void application_api_table_add(u32 app_index, u32 api_client_index)
Definition: application.c:156
static void application_format_listeners(application_t *app, int verbose)
Definition: application.c:2039
static clib_error_t * application_start_stop_proxy_fib_proto(application_t *app, u8 fib_proto, u8 transport_proto, u8 is_start)
Definition: application.c:1132
#define hash_get_mem(h, key)
Definition: hash.h:269
static void application_format_local_sessions(application_t *app, int verbose)
Definition: application.c:2185
u32 app_index
Index of owning app.
Definition: application.h:71
int( app_send_evt_handler_fn)(app_worker_t *app, stream_session_t *s, u8 lock)
Definition: application.c:1388
static void application_start_stop_proxy_local_scope(application_t *app, u8 transport_proto, u8 is_start)
Definition: application.c:1189
uword * local_connects
Hash table of the app&#39;s local connects.
Definition: application.h:101
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
int application_stop_local_listen(u32 app_index, u32 wrk_map_index, session_handle_t lh)
Clean up local session table.
Definition: application.c:1551
local_session_t * local_sessions
Pool of local sessions the app owns (as a server)
Definition: application.h:98
segment_manager_t * application_get_local_segment_manager_w_session(app_worker_t *app, local_session_t *ls)
Definition: application.c:1011
#define clib_error_return_code(e, code, flags, args...)
Definition: error.h:93
u8 * tls_cert
Certificate to be used for listen sessions.
Definition: application.h:160
static app_worker_map_t * app_worker_map_get(application_t *app, u32 map_index)
Definition: application.c:95
#define vec_foreach(var, vec)
Vector iterator.
static int svm_fifo_has_event(svm_fifo_t *f)
Definition: svm_fifo.h:148
void application_setup_proxy(application_t *app)
Definition: application.c:1232
static u8 application_verify_cfg(ssvm_segment_type_t st)
Check app config for given segment type.
Definition: application.c:248
static void application_format_connects(application_t *app, int verbose)
Definition: application.c:2131
int application_is_builtin_proxy(application_t *app)
Definition: application.c:1036
u32 api_client_index
API index for the worker.
Definition: application.h:104
segment_manager_t * app_worker_get_connect_segment_manager(app_worker_t *app)
Definition: application.c:928
static void app_worker_map_free(application_t *app, app_worker_map_t *map)
Definition: application.c:89
int app_worker_send_event(app_worker_t *app, stream_session_t *s, u8 evt_type)
Send event to application.
Definition: application.c:1405
void application_start_stop_proxy(application_t *app, transport_proto_t transport_proto, u8 is_start)
Definition: application.c:1216
static int svm_msg_q_lock(svm_msg_q_t *mq)
Lock, or block trying, the message queue.
segment_manager_properties_t * application_segment_manager_properties(application_t *app)
Definition: application.c:1264
svm_msg_q_t * event_queue
Application listens for events on this svm queue.
Definition: application.h:74
static void application_local_listener_session_endpoint(local_session_t *ll, session_endpoint_t *sep)
Definition: application.c:134
#define APP_INVALID_SEGMENT_MANAGER_INDEX
Definition: application.h:221
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
static u8 svm_msg_q_is_full(svm_msg_q_t *mq)
Check if message queue is full.
#define APP_DBG(_fmt, _args...)
Definition: application.h:28
static segment_manager_t * segment_manager_get(u32 index)
svm_msg_q_msg_t svm_msg_q_alloc_msg_w_ring(svm_msg_q_t *mq, u32 ring_index)
Allocate message buffer on ring.
static u64 listen_session_get_handle(stream_session_t *s)
Definition: session.h:665
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
u8 first_segment_manager_in_use
Definition: application.h:88
int application_start_local_listen(application_t *app, session_endpoint_cfg_t *sep_ext, session_handle_t *handle)
Definition: application.c:1489
static void local_session_parse_handle(session_handle_t handle, u32 *app_or_wrk_index, u32 *session_index)
Definition: application.h:342
clib_error_t * vnet_app_worker_add_del(vnet_app_worker_add_del_args_t *a)
Definition: application.c:953
void application_format_all_clients(vlib_main_t *vm, int do_local, int verbose)
Definition: application.c:2372
void mq_send_local_session_disconnected_cb(u32 app_or_wrk, local_session_t *ls)
Definition: session_api.c:530
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
static void app_worker_format_local_connects(app_worker_t *app, int verbose)
Definition: application.c:2226
static app_listener_t * app_listener_alloc(application_t *app)
Definition: application.c:24
u8 application_has_local_scope(application_t *app)
Definition: application.c:1042
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128