FD.io VPP  v19.04.1-1-ge4a0f9f
Vector Packet Processing
application_worker.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 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 
18 #include <vnet/session/session.h>
19 
20 /**
21  * Pool of workers associated to apps
22  */
24 
27 {
28  app_worker_t *app_wrk;
29  pool_get (app_workers, app_wrk);
30  clib_memset (app_wrk, 0, sizeof (*app_wrk));
31  app_wrk->wrk_index = app_wrk - app_workers;
32  app_wrk->app_index = app->app_index;
33  app_wrk->wrk_map_index = ~0;
36  APP_DBG ("New app %v worker %u", app_get_name (app), app_wrk->wrk_index);
37  return app_wrk;
38 }
39 
41 app_worker_get (u32 wrk_index)
42 {
43  return pool_elt_at_index (app_workers, wrk_index);
44 }
45 
48 {
49  if (pool_is_free_index (app_workers, wrk_index))
50  return 0;
51  return pool_elt_at_index (app_workers, wrk_index);
52 }
53 
54 void
56 {
57  application_t *app = application_get (app_wrk->app_index);
58  vnet_unlisten_args_t _a, *a = &_a;
59  u64 handle, *handles = 0;
61  u32 sm_index;
62  int i;
63  app_listener_t *al;
64  session_t *ls;
65 
66  /*
67  * Listener cleanup
68  */
69 
70  /* *INDENT-OFF* */
71  hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
72  ls = listen_session_get_from_handle (handle);
73  al = app_listener_get (app, ls->al_index);
74  vec_add1 (handles, app_listener_handle (al));
75  sm = segment_manager_get (sm_index);
76  sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
77  }));
78  /* *INDENT-ON* */
79 
80  for (i = 0; i < vec_len (handles); i++)
81  {
82  a->app_index = app->app_index;
83  a->wrk_map_index = app_wrk->wrk_map_index;
84  a->handle = handles[i];
85  /* seg manager is removed when unbind completes */
86  (void) vnet_unlisten (a);
87  }
88 
89  /*
90  * Connects segment manager cleanup
91  */
92 
94  {
96  sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
97  sm->first_is_protected = 0;
99  }
100 
101  /* If first segment manager is used by a listener */
103  && app_wrk->first_segment_manager != app_wrk->connects_seg_manager)
104  {
106  sm->first_is_protected = 0;
107  sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
108  /* .. and has no fifos, e.g. it might be used for redirected sessions,
109  * remove it */
110  if (!segment_manager_has_fifos (sm))
111  segment_manager_del (sm);
112  }
113 
114  pool_put (app_workers, app_wrk);
115  if (CLIB_DEBUG)
116  clib_memset (app_wrk, 0xfe, sizeof (*app_wrk));
117 }
118 
121 {
122  app_worker_t *app_wrk;
123  app_wrk = app_worker_get_if_valid (wrk_index);
124  if (!app_wrk)
125  return 0;
126  return application_get_if_valid (app_wrk->app_index);
127 }
128 
129 static segment_manager_t *
131 {
132  segment_manager_t *sm = 0;
133 
134  /* If the first segment manager is not in use, don't allocate a new one */
136  && app_wrk->first_segment_manager_in_use == 0)
137  {
139  app_wrk->first_segment_manager_in_use = 1;
140  return sm;
141  }
142 
143  sm = segment_manager_new ();
144  sm->app_wrk_index = app_wrk->wrk_index;
145 
146  return sm;
147 }
148 
149 static int
151 {
152  svm_fifo_t *rx_fifo = 0, *tx_fifo = 0;
153  u32 fifo_segment_index;
154  int rv;
155 
156  if ((rv = segment_manager_alloc_session_fifos (sm, &rx_fifo, &tx_fifo,
157  &fifo_segment_index)))
158  return rv;
159 
160  rx_fifo->master_session_index = s->session_index;
161  rx_fifo->master_thread_index = s->thread_index;
162 
163  tx_fifo->master_session_index = s->session_index;
164  tx_fifo->master_thread_index = s->thread_index;
165 
166  s->rx_fifo = rx_fifo;
167  s->tx_fifo = tx_fifo;
168  return 0;
169 }
170 
171 int
173 {
174  segment_manager_t *sm;
175 
176  /* Allocate segment manager. All sessions derived out of a listen session
177  * have fifos allocated by the same segment manager. */
178  if (!(sm = app_worker_alloc_segment_manager (app_wrk)))
179  return -1;
180 
181  /* Keep track of the segment manager for the listener or this worker */
183  segment_manager_index (sm));
184 
186  {
187  if (!ls->rx_fifo && app_worker_alloc_session_fifos (sm, ls))
188  return -1;
189  }
190  return 0;
191 }
192 
193 int
195  app_listener_t * app_listener)
196 {
197  session_t *ls;
198 
199  if (clib_bitmap_get (app_listener->workers, app_wrk->wrk_map_index))
200  return VNET_API_ERROR_ADDRESS_IN_USE;
201 
202  app_listener->workers = clib_bitmap_set (app_listener->workers,
203  app_wrk->wrk_map_index, 1);
204 
205  if (app_listener->session_index != SESSION_INVALID_INDEX)
206  {
207  ls = session_get (app_listener->session_index, 0);
208  if (app_worker_init_listener (app_wrk, ls))
209  return -1;
210  }
211 
212  if (app_listener->local_index != SESSION_INVALID_INDEX)
213  {
214  ls = session_get (app_listener->local_index, 0);
215  if (app_worker_init_listener (app_wrk, ls))
216  return -1;
217  }
218 
219  return 0;
220 }
221 
222 static void
224 {
225  session_handle_t handle;
226  segment_manager_t *sm;
227  uword *sm_indexp;
228 
229  handle = listen_session_get_handle (ls);
230  sm_indexp = hash_get (app_wrk->listeners_table, handle);
231  if (PREDICT_FALSE (!sm_indexp))
232  return;
233 
234  sm = segment_manager_get (*sm_indexp);
235  if (app_wrk->first_segment_manager == *sm_indexp)
236  {
237  /* Delete sessions but don't remove segment manager */
238  app_wrk->first_segment_manager_in_use = 0;
240  }
241  else
242  {
244  }
245  hash_unset (app_wrk->listeners_table, handle);
246 }
247 
248 int
250 {
251  session_t *ls;
252 
253  if (!clib_bitmap_get (al->workers, app_wrk->wrk_map_index))
254  return 0;
255 
257  {
259  app_worker_stop_listen_session (app_wrk, ls);
260  }
261 
263  {
264  ls = listen_session_get (al->local_index);
265  app_worker_stop_listen_session (app_wrk, ls);
266  }
267 
269  if (clib_bitmap_is_zero (al->workers))
271 
272  return 0;
273 }
274 
275 int
277 {
278  app_worker_t *app_wrk;
279  segment_manager_t *sm;
281 
282  listener = listen_session_get (s->listener_index);
283  app_wrk = application_listener_select_worker (listener);
284  s->app_wrk_index = app_wrk->wrk_index;
285 
286  sm = app_worker_get_listen_segment_manager (app_wrk, listener);
287  if (app_worker_alloc_session_fifos (sm, s))
288  return -1;
289 
290  return 0;
291 }
292 
293 int
295 {
296  application_t *app = application_get (app_wrk->app_index);
297  return app->cb_fns.session_accept_callback (s);
298 }
299 
300 int
302 {
303  application_t *app = application_get (app_wrk->app_index);
304  segment_manager_t *sm;
305 
306  /* Allocate fifos for session, unless the app is a builtin proxy */
307  if (!application_is_builtin_proxy (app))
308  {
310  if (app_worker_alloc_session_fifos (sm, s))
311  return -1;
312  }
313  return 0;
314 }
315 
316 int
318 {
319  application_t *app = application_get (app_wrk->app_index);
320  return app->cb_fns.session_connected_callback (app_wrk->wrk_index, opaque,
321  s, s == 0 /* is_fail */ );
322 }
323 
324 int
326 {
327  application_t *app = application_get (app_wrk->app_index);
328  app->cb_fns.session_disconnect_callback (s);
329  return 0;
330 }
331 
332 int
334 {
335  application_t *app = application_get (app_wrk->app_index);
336  app->cb_fns.session_reset_callback (s);
337  return 0;
338 }
339 
340 int
342 {
343  application_t *app = application_get (app_wrk->app_index);
344  app->cb_fns.builtin_app_rx_callback (s);
345  return 0;
346 }
347 
348 int
350 {
351  segment_manager_t *sm;
352  svm_fifo_t *rxf, *txf;
353 
355  return application_change_listener_owner (s, app_wrk);
356 
357  s->app_wrk_index = app_wrk->wrk_index;
358 
359  rxf = s->rx_fifo;
360  txf = s->tx_fifo;
361 
362  if (!rxf || !txf)
363  return 0;
364 
365  s->rx_fifo = 0;
366  s->tx_fifo = 0;
367 
369  if (app_worker_alloc_session_fifos (sm, s))
370  return -1;
371 
372  if (!svm_fifo_is_empty (rxf))
373  {
374  clib_memcpy_fast (s->rx_fifo->data, rxf->data, rxf->nitems);
375  s->rx_fifo->head = rxf->head;
376  s->rx_fifo->tail = rxf->tail;
377  s->rx_fifo->cursize = rxf->cursize;
378  }
379 
380  if (!svm_fifo_is_empty (txf))
381  {
382  clib_memcpy_fast (s->tx_fifo->data, txf->data, txf->nitems);
383  s->tx_fifo->head = txf->head;
384  s->tx_fifo->tail = txf->tail;
385  s->tx_fifo->cursize = txf->cursize;
386  }
387 
389 
390  return 0;
391 }
392 
393 int
395  u32 api_context)
396 {
397  int rv;
398 
399  /* Make sure we have a segment manager for connects */
401 
402  if ((rv = session_open (app->wrk_index, sep, api_context)))
403  return rv;
404 
405  return 0;
406 }
407 
408 int
410 {
411  segment_manager_t *sm;
412 
414  {
415  sm = app_worker_alloc_segment_manager (app_wrk);
416  if (sm == 0)
417  return -1;
419  }
420  return 0;
421 }
422 
425 {
426  ASSERT (app->connects_seg_manager != (u32) ~ 0);
428 }
429 
432 {
433  if (app_wrk->connects_seg_manager == (u32) ~ 0)
435  return segment_manager_get (app_wrk->connects_seg_manager);
436 }
437 
441 {
442  uword *smp;
443  smp = hash_get (app->listeners_table, listen_session_get_handle (listener));
444  ASSERT (smp != 0);
445  return segment_manager_get (*smp);
446 }
447 
448 session_t *
450  u8 transport_proto)
451 {
453  u64 handle;
454  u32 sm_index;
455  u8 sst;
456 
457  sst = session_type_from_proto_and_ip (transport_proto,
458  fib_proto == FIB_PROTOCOL_IP4);
459 
460  /* *INDENT-OFF* */
461  hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
462  listener = listen_session_get_from_handle (handle);
463  if (listener->session_type == sst
464  && !(listener->flags & SESSION_F_PROXY))
465  return listener;
466  }));
467  /* *INDENT-ON* */
468 
469  return 0;
470 }
471 
472 session_t *
474  u8 transport_proto)
475 {
477  u64 handle;
478  u32 sm_index;
479  u8 sst;
480 
481  sst = session_type_from_proto_and_ip (transport_proto,
482  fib_proto == FIB_PROTOCOL_IP4);
483 
484  /* *INDENT-OFF* */
485  hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
486  listener = listen_session_get_from_handle (handle);
487  if (listener->session_type == sst && (listener->flags & SESSION_F_PROXY))
488  return listener;
489  }));
490  /* *INDENT-ON* */
491 
492  return 0;
493 }
494 
495 /**
496  * Send an API message to the external app, to map new segment
497  */
498 int
499 app_worker_add_segment_notify (app_worker_t * app_wrk, u64 segment_handle)
500 {
501  application_t *app = application_get (app_wrk->app_index);
502  return app->cb_fns.add_segment_callback (app_wrk->api_client_index,
503  segment_handle);
504 }
505 
506 int
507 app_worker_del_segment_notify (app_worker_t * app_wrk, u64 segment_handle)
508 {
509  application_t *app = application_get (app_wrk->app_index);
510  return app->cb_fns.del_segment_callback (app_wrk->api_client_index,
511  segment_handle);
512 }
513 
514 static inline u8
516 {
517  return app_wrk->app_is_builtin;
518 }
519 
520 static inline int
522 {
523  if (PREDICT_FALSE (svm_msg_q_is_full (mq)))
524  {
525  clib_warning ("evt q full");
526  svm_msg_q_free_msg (mq, msg);
527  if (lock)
528  svm_msg_q_unlock (mq);
529  return -1;
530  }
531 
532  if (lock)
533  {
534  svm_msg_q_add_and_unlock (mq, msg);
535  return 0;
536  }
537 
538  /* Even when not locking the ring, we must wait for queue mutex */
539  if (svm_msg_q_add (mq, msg, SVM_Q_WAIT))
540  {
541  clib_warning ("msg q add returned");
542  return -1;
543  }
544  return 0;
545 }
546 
547 static inline int
549 {
550  session_event_t *evt;
551  svm_msg_q_msg_t msg;
552  svm_msg_q_t *mq;
553 
556  return 0;
557 
558  if (app_worker_application_is_builtin (app_wrk))
559  return app_worker_builtin_rx (app_wrk, s);
560 
561  if (svm_fifo_has_event (s->rx_fifo))
562  return 0;
563 
564  mq = app_wrk->event_queue;
565  if (lock)
566  svm_msg_q_lock (mq);
567 
569  {
570  clib_warning ("evt q rings full");
571  if (lock)
572  svm_msg_q_unlock (mq);
573  return -1;
574  }
575 
578 
579  evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
580  evt->session_index = s->rx_fifo->client_session_index;
581  evt->event_type = SESSION_IO_EVT_RX;
582 
583  (void) svm_fifo_set_event (s->rx_fifo);
584 
585  if (app_enqueue_evt (mq, &msg, lock))
586  return -1;
587  return 0;
588 }
589 
590 static inline int
592 {
593  svm_msg_q_t *mq;
594  session_event_t *evt;
595  svm_msg_q_msg_t msg;
596 
597  if (app_worker_application_is_builtin (app_wrk))
598  return 0;
599 
600  mq = app_wrk->event_queue;
601  if (lock)
602  svm_msg_q_lock (mq);
603 
605  {
606  clib_warning ("evt q rings full");
607  if (lock)
608  svm_msg_q_unlock (mq);
609  return -1;
610  }
611 
614 
615  evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
616  evt->event_type = SESSION_IO_EVT_TX;
617  evt->session_index = s->tx_fifo->client_session_index;
618 
619  return app_enqueue_evt (mq, &msg, lock);
620 }
621 
622 /* *INDENT-OFF* */
624  session_t *s,
625  u8 lock);
629 };
630 /* *INDENT-ON* */
631 
632 /**
633  * Send event to application
634  *
635  * Logic from queue perspective is non-blocking. If there's
636  * not enough space to enqueue a message, we return.
637  */
638 int
640 {
641  ASSERT (app && evt_type <= SESSION_IO_EVT_TX);
642  return app_send_evt_handler_fns[evt_type] (app, s, 0 /* lock */ );
643 }
644 
645 /**
646  * Send event to application
647  *
648  * Logic from queue perspective is blocking. However, if queue is full,
649  * we return.
650  */
651 int
653  u8 evt_type)
654 {
655  return app_send_evt_handler_fns[evt_type] (app, s, 1 /* lock */ );
656 }
657 
658 u8 *
659 format_app_worker_listener (u8 * s, va_list * args)
660 {
661  app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
662  u64 handle = va_arg (*args, u64);
663  u32 sm_index = va_arg (*args, u32);
664  int verbose = va_arg (*args, int);
666  const u8 *app_name;
667  u8 *str;
668 
669  if (!app_wrk)
670  {
671  if (verbose)
672  s = format (s, "%-40s%-25s%=10s%-15s%-15s%-10s", "Connection", "App",
673  "Wrk", "API Client", "ListenerID", "SegManager");
674  else
675  s = format (s, "%-40s%-25s%=10s", "Connection", "App", "Wrk");
676 
677  return s;
678  }
679 
680  app_name = application_name_from_index (app_wrk->app_index);
681  listener = listen_session_get_from_handle (handle);
682  str = format (0, "%U", format_session, listener, verbose);
683 
684  if (verbose)
685  {
686  char buf[32];
687  sprintf (buf, "%u(%u)", app_wrk->wrk_map_index, app_wrk->wrk_index);
688  s = format (s, "%-40s%-25s%=10s%-15u%-15u%-10u", str, app_name,
689  buf, app_wrk->api_client_index, handle, sm_index);
690  }
691  else
692  s = format (s, "%-40s%-25s%=10u", str, app_name, app_wrk->wrk_map_index);
693 
694  return s;
695 }
696 
697 u8 *
698 format_app_worker (u8 * s, va_list * args)
699 {
700  app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
701  u32 indent = 1;
702 
703  s = format (s, "%U wrk-index %u app-index %u map-index %u "
704  "api-client-index %d\n", format_white_space, indent,
705  app_wrk->wrk_index, app_wrk->app_index, app_wrk->wrk_map_index,
706  app_wrk->api_client_index);
707  return s;
708 }
709 
710 void
711 app_worker_format_connects (app_worker_t * app_wrk, int verbose)
712 {
713  svm_fifo_segment_private_t *fifo_segment;
715  segment_manager_t *sm;
716  const u8 *app_name;
717  u8 *s = 0;
718 
719  /* Header */
720  if (!app_wrk)
721  {
722  if (verbose)
723  vlib_cli_output (vm, "%-40s%-20s%-15s%-10s", "Connection", "App",
724  "API Client", "SegManager");
725  else
726  vlib_cli_output (vm, "%-40s%-20s", "Connection", "App");
727  return;
728  }
729 
730  if (app_wrk->connects_seg_manager == (u32) ~ 0)
731  return;
732 
733  app_name = application_name_from_index (app_wrk->app_index);
734 
735  /* Across all fifo segments */
737 
738  /* *INDENT-OFF* */
739  segment_manager_foreach_segment_w_lock (fifo_segment, sm, ({
740  svm_fifo_t *fifo;
741  u8 *str;
742 
743  fifo = svm_fifo_segment_get_fifo_list (fifo_segment);
744  while (fifo)
745  {
746  u32 session_index, thread_index;
747  session_t *session;
748 
749  session_index = fifo->master_session_index;
750  thread_index = fifo->master_thread_index;
751 
752  session = session_get (session_index, thread_index);
753  str = format (0, "%U", format_session, session, verbose);
754 
755  if (verbose)
756  s = format (s, "%-40s%-20s%-15u%-10u", str, app_name,
757  app_wrk->api_client_index, app_wrk->connects_seg_manager);
758  else
759  s = format (s, "%-40s%-20s", str, app_name);
760 
761  vlib_cli_output (vm, "%v", s);
762  vec_reset_length (s);
763  vec_free (str);
764 
765  fifo = fifo->next;
766  }
767  vec_free (s);
768  }));
769  /* *INDENT-ON* */
770 }
771 
772 /*
773  * fd.io coding-style-patch-verification: ON
774  *
775  * Local Variables:
776  * eval: (c-set-style "gnu")
777  * End:
778  */
int app_worker_init_accepted(session_t *s)
static u8 svm_msg_q_msg_is_invalid(svm_msg_q_msg_t *msg)
Check if message is invalid.
#define hash_set(h, key, value)
Definition: hash.h:255
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)
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:1001
int app_worker_init_connected(app_worker_t *app_wrk, session_t *s)
#define hash_unset(h, key)
Definition: hash.h:261
u8 * format_session(u8 *s, va_list *args)
Format stream session as per the following format.
Definition: session_cli.c:55
a
Definition: bitmap.h:538
svm_fifo_t * tx_fifo
struct _vnet_unlisten_args_t vnet_unlisten_args_t
int application_change_listener_owner(session_t *s, app_worker_t *app_wrk)
Definition: application.c:1114
u32 session_index
Index in thread pool where session was allocated.
static segment_manager_t * app_worker_alloc_segment_manager(app_worker_t *app_wrk)
unsigned long u64
Definition: types.h:89
session_t * app_worker_first_listener(app_worker_t *app_wrk, u8 fib_proto, u8 transport_proto)
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
int app_worker_connect_notify(app_worker_t *app_wrk, session_t *s, u32 opaque)
static int app_enqueue_evt(svm_msg_q_t *mq, svm_msg_q_msg_t *msg, u8 lock)
svm_fifo_t * rx_fifo
Pointers to rx/tx buffers.
static session_t * listen_session_get_from_handle(session_handle_t handle)
Definition: session.h:452
int app_worker_builtin_rx(app_worker_t *app_wrk, session_t *s)
u32 wrk_map_index
Worker index in app&#39;s map pool.
Definition: application.h:40
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
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
static session_t * session_get(u32 si, u32 thread_index)
Definition: session.h:207
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
int vnet_unlisten(vnet_unlisten_args_t *a)
Definition: application.c:1065
int app_worker_reset_notify(app_worker_t *app_wrk, session_t *s)
uword * listeners_table
Lookup tables for listeners.
Definition: application.h:52
#define segment_manager_foreach_segment_w_lock(VAR, SM, BODY)
u8 app_is_builtin
Definition: application.h:65
static u8 app_worker_application_is_builtin(app_worker_t *app_wrk)
#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:49
unsigned char u8
Definition: types.h:56
application_t * application_get_if_valid(u32 app_index)
Definition: application.c:455
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
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 SESSION_INVALID_INDEX
Definition: session_table.h:58
static int svm_fifo_is_empty(svm_fifo_t *f)
Definition: svm_fifo.h:141
int app_worker_connect_session(app_worker_t *app, session_endpoint_t *sep, u32 api_context)
application_t * app_worker_get_app(u32 wrk_index)
u32 first_segment_manager
First segment manager has in the the first segment the application&#39;s event fifo.
Definition: application.h:59
static int app_worker_alloc_session_fifos(segment_manager_t *sm, session_t *s)
void segment_manager_dealloc_fifos(svm_fifo_t *rx_fifo, svm_fifo_t *tx_fifo)
static uword clib_bitmap_is_zero(uword *ai)
predicate function; is an entire bitmap empty?
Definition: bitmap.h:57
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
unsigned int u32
Definition: types.h:88
app_worker_t * app_worker_alloc(application_t *app)
segment_manager_t * segment_manager_new()
static const u8 * app_get_name(application_t *app)
Definition: application.c:347
int app_worker_del_segment_notify(app_worker_t *app_wrk, u64 segment_handle)
int segment_manager_alloc_session_fifos(segment_manager_t *sm, svm_fifo_t **rx_fifo, svm_fifo_t **tx_fifo, u32 *fifo_segment_index)
#define hash_get(h, key)
Definition: hash.h:249
static svm_fifo_t * svm_fifo_segment_get_fifo_list(svm_fifo_segment_private_t *fifo_segment)
static session_type_t session_type_from_proto_and_ip(transport_proto_t proto, u8 is_ip4)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
void app_worker_free(app_worker_t *app_wrk)
u8 * format_app_worker_listener(u8 *s, va_list *args)
int app_worker_stop_listen(app_worker_t *app_wrk, app_listener_t *al)
const u8 * application_name_from_index(u32 app_index)
Returns app name for app-index.
Definition: application.c:381
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
u8 segment_manager_has_fifos(segment_manager_t *sm)
#define PREDICT_FALSE(x)
Definition: clib.h:111
u32 wrk_index
Worker index in global worker pool.
Definition: application.h:37
segment_manager_t * app_worker_get_or_alloc_connect_segment_manager(app_worker_t *app_wrk)
int app_worker_send_event(app_worker_t *app, session_t *s, u8 evt_type)
Send event to application.
static void app_worker_stop_listen_session(app_worker_t *app_wrk, session_t *ls)
static u64 listen_session_get_handle(session_t *s)
Definition: session.h:445
int( app_send_evt_handler_fn)(app_worker_t *app, session_t *s, u8 lock)
int app_worker_accept_notify(app_worker_t *app_wrk, session_t *s)
#define SEGMENT_MANAGER_INVALID_APP_INDEX
static u8 svm_fifo_set_event(svm_fifo_t *f)
Sets fifo event flag.
Definition: svm_fifo.h:172
session_t * app_worker_proxy_listener(app_worker_t *app_wrk, u8 fib_proto, u8 transport_proto)
vlib_main_t * vm
Definition: buffer.c:312
static void svm_msg_q_unlock(svm_msg_q_t *mq)
Unlock message queue.
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
#define clib_warning(format, args...)
Definition: error.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.
clib_bitmap_t * workers
workers accepting connections
Definition: application.h:75
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
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
int app_worker_close_notify(app_worker_t *app_wrk, session_t *s)
int app_worker_own_session(app_worker_t *app_wrk, session_t *s)
application_t * application_get(u32 app_index)
Definition: application.c:447
static u32 segment_manager_index(segment_manager_t *sm)
app_worker_t * app_worker_get_if_valid(u32 wrk_index)
void segment_manager_init_del(segment_manager_t *sm)
#define ASSERT(truth)
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.
app_worker_t * application_listener_select_worker(session_t *ls)
Definition: application.c:696
session_cb_vft_t cb_fns
Callbacks: shoulder-taps for the server/client.
Definition: application.h:92
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static app_send_evt_handler_fn *const app_send_evt_handler_fns[2]
u8 thread_index
Index of the thread that allocated the session.
app_worker_t * app_worker_get(u32 wrk_index)
u32 app_index
App index in app pool.
Definition: application.h:86
void segment_manager_del(segment_manager_t *sm)
Removes segment manager.
u64 session_handle_t
void svm_msg_q_free_msg(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Free message buffer.
void app_worker_format_connects(app_worker_t *app_wrk, int verbose)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static int app_send_io_evt_rx(app_worker_t *app_wrk, session_t *s, u8 lock)
volatile u8 session_state
State in session layer state machine.
segment_manager_t * app_worker_get_listen_segment_manager(app_worker_t *app, session_t *listener)
int app_worker_add_segment_notify(app_worker_t *app_wrk, u64 segment_handle)
Send an API message to the external app, to map new segment.
u64 uword
Definition: types.h:112
void segment_manager_del_sessions(segment_manager_t *sm)
Initiate disconnects for all sessions &#39;owned&#39; by a segment manager.
connectionless service
struct _segment_manager segment_manager_t
int app_worker_start_listen(app_worker_t *app_wrk, app_listener_t *app_listener)
void app_listener_cleanup(app_listener_t *al)
Definition: application.c:259
u32 app_index
Index of owning app.
Definition: application.h:43
u8 * format_app_worker(u8 *s, va_list *args)
int app_worker_lock_and_send_event(app_worker_t *app, session_t *s, u8 evt_type)
Send event to application.
u32 app_wrk_index
Index of the app worker that owns the session.
static int svm_fifo_has_event(svm_fifo_t *f)
Definition: svm_fifo.h:153
int app_worker_init_listener(app_worker_t *app_wrk, session_t *ls)
static app_worker_t * app_workers
Pool of workers associated to apps.
int application_is_builtin_proxy(application_t *app)
Definition: application.c:1159
u32 api_client_index
API index for the worker.
Definition: application.h:63
struct _session_endpoint session_endpoint_t
static int svm_msg_q_lock(svm_msg_q_t *mq)
Lock, or block trying, the message queue.
static int app_send_io_evt_tx(app_worker_t *app_wrk, session_t *s, u8 lock)
svm_msg_q_t * event_queue
Application listens for events on this svm queue.
Definition: application.h:46
static transport_service_type_t session_transport_service_type(session_t *s)
#define APP_INVALID_SEGMENT_MANAGER_INDEX
Definition: application.h:166
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:29
segment_manager_t * app_worker_get_connect_segment_manager(app_worker_t *app)
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.
int app_worker_alloc_connects_segment_manager(app_worker_t *app_wrk)
static session_t * listen_session_get(u32 ls_index)
Definition: session.h:475
u8 first_segment_manager_in_use
Definition: application.h:60
u32 listener_index
Parent listener session index if the result of an accept.