blob: 6f137e91e559c773a3e91d82220f5fe5267fe62f [file] [log] [blame]
Florin Coras623eb562019-02-03 19:28:34 -08001/*
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
16#include <vnet/session/application.h>
17#include <vnet/session/application_interface.h>
Florin Coras54a51fd2019-02-07 15:34:52 -080018#include <vnet/session/session.h>
Florin Coras623eb562019-02-03 19:28:34 -080019
20/**
21 * Pool of workers associated to apps
22 */
23static app_worker_t *app_workers;
24
Florin Coras623eb562019-02-03 19:28:34 -080025app_worker_t *
26app_worker_alloc (application_t * app)
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;
34 app_wrk->connects_seg_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
35 app_wrk->first_segment_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
Nathan Skrzypczakba65ca42019-05-16 16:35:40 +020036 APP_DBG ("New app %v worker %u", app->name, app_wrk->wrk_index);
Florin Coras623eb562019-02-03 19:28:34 -080037 return app_wrk;
38}
39
40app_worker_t *
41app_worker_get (u32 wrk_index)
42{
43 return pool_elt_at_index (app_workers, wrk_index);
44}
45
46app_worker_t *
47app_worker_get_if_valid (u32 wrk_index)
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
54void
55app_worker_free (app_worker_t * app_wrk)
56{
57 application_t *app = application_get (app_wrk->app_index);
Florin Corasc1a42652019-02-08 18:27:29 -080058 vnet_unlisten_args_t _a, *a = &_a;
Florin Coras623eb562019-02-03 19:28:34 -080059 u64 handle, *handles = 0;
60 segment_manager_t *sm;
Florin Coras87d66332019-06-11 12:31:31 -070061 session_t *ls;
Florin Coras623eb562019-02-03 19:28:34 -080062 u32 sm_index;
63 int i;
64
65 /*
66 * Listener cleanup
67 */
68
69 /* *INDENT-OFF* */
Florin Corasc9940fc2019-02-05 20:55:11 -080070 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
71 ls = listen_session_get_from_handle (handle);
Florin Coras87d66332019-06-11 12:31:31 -070072 vec_add1 (handles, app_listen_session_handle (ls));
Florin Coras623eb562019-02-03 19:28:34 -080073 sm = segment_manager_get (sm_index);
74 sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
75 }));
76 /* *INDENT-ON* */
77
78 for (i = 0; i < vec_len (handles); i++)
79 {
80 a->app_index = app->app_index;
81 a->wrk_map_index = app_wrk->wrk_map_index;
82 a->handle = handles[i];
83 /* seg manager is removed when unbind completes */
Florin Corasc1a42652019-02-08 18:27:29 -080084 (void) vnet_unlisten (a);
Florin Coras623eb562019-02-03 19:28:34 -080085 }
86
87 /*
88 * Connects segment manager cleanup
89 */
90
91 if (app_wrk->connects_seg_manager != APP_INVALID_SEGMENT_MANAGER_INDEX)
92 {
93 sm = segment_manager_get (app_wrk->connects_seg_manager);
94 sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
Florin Coras565115e2019-02-20 19:48:31 -080095 sm->first_is_protected = 0;
Florin Coras88001c62019-04-24 14:44:46 -070096 segment_manager_init_free (sm);
Florin Coras623eb562019-02-03 19:28:34 -080097 }
98
99 /* If first segment manager is used by a listener */
100 if (app_wrk->first_segment_manager != APP_INVALID_SEGMENT_MANAGER_INDEX
101 && app_wrk->first_segment_manager != app_wrk->connects_seg_manager)
102 {
103 sm = segment_manager_get (app_wrk->first_segment_manager);
104 sm->first_is_protected = 0;
105 sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
106 /* .. and has no fifos, e.g. it might be used for redirected sessions,
107 * remove it */
108 if (!segment_manager_has_fifos (sm))
Florin Coras88001c62019-04-24 14:44:46 -0700109 segment_manager_free (sm);
Florin Coras623eb562019-02-03 19:28:34 -0800110 }
111
Florin Coras623eb562019-02-03 19:28:34 -0800112 pool_put (app_workers, app_wrk);
113 if (CLIB_DEBUG)
114 clib_memset (app_wrk, 0xfe, sizeof (*app_wrk));
115}
116
117application_t *
118app_worker_get_app (u32 wrk_index)
119{
120 app_worker_t *app_wrk;
121 app_wrk = app_worker_get_if_valid (wrk_index);
122 if (!app_wrk)
123 return 0;
124 return application_get_if_valid (app_wrk->app_index);
125}
126
127static segment_manager_t *
128app_worker_alloc_segment_manager (app_worker_t * app_wrk)
129{
130 segment_manager_t *sm = 0;
131
132 /* If the first segment manager is not in use, don't allocate a new one */
133 if (app_wrk->first_segment_manager != APP_INVALID_SEGMENT_MANAGER_INDEX
134 && app_wrk->first_segment_manager_in_use == 0)
135 {
136 sm = segment_manager_get (app_wrk->first_segment_manager);
137 app_wrk->first_segment_manager_in_use = 1;
138 return sm;
139 }
140
Florin Coras88001c62019-04-24 14:44:46 -0700141 sm = segment_manager_alloc ();
Florin Coras623eb562019-02-03 19:28:34 -0800142 sm->app_wrk_index = app_wrk->wrk_index;
143
144 return sm;
145}
146
Florin Corasa27a46e2019-02-18 13:02:28 -0800147static int
148app_worker_alloc_session_fifos (segment_manager_t * sm, session_t * s)
149{
150 svm_fifo_t *rx_fifo = 0, *tx_fifo = 0;
Florin Corasa27a46e2019-02-18 13:02:28 -0800151 int rv;
152
Florin Coras1219b2d2019-04-23 15:53:43 -0700153 if ((rv = segment_manager_alloc_session_fifos (sm, &rx_fifo, &tx_fifo)))
Florin Corasa27a46e2019-02-18 13:02:28 -0800154 return rv;
155
156 rx_fifo->master_session_index = s->session_index;
157 rx_fifo->master_thread_index = s->thread_index;
158
159 tx_fifo->master_session_index = s->session_index;
160 tx_fifo->master_thread_index = s->thread_index;
161
162 s->rx_fifo = rx_fifo;
163 s->tx_fifo = tx_fifo;
Florin Corasa27a46e2019-02-18 13:02:28 -0800164 return 0;
165}
166
Florin Coras623eb562019-02-03 19:28:34 -0800167int
Florin Corasd4295e62019-02-22 13:11:38 -0800168app_worker_init_listener (app_worker_t * app_wrk, session_t * ls)
Florin Coras623eb562019-02-03 19:28:34 -0800169{
170 segment_manager_t *sm;
171
172 /* Allocate segment manager. All sessions derived out of a listen session
173 * have fifos allocated by the same segment manager. */
174 if (!(sm = app_worker_alloc_segment_manager (app_wrk)))
175 return -1;
176
Florin Corasc9940fc2019-02-05 20:55:11 -0800177 /* Keep track of the segment manager for the listener or this worker */
Florin Coras623eb562019-02-03 19:28:34 -0800178 hash_set (app_wrk->listeners_table, listen_session_get_handle (ls),
179 segment_manager_index (sm));
180
Florin Corasc9940fc2019-02-05 20:55:11 -0800181 if (session_transport_service_type (ls) == TRANSPORT_SERVICE_CL)
Florin Coras623eb562019-02-03 19:28:34 -0800182 {
Florin Corasa27a46e2019-02-18 13:02:28 -0800183 if (!ls->rx_fifo && app_worker_alloc_session_fifos (sm, ls))
Florin Coras623eb562019-02-03 19:28:34 -0800184 return -1;
185 }
186 return 0;
187}
188
189int
Florin Corasd4295e62019-02-22 13:11:38 -0800190app_worker_start_listen (app_worker_t * app_wrk,
191 app_listener_t * app_listener)
192{
193 session_t *ls;
194
195 if (clib_bitmap_get (app_listener->workers, app_wrk->wrk_map_index))
196 return VNET_API_ERROR_ADDRESS_IN_USE;
197
198 app_listener->workers = clib_bitmap_set (app_listener->workers,
199 app_wrk->wrk_map_index, 1);
200
201 if (app_listener->session_index != SESSION_INVALID_INDEX)
202 {
203 ls = session_get (app_listener->session_index, 0);
204 if (app_worker_init_listener (app_wrk, ls))
205 return -1;
206 }
207
208 if (app_listener->local_index != SESSION_INVALID_INDEX)
209 {
210 ls = session_get (app_listener->local_index, 0);
211 if (app_worker_init_listener (app_wrk, ls))
212 return -1;
213 }
214
215 return 0;
216}
217
Florin Coras2b81e3c2019-02-27 07:55:46 -0800218static void
219app_worker_stop_listen_session (app_worker_t * app_wrk, session_t * ls)
Florin Coras623eb562019-02-03 19:28:34 -0800220{
Florin Corasc9940fc2019-02-05 20:55:11 -0800221 session_handle_t handle;
Florin Coras623eb562019-02-03 19:28:34 -0800222 segment_manager_t *sm;
223 uword *sm_indexp;
Florin Coras2b81e3c2019-02-27 07:55:46 -0800224
225 handle = listen_session_get_handle (ls);
226 sm_indexp = hash_get (app_wrk->listeners_table, handle);
227 if (PREDICT_FALSE (!sm_indexp))
228 return;
229
230 sm = segment_manager_get (*sm_indexp);
231 if (app_wrk->first_segment_manager == *sm_indexp)
232 {
233 /* Delete sessions but don't remove segment manager */
234 app_wrk->first_segment_manager_in_use = 0;
235 segment_manager_del_sessions (sm);
236 }
237 else
238 {
Florin Coras88001c62019-04-24 14:44:46 -0700239 segment_manager_init_free (sm);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800240 }
241 hash_unset (app_wrk->listeners_table, handle);
242}
243
244int
245app_worker_stop_listen (app_worker_t * app_wrk, app_listener_t * al)
246{
Florin Corasd4295e62019-02-22 13:11:38 -0800247 session_t *ls;
Florin Coras623eb562019-02-03 19:28:34 -0800248
Florin Corasc9940fc2019-02-05 20:55:11 -0800249 if (!clib_bitmap_get (al->workers, app_wrk->wrk_map_index))
250 return 0;
251
252 if (al->session_index != SESSION_INVALID_INDEX)
Florin Coras623eb562019-02-03 19:28:34 -0800253 {
Florin Corasc9940fc2019-02-05 20:55:11 -0800254 ls = listen_session_get (al->session_index);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800255 app_worker_stop_listen_session (app_wrk, ls);
Florin Coras623eb562019-02-03 19:28:34 -0800256 }
257
Florin Corasc9940fc2019-02-05 20:55:11 -0800258 if (al->local_index != SESSION_INVALID_INDEX)
Florin Coras623eb562019-02-03 19:28:34 -0800259 {
Florin Corasd4295e62019-02-22 13:11:38 -0800260 ls = listen_session_get (al->local_index);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800261 app_worker_stop_listen_session (app_wrk, ls);
Florin Coras623eb562019-02-03 19:28:34 -0800262 }
Florin Corasc9940fc2019-02-05 20:55:11 -0800263
264 clib_bitmap_set_no_check (al->workers, app_wrk->wrk_map_index, 0);
265 if (clib_bitmap_is_zero (al->workers))
266 app_listener_cleanup (al);
Florin Coras623eb562019-02-03 19:28:34 -0800267
268 return 0;
269}
270
271int
Florin Corasa27a46e2019-02-18 13:02:28 -0800272app_worker_init_accepted (session_t * s)
273{
274 app_worker_t *app_wrk;
275 segment_manager_t *sm;
276 session_t *listener;
277
278 listener = listen_session_get (s->listener_index);
279 app_wrk = application_listener_select_worker (listener);
280 s->app_wrk_index = app_wrk->wrk_index;
Florin Coras2b81e3c2019-02-27 07:55:46 -0800281
Florin Corasa27a46e2019-02-18 13:02:28 -0800282 sm = app_worker_get_listen_segment_manager (app_wrk, listener);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800283 if (app_worker_alloc_session_fifos (sm, s))
284 return -1;
285
286 return 0;
Florin Corasa27a46e2019-02-18 13:02:28 -0800287}
288
289int
290app_worker_accept_notify (app_worker_t * app_wrk, session_t * s)
291{
292 application_t *app = application_get (app_wrk->app_index);
293 return app->cb_fns.session_accept_callback (s);
294}
295
296int
297app_worker_init_connected (app_worker_t * app_wrk, session_t * s)
298{
299 application_t *app = application_get (app_wrk->app_index);
300 segment_manager_t *sm;
301
302 /* Allocate fifos for session, unless the app is a builtin proxy */
303 if (!application_is_builtin_proxy (app))
304 {
305 sm = app_worker_get_connect_segment_manager (app_wrk);
306 if (app_worker_alloc_session_fifos (sm, s))
307 return -1;
308 }
309 return 0;
310}
311
312int
313app_worker_connect_notify (app_worker_t * app_wrk, session_t * s, u32 opaque)
314{
315 application_t *app = application_get (app_wrk->app_index);
316 return app->cb_fns.session_connected_callback (app_wrk->wrk_index, opaque,
317 s, s == 0 /* is_fail */ );
318}
319
320int
Florin Corasbf7ce2c2019-03-06 14:44:42 -0800321app_worker_close_notify (app_worker_t * app_wrk, session_t * s)
322{
323 application_t *app = application_get (app_wrk->app_index);
324 app->cb_fns.session_disconnect_callback (s);
325 return 0;
326}
327
328int
Florin Coras69b68ef2019-04-02 11:38:51 -0700329app_worker_reset_notify (app_worker_t * app_wrk, session_t * s)
330{
331 application_t *app = application_get (app_wrk->app_index);
332 app->cb_fns.session_reset_callback (s);
333 return 0;
334}
335
336int
Florin Corasbf7ce2c2019-03-06 14:44:42 -0800337app_worker_builtin_rx (app_worker_t * app_wrk, session_t * s)
338{
339 application_t *app = application_get (app_wrk->app_index);
340 app->cb_fns.builtin_app_rx_callback (s);
341 return 0;
342}
343
344int
Florin Coras0e573f52019-05-07 16:28:16 -0700345app_worker_builtin_tx (app_worker_t * app_wrk, session_t * s)
346{
347 application_t *app = application_get (app_wrk->app_index);
348
349 if (!app->cb_fns.builtin_app_tx_callback)
350 return 0;
351
352 app->cb_fns.builtin_app_tx_callback (s);
353 return 0;
354}
355
356int
Florin Coras623eb562019-02-03 19:28:34 -0800357app_worker_own_session (app_worker_t * app_wrk, session_t * s)
358{
359 segment_manager_t *sm;
360 svm_fifo_t *rxf, *txf;
361
362 if (s->session_state == SESSION_STATE_LISTENING)
363 return application_change_listener_owner (s, app_wrk);
364
365 s->app_wrk_index = app_wrk->wrk_index;
366
367 rxf = s->rx_fifo;
368 txf = s->tx_fifo;
369
370 if (!rxf || !txf)
371 return 0;
372
373 s->rx_fifo = 0;
374 s->tx_fifo = 0;
375
376 sm = app_worker_get_or_alloc_connect_segment_manager (app_wrk);
Florin Corasa27a46e2019-02-18 13:02:28 -0800377 if (app_worker_alloc_session_fifos (sm, s))
Florin Coras623eb562019-02-03 19:28:34 -0800378 return -1;
379
Sirshak Das28aa5392019-02-05 01:33:33 -0600380 if (!svm_fifo_is_empty_cons (rxf))
381 svm_fifo_clone (s->rx_fifo, rxf);
Florin Coras623eb562019-02-03 19:28:34 -0800382
Sirshak Das28aa5392019-02-05 01:33:33 -0600383 if (!svm_fifo_is_empty_cons (txf))
384 svm_fifo_clone (s->tx_fifo, txf);
385
Florin Coras19223e02019-03-03 14:56:05 -0800386 segment_manager_dealloc_fifos (rxf, txf);
Florin Coras623eb562019-02-03 19:28:34 -0800387
388 return 0;
389}
390
391int
Florin Corasc9940fc2019-02-05 20:55:11 -0800392app_worker_connect_session (app_worker_t * app, session_endpoint_t * sep,
393 u32 api_context)
Florin Coras623eb562019-02-03 19:28:34 -0800394{
395 int rv;
396
397 /* Make sure we have a segment manager for connects */
398 app_worker_alloc_connects_segment_manager (app);
399
400 if ((rv = session_open (app->wrk_index, sep, api_context)))
401 return rv;
402
403 return 0;
404}
405
406int
407app_worker_alloc_connects_segment_manager (app_worker_t * app_wrk)
408{
409 segment_manager_t *sm;
410
411 if (app_wrk->connects_seg_manager == APP_INVALID_SEGMENT_MANAGER_INDEX)
412 {
413 sm = app_worker_alloc_segment_manager (app_wrk);
414 if (sm == 0)
415 return -1;
416 app_wrk->connects_seg_manager = segment_manager_index (sm);
417 }
418 return 0;
419}
420
421segment_manager_t *
422app_worker_get_connect_segment_manager (app_worker_t * app)
423{
424 ASSERT (app->connects_seg_manager != (u32) ~ 0);
425 return segment_manager_get (app->connects_seg_manager);
426}
427
428segment_manager_t *
429app_worker_get_or_alloc_connect_segment_manager (app_worker_t * app_wrk)
430{
431 if (app_wrk->connects_seg_manager == (u32) ~ 0)
432 app_worker_alloc_connects_segment_manager (app_wrk);
433 return segment_manager_get (app_wrk->connects_seg_manager);
434}
435
436segment_manager_t *
437app_worker_get_listen_segment_manager (app_worker_t * app,
438 session_t * listener)
439{
440 uword *smp;
441 smp = hash_get (app->listeners_table, listen_session_get_handle (listener));
442 ASSERT (smp != 0);
443 return segment_manager_get (*smp);
444}
445
446session_t *
Florin Corasc9940fc2019-02-05 20:55:11 -0800447app_worker_first_listener (app_worker_t * app_wrk, u8 fib_proto,
Florin Coras623eb562019-02-03 19:28:34 -0800448 u8 transport_proto)
449{
450 session_t *listener;
451 u64 handle;
452 u32 sm_index;
453 u8 sst;
454
455 sst = session_type_from_proto_and_ip (transport_proto,
456 fib_proto == FIB_PROTOCOL_IP4);
457
458 /* *INDENT-OFF* */
Florin Corasc9940fc2019-02-05 20:55:11 -0800459 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
Florin Coras623eb562019-02-03 19:28:34 -0800460 listener = listen_session_get_from_handle (handle);
461 if (listener->session_type == sst
Florin Corasd5c604d2019-03-18 09:06:35 -0700462 && !(listener->flags & SESSION_F_PROXY))
Florin Coras623eb562019-02-03 19:28:34 -0800463 return listener;
464 }));
465 /* *INDENT-ON* */
466
467 return 0;
468}
469
470session_t *
Florin Corasc9940fc2019-02-05 20:55:11 -0800471app_worker_proxy_listener (app_worker_t * app_wrk, u8 fib_proto,
Florin Coras623eb562019-02-03 19:28:34 -0800472 u8 transport_proto)
473{
474 session_t *listener;
475 u64 handle;
476 u32 sm_index;
477 u8 sst;
478
479 sst = session_type_from_proto_and_ip (transport_proto,
480 fib_proto == FIB_PROTOCOL_IP4);
481
482 /* *INDENT-OFF* */
Florin Corasc9940fc2019-02-05 20:55:11 -0800483 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
Florin Coras623eb562019-02-03 19:28:34 -0800484 listener = listen_session_get_from_handle (handle);
Florin Corasd5c604d2019-03-18 09:06:35 -0700485 if (listener->session_type == sst && (listener->flags & SESSION_F_PROXY))
Florin Coras623eb562019-02-03 19:28:34 -0800486 return listener;
487 }));
488 /* *INDENT-ON* */
489
490 return 0;
491}
492
493/**
494 * Send an API message to the external app, to map new segment
495 */
496int
Florin Coras2b81e3c2019-02-27 07:55:46 -0800497app_worker_add_segment_notify (app_worker_t * app_wrk, u64 segment_handle)
Florin Coras623eb562019-02-03 19:28:34 -0800498{
Florin Coras623eb562019-02-03 19:28:34 -0800499 application_t *app = application_get (app_wrk->app_index);
500 return app->cb_fns.add_segment_callback (app_wrk->api_client_index,
501 segment_handle);
502}
503
Florin Coras2b81e3c2019-02-27 07:55:46 -0800504int
505app_worker_del_segment_notify (app_worker_t * app_wrk, u64 segment_handle)
506{
507 application_t *app = application_get (app_wrk->app_index);
508 return app->cb_fns.del_segment_callback (app_wrk->api_client_index,
509 segment_handle);
510}
511
Florin Coras31c99552019-03-01 13:00:58 -0800512static inline u8
Florin Coras623eb562019-02-03 19:28:34 -0800513app_worker_application_is_builtin (app_worker_t * app_wrk)
514{
515 return app_wrk->app_is_builtin;
516}
517
518static inline int
519app_enqueue_evt (svm_msg_q_t * mq, svm_msg_q_msg_t * msg, u8 lock)
520{
521 if (PREDICT_FALSE (svm_msg_q_is_full (mq)))
522 {
523 clib_warning ("evt q full");
524 svm_msg_q_free_msg (mq, msg);
525 if (lock)
526 svm_msg_q_unlock (mq);
527 return -1;
528 }
529
530 if (lock)
531 {
532 svm_msg_q_add_and_unlock (mq, msg);
533 return 0;
534 }
535
536 /* Even when not locking the ring, we must wait for queue mutex */
537 if (svm_msg_q_add (mq, msg, SVM_Q_WAIT))
538 {
539 clib_warning ("msg q add returned");
540 return -1;
541 }
542 return 0;
543}
544
545static inline int
546app_send_io_evt_rx (app_worker_t * app_wrk, session_t * s, u8 lock)
547{
548 session_event_t *evt;
549 svm_msg_q_msg_t msg;
550 svm_msg_q_t *mq;
551
552 if (PREDICT_FALSE (s->session_state != SESSION_STATE_READY
553 && s->session_state != SESSION_STATE_LISTENING))
Florin Coras096f2f82019-04-02 10:17:48 -0700554 return 0;
Florin Coras623eb562019-02-03 19:28:34 -0800555
556 if (app_worker_application_is_builtin (app_wrk))
Florin Coras69b68ef2019-04-02 11:38:51 -0700557 return app_worker_builtin_rx (app_wrk, s);
Florin Coras623eb562019-02-03 19:28:34 -0800558
Florin Coras653e43f2019-03-04 10:56:23 -0800559 if (svm_fifo_has_event (s->rx_fifo))
Florin Coras623eb562019-02-03 19:28:34 -0800560 return 0;
561
562 mq = app_wrk->event_queue;
563 if (lock)
564 svm_msg_q_lock (mq);
565
566 if (PREDICT_FALSE (svm_msg_q_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
567 {
568 clib_warning ("evt q rings full");
569 if (lock)
570 svm_msg_q_unlock (mq);
571 return -1;
572 }
573
574 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
575 ASSERT (!svm_msg_q_msg_is_invalid (&msg));
576
577 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Corasc0737e92019-03-04 14:19:39 -0800578 evt->session_index = s->rx_fifo->client_session_index;
Florin Corasf6c43132019-03-01 12:41:21 -0800579 evt->event_type = SESSION_IO_EVT_RX;
Florin Coras623eb562019-02-03 19:28:34 -0800580
581 (void) svm_fifo_set_event (s->rx_fifo);
582
583 if (app_enqueue_evt (mq, &msg, lock))
584 return -1;
585 return 0;
586}
587
588static inline int
589app_send_io_evt_tx (app_worker_t * app_wrk, session_t * s, u8 lock)
590{
591 svm_msg_q_t *mq;
592 session_event_t *evt;
593 svm_msg_q_msg_t msg;
594
595 if (app_worker_application_is_builtin (app_wrk))
Florin Coras0e573f52019-05-07 16:28:16 -0700596 return app_worker_builtin_tx (app_wrk, s);
Florin Coras623eb562019-02-03 19:28:34 -0800597
598 mq = app_wrk->event_queue;
599 if (lock)
600 svm_msg_q_lock (mq);
601
602 if (PREDICT_FALSE (svm_msg_q_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
603 {
604 clib_warning ("evt q rings full");
605 if (lock)
606 svm_msg_q_unlock (mq);
607 return -1;
608 }
609
610 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
611 ASSERT (!svm_msg_q_msg_is_invalid (&msg));
612
613 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Corasf6c43132019-03-01 12:41:21 -0800614 evt->event_type = SESSION_IO_EVT_TX;
Florin Corasc0737e92019-03-04 14:19:39 -0800615 evt->session_index = s->tx_fifo->client_session_index;
Florin Coras623eb562019-02-03 19:28:34 -0800616
617 return app_enqueue_evt (mq, &msg, lock);
618}
619
620/* *INDENT-OFF* */
621typedef int (app_send_evt_handler_fn) (app_worker_t *app,
622 session_t *s,
623 u8 lock);
Florin Coras653e43f2019-03-04 10:56:23 -0800624static app_send_evt_handler_fn * const app_send_evt_handler_fns[2] = {
Florin Coras623eb562019-02-03 19:28:34 -0800625 app_send_io_evt_rx,
Florin Coras623eb562019-02-03 19:28:34 -0800626 app_send_io_evt_tx,
627};
628/* *INDENT-ON* */
629
630/**
631 * Send event to application
632 *
633 * Logic from queue perspective is non-blocking. If there's
634 * not enough space to enqueue a message, we return.
635 */
636int
637app_worker_send_event (app_worker_t * app, session_t * s, u8 evt_type)
638{
Florin Corasf6c43132019-03-01 12:41:21 -0800639 ASSERT (app && evt_type <= SESSION_IO_EVT_TX);
Florin Coras623eb562019-02-03 19:28:34 -0800640 return app_send_evt_handler_fns[evt_type] (app, s, 0 /* lock */ );
641}
642
643/**
644 * Send event to application
645 *
646 * Logic from queue perspective is blocking. However, if queue is full,
647 * we return.
648 */
649int
650app_worker_lock_and_send_event (app_worker_t * app, session_t * s,
651 u8 evt_type)
652{
653 return app_send_evt_handler_fns[evt_type] (app, s, 1 /* lock */ );
654}
655
Florin Coras623eb562019-02-03 19:28:34 -0800656u8 *
657format_app_worker_listener (u8 * s, va_list * args)
658{
659 app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
660 u64 handle = va_arg (*args, u64);
661 u32 sm_index = va_arg (*args, u32);
662 int verbose = va_arg (*args, int);
663 session_t *listener;
664 const u8 *app_name;
665 u8 *str;
666
667 if (!app_wrk)
668 {
669 if (verbose)
670 s = format (s, "%-40s%-25s%=10s%-15s%-15s%-10s", "Connection", "App",
671 "Wrk", "API Client", "ListenerID", "SegManager");
672 else
673 s = format (s, "%-40s%-25s%=10s", "Connection", "App", "Wrk");
674
675 return s;
676 }
677
678 app_name = application_name_from_index (app_wrk->app_index);
679 listener = listen_session_get_from_handle (handle);
Florin Coras31c99552019-03-01 13:00:58 -0800680 str = format (0, "%U", format_session, listener, verbose);
Florin Coras623eb562019-02-03 19:28:34 -0800681
682 if (verbose)
683 {
684 char buf[32];
685 sprintf (buf, "%u(%u)", app_wrk->wrk_map_index, app_wrk->wrk_index);
686 s = format (s, "%-40s%-25s%=10s%-15u%-15u%-10u", str, app_name,
687 buf, app_wrk->api_client_index, handle, sm_index);
688 }
689 else
690 s = format (s, "%-40s%-25s%=10u", str, app_name, app_wrk->wrk_map_index);
691
692 return s;
693}
694
695u8 *
696format_app_worker (u8 * s, va_list * args)
697{
698 app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
699 u32 indent = 1;
700
701 s = format (s, "%U wrk-index %u app-index %u map-index %u "
702 "api-client-index %d\n", format_white_space, indent,
703 app_wrk->wrk_index, app_wrk->app_index, app_wrk->wrk_map_index,
704 app_wrk->api_client_index);
705 return s;
706}
707
708void
709app_worker_format_connects (app_worker_t * app_wrk, int verbose)
710{
Florin Coras623eb562019-02-03 19:28:34 -0800711 segment_manager_t *sm;
Florin Coras623eb562019-02-03 19:28:34 -0800712
713 /* Header */
714 if (!app_wrk)
715 {
Florin Coras88001c62019-04-24 14:44:46 -0700716 segment_manager_format_sessions (0, verbose);
Florin Coras623eb562019-02-03 19:28:34 -0800717 return;
718 }
719
720 if (app_wrk->connects_seg_manager == (u32) ~ 0)
721 return;
722
Florin Coras623eb562019-02-03 19:28:34 -0800723 sm = segment_manager_get (app_wrk->connects_seg_manager);
Florin Coras88001c62019-04-24 14:44:46 -0700724 segment_manager_format_sessions (sm, verbose);
Florin Coras623eb562019-02-03 19:28:34 -0800725}
726
Florin Coras623eb562019-02-03 19:28:34 -0800727/*
728 * fd.io coding-style-patch-verification: ON
729 *
730 * Local Variables:
731 * eval: (c-set-style "gnu")
732 * End:
733 */