blob: 17aeb57d49ba49d5de7756691aa18a8b746b2d9d [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;
Florin Corasc8e812f2020-05-14 05:32:18 +000036 clib_spinlock_init (&app_wrk->detached_seg_managers_lock);
Nathan Skrzypczakba65ca42019-05-16 16:35:40 +020037 APP_DBG ("New app %v worker %u", app->name, app_wrk->wrk_index);
Florin Coras623eb562019-02-03 19:28:34 -080038 return app_wrk;
39}
40
41app_worker_t *
42app_worker_get (u32 wrk_index)
43{
44 return pool_elt_at_index (app_workers, wrk_index);
45}
46
47app_worker_t *
48app_worker_get_if_valid (u32 wrk_index)
49{
50 if (pool_is_free_index (app_workers, wrk_index))
51 return 0;
52 return pool_elt_at_index (app_workers, wrk_index);
53}
54
55void
56app_worker_free (app_worker_t * app_wrk)
57{
58 application_t *app = application_get (app_wrk->app_index);
Florin Corasc1a42652019-02-08 18:27:29 -080059 vnet_unlisten_args_t _a, *a = &_a;
Florin Corasbf395972020-04-30 15:05:24 +000060 u64 handle, *handles = 0, *sm_indices = 0;
Florin Coras623eb562019-02-03 19:28:34 -080061 segment_manager_t *sm;
Florin Coras87d66332019-06-11 12:31:31 -070062 session_t *ls;
Florin Coras623eb562019-02-03 19:28:34 -080063 u32 sm_index;
Florin Coras701c0992020-04-19 19:20:19 +000064 int i, j;
Florin Coras623eb562019-02-03 19:28:34 -080065
66 /*
67 * Listener cleanup
68 */
69
70 /* *INDENT-OFF* */
Florin Corasc9940fc2019-02-05 20:55:11 -080071 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
72 ls = listen_session_get_from_handle (handle);
Florin Coras87d66332019-06-11 12:31:31 -070073 vec_add1 (handles, app_listen_session_handle (ls));
Florin Corasbf395972020-04-30 15:05:24 +000074 vec_add1 (sm_indices, sm_index);
Florin Coras623eb562019-02-03 19:28:34 -080075 sm = segment_manager_get (sm_index);
Florin Coras623eb562019-02-03 19:28:34 -080076 }));
77 /* *INDENT-ON* */
78
79 for (i = 0; i < vec_len (handles); i++)
80 {
Florin Corasbf395972020-04-30 15:05:24 +000081 /* Cleanup listener */
Florin Coras623eb562019-02-03 19:28:34 -080082 a->app_index = app->app_index;
83 a->wrk_map_index = app_wrk->wrk_map_index;
84 a->handle = handles[i];
Florin Corasc1a42652019-02-08 18:27:29 -080085 (void) vnet_unlisten (a);
Florin Corasbf395972020-04-30 15:05:24 +000086
87 sm = segment_manager_get_if_valid (sm_indices[i]);
88 if (sm && !segment_manager_app_detached (sm))
89 {
90 sm->first_is_protected = 0;
91 segment_manager_init_free (sm);
92 }
Florin Coras623eb562019-02-03 19:28:34 -080093 }
Florin Corasd50ff7f2020-04-16 04:30:22 +000094 vec_reset_length (handles);
Florin Corasbf395972020-04-30 15:05:24 +000095 vec_free (sm_indices);
96 hash_free (app_wrk->listeners_table);
Florin Coras623eb562019-02-03 19:28:34 -080097
98 /*
99 * Connects segment manager cleanup
100 */
101
102 if (app_wrk->connects_seg_manager != APP_INVALID_SEGMENT_MANAGER_INDEX)
103 {
104 sm = segment_manager_get (app_wrk->connects_seg_manager);
105 sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
Florin Coras565115e2019-02-20 19:48:31 -0800106 sm->first_is_protected = 0;
Florin Coras88001c62019-04-24 14:44:46 -0700107 segment_manager_init_free (sm);
Florin Coras623eb562019-02-03 19:28:34 -0800108 }
109
Florin Corasd50ff7f2020-04-16 04:30:22 +0000110 /*
111 * Half-open cleanup
112 */
113
114 for (i = 0; i < vec_len (app_wrk->half_open_table); i++)
115 {
116 if (!app_wrk->half_open_table[i])
117 continue;
118
119 /* *INDENT-OFF* */
120 hash_foreach (handle, sm_index, app_wrk->half_open_table[i], ({
121 vec_add1 (handles, handle);
122 }));
123 /* *INDENT-ON* */
124
Florin Coras701c0992020-04-19 19:20:19 +0000125 for (j = 0; j < vec_len (handles); j++)
126 session_cleanup_half_open (i, handles[j]);
Florin Corasd50ff7f2020-04-16 04:30:22 +0000127
128 hash_free (app_wrk->half_open_table[i]);
129 vec_reset_length (handles);
130 }
131
132 vec_free (app_wrk->half_open_table);
133 vec_free (handles);
134
Florin Corasc8e812f2020-05-14 05:32:18 +0000135 /*
136 * Detached listener segment managers cleanup
137 */
138 for (i = 0; i < vec_len (app_wrk->detached_seg_managers); i++)
139 {
140 sm = segment_manager_get (app_wrk->detached_seg_managers[i]);
141 segment_manager_init_free (sm);
142 }
143 vec_free (app_wrk->detached_seg_managers);
144 clib_spinlock_free (&app_wrk->detached_seg_managers_lock);
145
Florin Corasbf395972020-04-30 15:05:24 +0000146 /* If first segment manager is used by a listener that recently
147 * stopped listening, mark it as detached */
148 if (app_wrk->first_segment_manager != app_wrk->connects_seg_manager
Florin Corasc8e812f2020-05-14 05:32:18 +0000149 && (sm = segment_manager_get_if_valid (app_wrk->first_segment_manager))
150 && !segment_manager_app_detached (sm))
Florin Coras623eb562019-02-03 19:28:34 -0800151 {
Florin Coras623eb562019-02-03 19:28:34 -0800152 sm->first_is_protected = 0;
153 sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
Florin Corasc8e812f2020-05-14 05:32:18 +0000154 segment_manager_init_free (sm);
Florin Coras623eb562019-02-03 19:28:34 -0800155 }
156
Florin Coras623eb562019-02-03 19:28:34 -0800157 if (CLIB_DEBUG)
158 clib_memset (app_wrk, 0xfe, sizeof (*app_wrk));
Benoît Ganned4aeb842019-07-18 18:38:42 +0200159 pool_put (app_workers, app_wrk);
Florin Coras623eb562019-02-03 19:28:34 -0800160}
161
162application_t *
163app_worker_get_app (u32 wrk_index)
164{
165 app_worker_t *app_wrk;
166 app_wrk = app_worker_get_if_valid (wrk_index);
167 if (!app_wrk)
168 return 0;
169 return application_get_if_valid (app_wrk->app_index);
170}
171
172static segment_manager_t *
173app_worker_alloc_segment_manager (app_worker_t * app_wrk)
174{
175 segment_manager_t *sm = 0;
176
177 /* If the first segment manager is not in use, don't allocate a new one */
178 if (app_wrk->first_segment_manager != APP_INVALID_SEGMENT_MANAGER_INDEX
179 && app_wrk->first_segment_manager_in_use == 0)
180 {
181 sm = segment_manager_get (app_wrk->first_segment_manager);
182 app_wrk->first_segment_manager_in_use = 1;
183 return sm;
184 }
185
Florin Coras88001c62019-04-24 14:44:46 -0700186 sm = segment_manager_alloc ();
Florin Coras623eb562019-02-03 19:28:34 -0800187 sm->app_wrk_index = app_wrk->wrk_index;
188
189 return sm;
190}
191
Florin Corasa27a46e2019-02-18 13:02:28 -0800192static int
193app_worker_alloc_session_fifos (segment_manager_t * sm, session_t * s)
194{
195 svm_fifo_t *rx_fifo = 0, *tx_fifo = 0;
Florin Corasa27a46e2019-02-18 13:02:28 -0800196 int rv;
197
Florin Coras62ddc032019-12-08 18:30:42 -0800198 if ((rv = segment_manager_alloc_session_fifos (sm, s->thread_index,
199 &rx_fifo, &tx_fifo)))
Florin Corasa27a46e2019-02-18 13:02:28 -0800200 return rv;
201
202 rx_fifo->master_session_index = s->session_index;
203 rx_fifo->master_thread_index = s->thread_index;
204
205 tx_fifo->master_session_index = s->session_index;
206 tx_fifo->master_thread_index = s->thread_index;
207
208 s->rx_fifo = rx_fifo;
209 s->tx_fifo = tx_fifo;
Florin Corasa27a46e2019-02-18 13:02:28 -0800210 return 0;
211}
212
Florin Coras623eb562019-02-03 19:28:34 -0800213int
Florin Corasd4295e62019-02-22 13:11:38 -0800214app_worker_init_listener (app_worker_t * app_wrk, session_t * ls)
Florin Coras623eb562019-02-03 19:28:34 -0800215{
216 segment_manager_t *sm;
217
218 /* Allocate segment manager. All sessions derived out of a listen session
219 * have fifos allocated by the same segment manager. */
220 if (!(sm = app_worker_alloc_segment_manager (app_wrk)))
Florin Coras00e01d32019-10-21 16:07:46 -0700221 return SESSION_E_ALLOC;
Florin Coras623eb562019-02-03 19:28:34 -0800222
Florin Corasc9940fc2019-02-05 20:55:11 -0800223 /* Keep track of the segment manager for the listener or this worker */
Florin Coras623eb562019-02-03 19:28:34 -0800224 hash_set (app_wrk->listeners_table, listen_session_get_handle (ls),
225 segment_manager_index (sm));
226
Florin Coras87b7e3d2020-03-27 15:06:07 +0000227 if (transport_connection_is_cless (session_get_transport (ls)))
Florin Coras623eb562019-02-03 19:28:34 -0800228 {
Florin Coras87b7e3d2020-03-27 15:06:07 +0000229 if (ls->rx_fifo)
Florin Coras00e01d32019-10-21 16:07:46 -0700230 return SESSION_E_NOSUPPORT;
231 return app_worker_alloc_session_fifos (sm, ls);
Florin Coras623eb562019-02-03 19:28:34 -0800232 }
233 return 0;
234}
235
236int
Florin Corasd4295e62019-02-22 13:11:38 -0800237app_worker_start_listen (app_worker_t * app_wrk,
238 app_listener_t * app_listener)
239{
240 session_t *ls;
Florin Coras00e01d32019-10-21 16:07:46 -0700241 int rv;
Florin Corasd4295e62019-02-22 13:11:38 -0800242
243 if (clib_bitmap_get (app_listener->workers, app_wrk->wrk_map_index))
Florin Coras00e01d32019-10-21 16:07:46 -0700244 return SESSION_E_ALREADY_LISTENING;
Florin Corasd4295e62019-02-22 13:11:38 -0800245
246 app_listener->workers = clib_bitmap_set (app_listener->workers,
247 app_wrk->wrk_map_index, 1);
248
249 if (app_listener->session_index != SESSION_INVALID_INDEX)
250 {
251 ls = session_get (app_listener->session_index, 0);
Florin Coras00e01d32019-10-21 16:07:46 -0700252 if ((rv = app_worker_init_listener (app_wrk, ls)))
253 return rv;
Florin Corasd4295e62019-02-22 13:11:38 -0800254 }
255
256 if (app_listener->local_index != SESSION_INVALID_INDEX)
257 {
258 ls = session_get (app_listener->local_index, 0);
Florin Coras00e01d32019-10-21 16:07:46 -0700259 if ((rv = app_worker_init_listener (app_wrk, ls)))
260 return rv;
Florin Corasd4295e62019-02-22 13:11:38 -0800261 }
262
263 return 0;
264}
265
Florin Coras2b81e3c2019-02-27 07:55:46 -0800266static void
Florin Corasc8e812f2020-05-14 05:32:18 +0000267app_worker_add_detached_sm (app_worker_t * app_wrk, u32 sm_index)
268{
269 vec_add1 (app_wrk->detached_seg_managers, sm_index);
270}
271
272void
273app_worker_del_detached_sm (app_worker_t * app_wrk, u32 sm_index)
274{
275 u32 i;
276
277 clib_spinlock_lock (&app_wrk->detached_seg_managers_lock);
278 for (i = 0; i < vec_len (app_wrk->detached_seg_managers); i++)
279 {
280 if (app_wrk->detached_seg_managers[i] == sm_index)
281 {
282 vec_del1 (app_wrk->detached_seg_managers, i);
283 break;
284 }
285 }
286 clib_spinlock_unlock (&app_wrk->detached_seg_managers_lock);
287}
288
289static void
Florin Coras2b81e3c2019-02-27 07:55:46 -0800290app_worker_stop_listen_session (app_worker_t * app_wrk, session_t * ls)
Florin Coras623eb562019-02-03 19:28:34 -0800291{
Florin Corasc9940fc2019-02-05 20:55:11 -0800292 session_handle_t handle;
Florin Coras623eb562019-02-03 19:28:34 -0800293 segment_manager_t *sm;
294 uword *sm_indexp;
Florin Coras2b81e3c2019-02-27 07:55:46 -0800295
296 handle = listen_session_get_handle (ls);
297 sm_indexp = hash_get (app_wrk->listeners_table, handle);
298 if (PREDICT_FALSE (!sm_indexp))
299 return;
300
Florin Coras1bd46162020-04-13 23:35:55 +0000301 /* Dealloc fifos, if any (dgram listeners) */
Florin Coras87b7e3d2020-03-27 15:06:07 +0000302 if (ls->rx_fifo)
303 {
304 segment_manager_dealloc_fifos (ls->rx_fifo, ls->tx_fifo);
305 ls->tx_fifo = ls->rx_fifo = 0;
306 }
307
Florin Coras1bd46162020-04-13 23:35:55 +0000308 /* Try to cleanup segment manager */
Florin Coras2b81e3c2019-02-27 07:55:46 -0800309 sm = segment_manager_get (*sm_indexp);
Florin Coras1bd46162020-04-13 23:35:55 +0000310 if (sm && app_wrk->first_segment_manager != *sm_indexp)
Florin Coras2b81e3c2019-02-27 07:55:46 -0800311 {
Florin Coras1bd46162020-04-13 23:35:55 +0000312 segment_manager_app_detach (sm);
313 if (!segment_manager_has_fifos (sm))
314 segment_manager_free (sm);
Florin Corasc8e812f2020-05-14 05:32:18 +0000315 else
316 {
317 /* Track segment manager in case app detaches and all the
318 * outstanding sessions need to be closed */
319 app_worker_add_detached_sm (app_wrk, *sm_indexp);
320 sm->flags |= SEG_MANAGER_F_DETACHED_LISTENER;
321 }
Florin Coras2b81e3c2019-02-27 07:55:46 -0800322 }
Florin Coras1bd46162020-04-13 23:35:55 +0000323
Florin Coras2b81e3c2019-02-27 07:55:46 -0800324 hash_unset (app_wrk->listeners_table, handle);
325}
326
327int
328app_worker_stop_listen (app_worker_t * app_wrk, app_listener_t * al)
329{
Florin Corasd4295e62019-02-22 13:11:38 -0800330 session_t *ls;
Florin Coras623eb562019-02-03 19:28:34 -0800331
Florin Corasc9940fc2019-02-05 20:55:11 -0800332 if (!clib_bitmap_get (al->workers, app_wrk->wrk_map_index))
333 return 0;
334
335 if (al->session_index != SESSION_INVALID_INDEX)
Florin Coras623eb562019-02-03 19:28:34 -0800336 {
Florin Corasc9940fc2019-02-05 20:55:11 -0800337 ls = listen_session_get (al->session_index);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800338 app_worker_stop_listen_session (app_wrk, ls);
Florin Coras623eb562019-02-03 19:28:34 -0800339 }
340
Florin Corasc9940fc2019-02-05 20:55:11 -0800341 if (al->local_index != SESSION_INVALID_INDEX)
Florin Coras623eb562019-02-03 19:28:34 -0800342 {
Florin Corasd4295e62019-02-22 13:11:38 -0800343 ls = listen_session_get (al->local_index);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800344 app_worker_stop_listen_session (app_wrk, ls);
Florin Coras623eb562019-02-03 19:28:34 -0800345 }
Florin Corasc9940fc2019-02-05 20:55:11 -0800346
347 clib_bitmap_set_no_check (al->workers, app_wrk->wrk_map_index, 0);
348 if (clib_bitmap_is_zero (al->workers))
349 app_listener_cleanup (al);
Florin Coras623eb562019-02-03 19:28:34 -0800350
351 return 0;
352}
353
354int
Florin Corasa27a46e2019-02-18 13:02:28 -0800355app_worker_init_accepted (session_t * s)
356{
357 app_worker_t *app_wrk;
358 segment_manager_t *sm;
359 session_t *listener;
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000360 application_t *app;
Florin Corasa27a46e2019-02-18 13:02:28 -0800361
Nathan Skrzypczak2f0f96b2019-06-13 10:14:28 +0200362 listener = listen_session_get_from_handle (s->listener_handle);
Florin Corasa27a46e2019-02-18 13:02:28 -0800363 app_wrk = application_listener_select_worker (listener);
364 s->app_wrk_index = app_wrk->wrk_index;
Florin Coras2b81e3c2019-02-27 07:55:46 -0800365
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000366 app = application_get (app_wrk->app_index);
367 if (app->cb_fns.fifo_tuning_callback)
368 s->flags |= SESSION_F_CUSTOM_FIFO_TUNING;
369
Florin Corasa27a46e2019-02-18 13:02:28 -0800370 sm = app_worker_get_listen_segment_manager (app_wrk, listener);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800371 if (app_worker_alloc_session_fifos (sm, s))
372 return -1;
373
374 return 0;
Florin Corasa27a46e2019-02-18 13:02:28 -0800375}
376
377int
378app_worker_accept_notify (app_worker_t * app_wrk, session_t * s)
379{
380 application_t *app = application_get (app_wrk->app_index);
381 return app->cb_fns.session_accept_callback (s);
382}
383
384int
385app_worker_init_connected (app_worker_t * app_wrk, session_t * s)
386{
387 application_t *app = application_get (app_wrk->app_index);
388 segment_manager_t *sm;
389
390 /* Allocate fifos for session, unless the app is a builtin proxy */
391 if (!application_is_builtin_proxy (app))
392 {
393 sm = app_worker_get_connect_segment_manager (app_wrk);
Florin Coras00e01d32019-10-21 16:07:46 -0700394 return app_worker_alloc_session_fifos (sm, s);
Florin Corasa27a46e2019-02-18 13:02:28 -0800395 }
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000396
397 if (app->cb_fns.fifo_tuning_callback)
398 s->flags |= SESSION_F_CUSTOM_FIFO_TUNING;
399
Florin Corasa27a46e2019-02-18 13:02:28 -0800400 return 0;
401}
402
403int
Florin Coras00e01d32019-10-21 16:07:46 -0700404app_worker_connect_notify (app_worker_t * app_wrk, session_t * s,
405 session_error_t err, u32 opaque)
Florin Corasa27a46e2019-02-18 13:02:28 -0800406{
407 application_t *app = application_get (app_wrk->app_index);
408 return app->cb_fns.session_connected_callback (app_wrk->wrk_index, opaque,
Florin Coras00e01d32019-10-21 16:07:46 -0700409 s, err);
Florin Corasa27a46e2019-02-18 13:02:28 -0800410}
411
412int
Florin Corasd50ff7f2020-04-16 04:30:22 +0000413app_worker_add_half_open (app_worker_t * app_wrk, transport_proto_t tp,
414 session_handle_t ho_handle,
415 session_handle_t wrk_handle)
416{
417 ASSERT (vlib_get_thread_index () == 0);
418 vec_validate (app_wrk->half_open_table, tp);
419 hash_set (app_wrk->half_open_table[tp], ho_handle, wrk_handle);
420 return 0;
421}
422
423int
424app_worker_del_half_open (app_worker_t * app_wrk, transport_proto_t tp,
425 session_handle_t ho_handle)
426{
427 ASSERT (vlib_get_thread_index () == 0);
428 hash_unset (app_wrk->half_open_table[tp], ho_handle);
429 return 0;
430}
431
432u64
433app_worker_lookup_half_open (app_worker_t * app_wrk, transport_proto_t tp,
434 session_handle_t ho_handle)
435{
436 u64 *ho_wrk_handlep;
437
438 /* No locking because all updates are done from main thread */
439 ho_wrk_handlep = hash_get (app_wrk->half_open_table[tp], ho_handle);
440 if (!ho_wrk_handlep)
441 return SESSION_INVALID_HANDLE;
442
443 return *ho_wrk_handlep;
444}
445
446int
Florin Corasbf7ce2c2019-03-06 14:44:42 -0800447app_worker_close_notify (app_worker_t * app_wrk, session_t * s)
448{
449 application_t *app = application_get (app_wrk->app_index);
450 app->cb_fns.session_disconnect_callback (s);
451 return 0;
452}
453
454int
Florin Coras692b9492019-07-12 15:01:53 -0700455app_worker_transport_closed_notify (app_worker_t * app_wrk, session_t * s)
456{
457 application_t *app = application_get (app_wrk->app_index);
458 if (app->cb_fns.session_transport_closed_callback)
459 app->cb_fns.session_transport_closed_callback (s);
460 return 0;
461}
462
463int
Florin Coras69b68ef2019-04-02 11:38:51 -0700464app_worker_reset_notify (app_worker_t * app_wrk, session_t * s)
465{
466 application_t *app = application_get (app_wrk->app_index);
467 app->cb_fns.session_reset_callback (s);
468 return 0;
469}
470
471int
Florin Coras70f26d52019-07-08 11:47:18 -0700472app_worker_cleanup_notify (app_worker_t * app_wrk, session_t * s,
473 session_cleanup_ntf_t ntf)
474{
475 application_t *app = application_get (app_wrk->app_index);
476 if (app->cb_fns.session_cleanup_callback)
477 app->cb_fns.session_cleanup_callback (s, ntf);
478 return 0;
479}
480
481int
Florin Corasbf7ce2c2019-03-06 14:44:42 -0800482app_worker_builtin_rx (app_worker_t * app_wrk, session_t * s)
483{
484 application_t *app = application_get (app_wrk->app_index);
485 app->cb_fns.builtin_app_rx_callback (s);
486 return 0;
487}
488
489int
Florin Coras0e573f52019-05-07 16:28:16 -0700490app_worker_builtin_tx (app_worker_t * app_wrk, session_t * s)
491{
492 application_t *app = application_get (app_wrk->app_index);
493
494 if (!app->cb_fns.builtin_app_tx_callback)
495 return 0;
496
497 app->cb_fns.builtin_app_tx_callback (s);
498 return 0;
499}
500
501int
Florin Coras49568af2019-07-31 16:46:24 -0700502app_worker_migrate_notify (app_worker_t * app_wrk, session_t * s,
503 session_handle_t new_sh)
504{
505 application_t *app = application_get (app_wrk->app_index);
506 app->cb_fns.session_migrate_callback (s, new_sh);
507 return 0;
508}
509
510int
Florin Coras623eb562019-02-03 19:28:34 -0800511app_worker_own_session (app_worker_t * app_wrk, session_t * s)
512{
513 segment_manager_t *sm;
514 svm_fifo_t *rxf, *txf;
515
516 if (s->session_state == SESSION_STATE_LISTENING)
517 return application_change_listener_owner (s, app_wrk);
518
519 s->app_wrk_index = app_wrk->wrk_index;
520
521 rxf = s->rx_fifo;
522 txf = s->tx_fifo;
523
524 if (!rxf || !txf)
525 return 0;
526
527 s->rx_fifo = 0;
528 s->tx_fifo = 0;
529
530 sm = app_worker_get_or_alloc_connect_segment_manager (app_wrk);
Florin Corasa27a46e2019-02-18 13:02:28 -0800531 if (app_worker_alloc_session_fifos (sm, s))
Florin Coras623eb562019-02-03 19:28:34 -0800532 return -1;
533
Sirshak Das28aa5392019-02-05 01:33:33 -0600534 if (!svm_fifo_is_empty_cons (rxf))
535 svm_fifo_clone (s->rx_fifo, rxf);
Florin Coras623eb562019-02-03 19:28:34 -0800536
Sirshak Das28aa5392019-02-05 01:33:33 -0600537 if (!svm_fifo_is_empty_cons (txf))
538 svm_fifo_clone (s->tx_fifo, txf);
539
Florin Coras19223e02019-03-03 14:56:05 -0800540 segment_manager_dealloc_fifos (rxf, txf);
Florin Coras623eb562019-02-03 19:28:34 -0800541
542 return 0;
543}
544
545int
Florin Coras72db6642020-04-15 01:30:46 +0000546app_worker_connect_session (app_worker_t * app_wrk, session_endpoint_t * sep,
Florin Corasc9940fc2019-02-05 20:55:11 -0800547 u32 api_context)
Florin Coras623eb562019-02-03 19:28:34 -0800548{
549 int rv;
550
551 /* Make sure we have a segment manager for connects */
Florin Coras72db6642020-04-15 01:30:46 +0000552 if (app_worker_alloc_connects_segment_manager (app_wrk))
553 return SESSION_E_ALLOC;
Florin Coras623eb562019-02-03 19:28:34 -0800554
Florin Coras72db6642020-04-15 01:30:46 +0000555 if ((rv = session_open (app_wrk->wrk_index, sep, api_context)))
Florin Coras623eb562019-02-03 19:28:34 -0800556 return rv;
557
558 return 0;
559}
560
561int
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000562app_worker_session_fifo_tuning (app_worker_t * app_wrk, session_t * s,
563 svm_fifo_t * f,
564 session_ft_action_t act, u32 len)
565{
566 application_t *app = application_get (app_wrk->app_index);
567 return app->cb_fns.fifo_tuning_callback (s, f, act, len);
568}
569
570int
Florin Coras623eb562019-02-03 19:28:34 -0800571app_worker_alloc_connects_segment_manager (app_worker_t * app_wrk)
572{
573 segment_manager_t *sm;
574
575 if (app_wrk->connects_seg_manager == APP_INVALID_SEGMENT_MANAGER_INDEX)
576 {
577 sm = app_worker_alloc_segment_manager (app_wrk);
578 if (sm == 0)
579 return -1;
580 app_wrk->connects_seg_manager = segment_manager_index (sm);
581 }
582 return 0;
583}
584
585segment_manager_t *
586app_worker_get_connect_segment_manager (app_worker_t * app)
587{
588 ASSERT (app->connects_seg_manager != (u32) ~ 0);
589 return segment_manager_get (app->connects_seg_manager);
590}
591
592segment_manager_t *
593app_worker_get_or_alloc_connect_segment_manager (app_worker_t * app_wrk)
594{
595 if (app_wrk->connects_seg_manager == (u32) ~ 0)
596 app_worker_alloc_connects_segment_manager (app_wrk);
597 return segment_manager_get (app_wrk->connects_seg_manager);
598}
599
600segment_manager_t *
601app_worker_get_listen_segment_manager (app_worker_t * app,
602 session_t * listener)
603{
604 uword *smp;
605 smp = hash_get (app->listeners_table, listen_session_get_handle (listener));
Dave Barach47d41ad2020-02-17 09:13:26 -0500606 ALWAYS_ASSERT (smp != 0);
Florin Coras623eb562019-02-03 19:28:34 -0800607 return segment_manager_get (*smp);
608}
609
610session_t *
Florin Corasc9940fc2019-02-05 20:55:11 -0800611app_worker_first_listener (app_worker_t * app_wrk, u8 fib_proto,
Florin Coras623eb562019-02-03 19:28:34 -0800612 u8 transport_proto)
613{
614 session_t *listener;
615 u64 handle;
616 u32 sm_index;
617 u8 sst;
618
619 sst = session_type_from_proto_and_ip (transport_proto,
620 fib_proto == FIB_PROTOCOL_IP4);
621
622 /* *INDENT-OFF* */
Florin Corasc9940fc2019-02-05 20:55:11 -0800623 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
Florin Coras623eb562019-02-03 19:28:34 -0800624 listener = listen_session_get_from_handle (handle);
625 if (listener->session_type == sst
Florin Corasd5c604d2019-03-18 09:06:35 -0700626 && !(listener->flags & SESSION_F_PROXY))
Florin Coras623eb562019-02-03 19:28:34 -0800627 return listener;
628 }));
629 /* *INDENT-ON* */
630
631 return 0;
632}
633
634session_t *
Florin Corasc9940fc2019-02-05 20:55:11 -0800635app_worker_proxy_listener (app_worker_t * app_wrk, u8 fib_proto,
Florin Coras623eb562019-02-03 19:28:34 -0800636 u8 transport_proto)
637{
638 session_t *listener;
639 u64 handle;
640 u32 sm_index;
641 u8 sst;
642
643 sst = session_type_from_proto_and_ip (transport_proto,
644 fib_proto == FIB_PROTOCOL_IP4);
645
646 /* *INDENT-OFF* */
Florin Corasc9940fc2019-02-05 20:55:11 -0800647 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
Florin Coras623eb562019-02-03 19:28:34 -0800648 listener = listen_session_get_from_handle (handle);
Florin Corasd5c604d2019-03-18 09:06:35 -0700649 if (listener->session_type == sst && (listener->flags & SESSION_F_PROXY))
Florin Coras623eb562019-02-03 19:28:34 -0800650 return listener;
651 }));
652 /* *INDENT-ON* */
653
654 return 0;
655}
656
657/**
658 * Send an API message to the external app, to map new segment
659 */
660int
Florin Coras2b81e3c2019-02-27 07:55:46 -0800661app_worker_add_segment_notify (app_worker_t * app_wrk, u64 segment_handle)
Florin Coras623eb562019-02-03 19:28:34 -0800662{
Florin Coras623eb562019-02-03 19:28:34 -0800663 application_t *app = application_get (app_wrk->app_index);
Florin Corasc4c4cf52019-08-24 18:17:34 -0700664
665 return app->cb_fns.add_segment_callback (app_wrk->wrk_index,
Florin Coras623eb562019-02-03 19:28:34 -0800666 segment_handle);
667}
668
Florin Coras2b81e3c2019-02-27 07:55:46 -0800669int
670app_worker_del_segment_notify (app_worker_t * app_wrk, u64 segment_handle)
671{
672 application_t *app = application_get (app_wrk->app_index);
Florin Corasc4c4cf52019-08-24 18:17:34 -0700673 return app->cb_fns.del_segment_callback (app_wrk->wrk_index,
Florin Coras2b81e3c2019-02-27 07:55:46 -0800674 segment_handle);
675}
676
Florin Coras31c99552019-03-01 13:00:58 -0800677static inline u8
Florin Coras623eb562019-02-03 19:28:34 -0800678app_worker_application_is_builtin (app_worker_t * app_wrk)
679{
680 return app_wrk->app_is_builtin;
681}
682
683static inline int
Florin Coras2b5fed82019-07-25 14:51:09 -0700684app_send_io_evt_rx (app_worker_t * app_wrk, session_t * s)
Florin Coras623eb562019-02-03 19:28:34 -0800685{
686 session_event_t *evt;
687 svm_msg_q_msg_t msg;
688 svm_msg_q_t *mq;
689
Florin Coras5c290292019-09-19 08:19:44 -0700690 if (app_worker_application_is_builtin (app_wrk))
691 return app_worker_builtin_rx (app_wrk, s);
692
Florin Coras653e43f2019-03-04 10:56:23 -0800693 if (svm_fifo_has_event (s->rx_fifo))
Florin Coras623eb562019-02-03 19:28:34 -0800694 return 0;
695
696 mq = app_wrk->event_queue;
Florin Coras2b5fed82019-07-25 14:51:09 -0700697 svm_msg_q_lock (mq);
698
699 if (PREDICT_FALSE (svm_msg_q_is_full (mq)))
700 {
701 clib_warning ("evt q full");
702 svm_msg_q_unlock (mq);
703 return -1;
704 }
Florin Coras623eb562019-02-03 19:28:34 -0800705
706 if (PREDICT_FALSE (svm_msg_q_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
707 {
708 clib_warning ("evt q rings full");
Florin Coras2b5fed82019-07-25 14:51:09 -0700709 svm_msg_q_unlock (mq);
Florin Coras623eb562019-02-03 19:28:34 -0800710 return -1;
711 }
712
713 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
Florin Coras623eb562019-02-03 19:28:34 -0800714 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Corasc0737e92019-03-04 14:19:39 -0800715 evt->session_index = s->rx_fifo->client_session_index;
Florin Corasf6c43132019-03-01 12:41:21 -0800716 evt->event_type = SESSION_IO_EVT_RX;
Florin Coras623eb562019-02-03 19:28:34 -0800717
718 (void) svm_fifo_set_event (s->rx_fifo);
Florin Coras2b5fed82019-07-25 14:51:09 -0700719 svm_msg_q_add_and_unlock (mq, &msg);
Florin Coras623eb562019-02-03 19:28:34 -0800720
Florin Coras623eb562019-02-03 19:28:34 -0800721 return 0;
722}
723
724static inline int
Florin Coras2b5fed82019-07-25 14:51:09 -0700725app_send_io_evt_tx (app_worker_t * app_wrk, session_t * s)
Florin Coras623eb562019-02-03 19:28:34 -0800726{
727 svm_msg_q_t *mq;
728 session_event_t *evt;
729 svm_msg_q_msg_t msg;
730
731 if (app_worker_application_is_builtin (app_wrk))
Florin Coras0e573f52019-05-07 16:28:16 -0700732 return app_worker_builtin_tx (app_wrk, s);
Florin Coras623eb562019-02-03 19:28:34 -0800733
734 mq = app_wrk->event_queue;
Florin Coras2b5fed82019-07-25 14:51:09 -0700735 svm_msg_q_lock (mq);
736
737 if (PREDICT_FALSE (svm_msg_q_is_full (mq)))
738 {
739 clib_warning ("evt q full");
740 svm_msg_q_unlock (mq);
741 return -1;
742 }
Florin Coras623eb562019-02-03 19:28:34 -0800743
744 if (PREDICT_FALSE (svm_msg_q_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
745 {
746 clib_warning ("evt q rings full");
Florin Coras2b5fed82019-07-25 14:51:09 -0700747 svm_msg_q_unlock (mq);
Florin Coras623eb562019-02-03 19:28:34 -0800748 return -1;
749 }
750
751 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
Florin Coras623eb562019-02-03 19:28:34 -0800752 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Corasf6c43132019-03-01 12:41:21 -0800753 evt->event_type = SESSION_IO_EVT_TX;
Florin Corasc0737e92019-03-04 14:19:39 -0800754 evt->session_index = s->tx_fifo->client_session_index;
Florin Coras623eb562019-02-03 19:28:34 -0800755
Florin Coras2b5fed82019-07-25 14:51:09 -0700756 svm_msg_q_add_and_unlock (mq, &msg);
757 return 0;
Florin Coras623eb562019-02-03 19:28:34 -0800758}
759
760/* *INDENT-OFF* */
761typedef int (app_send_evt_handler_fn) (app_worker_t *app,
Florin Coras2b5fed82019-07-25 14:51:09 -0700762 session_t *s);
Florin Coras653e43f2019-03-04 10:56:23 -0800763static app_send_evt_handler_fn * const app_send_evt_handler_fns[2] = {
Florin Coras623eb562019-02-03 19:28:34 -0800764 app_send_io_evt_rx,
Florin Coras623eb562019-02-03 19:28:34 -0800765 app_send_io_evt_tx,
766};
767/* *INDENT-ON* */
768
769/**
770 * Send event to application
771 *
Florin Coras623eb562019-02-03 19:28:34 -0800772 * Logic from queue perspective is blocking. However, if queue is full,
773 * we return.
774 */
775int
776app_worker_lock_and_send_event (app_worker_t * app, session_t * s,
777 u8 evt_type)
778{
Florin Coras2b5fed82019-07-25 14:51:09 -0700779 return app_send_evt_handler_fns[evt_type] (app, s);
Florin Coras623eb562019-02-03 19:28:34 -0800780}
781
Florin Coras623eb562019-02-03 19:28:34 -0800782u8 *
783format_app_worker_listener (u8 * s, va_list * args)
784{
785 app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
786 u64 handle = va_arg (*args, u64);
787 u32 sm_index = va_arg (*args, u32);
788 int verbose = va_arg (*args, int);
789 session_t *listener;
790 const u8 *app_name;
791 u8 *str;
792
793 if (!app_wrk)
794 {
795 if (verbose)
796 s = format (s, "%-40s%-25s%=10s%-15s%-15s%-10s", "Connection", "App",
797 "Wrk", "API Client", "ListenerID", "SegManager");
798 else
799 s = format (s, "%-40s%-25s%=10s", "Connection", "App", "Wrk");
800
801 return s;
802 }
803
804 app_name = application_name_from_index (app_wrk->app_index);
805 listener = listen_session_get_from_handle (handle);
Florin Coras31c99552019-03-01 13:00:58 -0800806 str = format (0, "%U", format_session, listener, verbose);
Florin Coras623eb562019-02-03 19:28:34 -0800807
808 if (verbose)
809 {
Dave Barach3e07a4a2020-04-04 10:05:48 -0400810 u8 *buf;
811 buf = format (0, "%u(%u)", app_wrk->wrk_map_index, app_wrk->wrk_index);
812 s = format (s, "%-40s%-25s%=10v%-15u%-15u%-10u", str, app_name,
Florin Coras623eb562019-02-03 19:28:34 -0800813 buf, app_wrk->api_client_index, handle, sm_index);
Dave Barach3e07a4a2020-04-04 10:05:48 -0400814 vec_free (buf);
Florin Coras623eb562019-02-03 19:28:34 -0800815 }
816 else
817 s = format (s, "%-40s%-25s%=10u", str, app_name, app_wrk->wrk_map_index);
818
819 return s;
820}
821
822u8 *
823format_app_worker (u8 * s, va_list * args)
824{
825 app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
826 u32 indent = 1;
827
828 s = format (s, "%U wrk-index %u app-index %u map-index %u "
829 "api-client-index %d\n", format_white_space, indent,
830 app_wrk->wrk_index, app_wrk->app_index, app_wrk->wrk_map_index,
831 app_wrk->api_client_index);
832 return s;
833}
834
835void
836app_worker_format_connects (app_worker_t * app_wrk, int verbose)
837{
Florin Coras623eb562019-02-03 19:28:34 -0800838 segment_manager_t *sm;
Florin Coras623eb562019-02-03 19:28:34 -0800839
840 /* Header */
841 if (!app_wrk)
842 {
Florin Coras88001c62019-04-24 14:44:46 -0700843 segment_manager_format_sessions (0, verbose);
Florin Coras623eb562019-02-03 19:28:34 -0800844 return;
845 }
846
847 if (app_wrk->connects_seg_manager == (u32) ~ 0)
848 return;
849
Florin Coras623eb562019-02-03 19:28:34 -0800850 sm = segment_manager_get (app_wrk->connects_seg_manager);
Florin Coras88001c62019-04-24 14:44:46 -0700851 segment_manager_format_sessions (sm, verbose);
Florin Coras623eb562019-02-03 19:28:34 -0800852}
853
Florin Coras623eb562019-02-03 19:28:34 -0800854/*
855 * fd.io coding-style-patch-verification: ON
856 *
857 * Local Variables:
858 * eval: (c-set-style "gnu")
859 * End:
860 */