blob: dd159c6693cf8a15a0e503384ac3a923c091dfca [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;
Florin Coras623eb562019-02-03 19:28:34 -0800183 }
Florin Coras2a7c0b62020-09-28 23:40:28 -0700184 else
185 {
186 sm = segment_manager_alloc ();
187 }
Florin Coras623eb562019-02-03 19:28:34 -0800188 sm->app_wrk_index = app_wrk->wrk_index;
Florin Corasa107f402020-09-29 19:18:46 -0700189 segment_manager_init (sm);
Florin Coras623eb562019-02-03 19:28:34 -0800190 return sm;
191}
192
Florin Corasa27a46e2019-02-18 13:02:28 -0800193static int
194app_worker_alloc_session_fifos (segment_manager_t * sm, session_t * s)
195{
196 svm_fifo_t *rx_fifo = 0, *tx_fifo = 0;
Florin Corasa27a46e2019-02-18 13:02:28 -0800197 int rv;
198
Florin Coras62ddc032019-12-08 18:30:42 -0800199 if ((rv = segment_manager_alloc_session_fifos (sm, s->thread_index,
200 &rx_fifo, &tx_fifo)))
Florin Corasa27a46e2019-02-18 13:02:28 -0800201 return rv;
202
203 rx_fifo->master_session_index = s->session_index;
204 rx_fifo->master_thread_index = s->thread_index;
205
206 tx_fifo->master_session_index = s->session_index;
207 tx_fifo->master_thread_index = s->thread_index;
208
209 s->rx_fifo = rx_fifo;
210 s->tx_fifo = tx_fifo;
Florin Corasa27a46e2019-02-18 13:02:28 -0800211 return 0;
212}
213
Florin Coras623eb562019-02-03 19:28:34 -0800214int
Florin Corasd4295e62019-02-22 13:11:38 -0800215app_worker_init_listener (app_worker_t * app_wrk, session_t * ls)
Florin Coras623eb562019-02-03 19:28:34 -0800216{
217 segment_manager_t *sm;
218
219 /* Allocate segment manager. All sessions derived out of a listen session
220 * have fifos allocated by the same segment manager. */
221 if (!(sm = app_worker_alloc_segment_manager (app_wrk)))
Florin Coras00e01d32019-10-21 16:07:46 -0700222 return SESSION_E_ALLOC;
Florin Coras623eb562019-02-03 19:28:34 -0800223
Florin Corasc9940fc2019-02-05 20:55:11 -0800224 /* Keep track of the segment manager for the listener or this worker */
Florin Coras623eb562019-02-03 19:28:34 -0800225 hash_set (app_wrk->listeners_table, listen_session_get_handle (ls),
226 segment_manager_index (sm));
227
Florin Coras87b7e3d2020-03-27 15:06:07 +0000228 if (transport_connection_is_cless (session_get_transport (ls)))
Florin Coras623eb562019-02-03 19:28:34 -0800229 {
Florin Coras87b7e3d2020-03-27 15:06:07 +0000230 if (ls->rx_fifo)
Florin Coras00e01d32019-10-21 16:07:46 -0700231 return SESSION_E_NOSUPPORT;
232 return app_worker_alloc_session_fifos (sm, ls);
Florin Coras623eb562019-02-03 19:28:34 -0800233 }
234 return 0;
235}
236
237int
Florin Corasd4295e62019-02-22 13:11:38 -0800238app_worker_start_listen (app_worker_t * app_wrk,
239 app_listener_t * app_listener)
240{
241 session_t *ls;
Florin Coras00e01d32019-10-21 16:07:46 -0700242 int rv;
Florin Corasd4295e62019-02-22 13:11:38 -0800243
244 if (clib_bitmap_get (app_listener->workers, app_wrk->wrk_map_index))
Florin Coras00e01d32019-10-21 16:07:46 -0700245 return SESSION_E_ALREADY_LISTENING;
Florin Corasd4295e62019-02-22 13:11:38 -0800246
247 app_listener->workers = clib_bitmap_set (app_listener->workers,
248 app_wrk->wrk_map_index, 1);
249
250 if (app_listener->session_index != SESSION_INVALID_INDEX)
251 {
252 ls = session_get (app_listener->session_index, 0);
Florin Coras00e01d32019-10-21 16:07:46 -0700253 if ((rv = app_worker_init_listener (app_wrk, ls)))
254 return rv;
Florin Corasd4295e62019-02-22 13:11:38 -0800255 }
256
257 if (app_listener->local_index != SESSION_INVALID_INDEX)
258 {
259 ls = session_get (app_listener->local_index, 0);
Florin Coras00e01d32019-10-21 16:07:46 -0700260 if ((rv = app_worker_init_listener (app_wrk, ls)))
261 return rv;
Florin Corasd4295e62019-02-22 13:11:38 -0800262 }
263
264 return 0;
265}
266
Florin Coras2b81e3c2019-02-27 07:55:46 -0800267static void
Florin Corasc8e812f2020-05-14 05:32:18 +0000268app_worker_add_detached_sm (app_worker_t * app_wrk, u32 sm_index)
269{
270 vec_add1 (app_wrk->detached_seg_managers, sm_index);
271}
272
273void
274app_worker_del_detached_sm (app_worker_t * app_wrk, u32 sm_index)
275{
276 u32 i;
277
278 clib_spinlock_lock (&app_wrk->detached_seg_managers_lock);
279 for (i = 0; i < vec_len (app_wrk->detached_seg_managers); i++)
280 {
281 if (app_wrk->detached_seg_managers[i] == sm_index)
282 {
283 vec_del1 (app_wrk->detached_seg_managers, i);
284 break;
285 }
286 }
287 clib_spinlock_unlock (&app_wrk->detached_seg_managers_lock);
288}
289
290static void
Florin Coras2b81e3c2019-02-27 07:55:46 -0800291app_worker_stop_listen_session (app_worker_t * app_wrk, session_t * ls)
Florin Coras623eb562019-02-03 19:28:34 -0800292{
Florin Corasc9940fc2019-02-05 20:55:11 -0800293 session_handle_t handle;
Florin Coras623eb562019-02-03 19:28:34 -0800294 segment_manager_t *sm;
295 uword *sm_indexp;
Florin Coras2b81e3c2019-02-27 07:55:46 -0800296
297 handle = listen_session_get_handle (ls);
298 sm_indexp = hash_get (app_wrk->listeners_table, handle);
299 if (PREDICT_FALSE (!sm_indexp))
300 return;
301
Florin Coras1bd46162020-04-13 23:35:55 +0000302 /* Dealloc fifos, if any (dgram listeners) */
Florin Coras87b7e3d2020-03-27 15:06:07 +0000303 if (ls->rx_fifo)
304 {
305 segment_manager_dealloc_fifos (ls->rx_fifo, ls->tx_fifo);
306 ls->tx_fifo = ls->rx_fifo = 0;
307 }
308
Florin Coras1bd46162020-04-13 23:35:55 +0000309 /* Try to cleanup segment manager */
Florin Coras2b81e3c2019-02-27 07:55:46 -0800310 sm = segment_manager_get (*sm_indexp);
Florin Coras1bd46162020-04-13 23:35:55 +0000311 if (sm && app_wrk->first_segment_manager != *sm_indexp)
Florin Coras2b81e3c2019-02-27 07:55:46 -0800312 {
Florin Coras1bd46162020-04-13 23:35:55 +0000313 segment_manager_app_detach (sm);
314 if (!segment_manager_has_fifos (sm))
315 segment_manager_free (sm);
Florin Corasc8e812f2020-05-14 05:32:18 +0000316 else
317 {
318 /* Track segment manager in case app detaches and all the
319 * outstanding sessions need to be closed */
320 app_worker_add_detached_sm (app_wrk, *sm_indexp);
321 sm->flags |= SEG_MANAGER_F_DETACHED_LISTENER;
322 }
Florin Coras2b81e3c2019-02-27 07:55:46 -0800323 }
Florin Coras1bd46162020-04-13 23:35:55 +0000324
Florin Coras2b81e3c2019-02-27 07:55:46 -0800325 hash_unset (app_wrk->listeners_table, handle);
326}
327
328int
329app_worker_stop_listen (app_worker_t * app_wrk, app_listener_t * al)
330{
Florin Corasd4295e62019-02-22 13:11:38 -0800331 session_t *ls;
Florin Coras623eb562019-02-03 19:28:34 -0800332
Florin Corasc9940fc2019-02-05 20:55:11 -0800333 if (!clib_bitmap_get (al->workers, app_wrk->wrk_map_index))
334 return 0;
335
336 if (al->session_index != SESSION_INVALID_INDEX)
Florin Coras623eb562019-02-03 19:28:34 -0800337 {
Florin Corasc9940fc2019-02-05 20:55:11 -0800338 ls = listen_session_get (al->session_index);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800339 app_worker_stop_listen_session (app_wrk, ls);
Florin Coras623eb562019-02-03 19:28:34 -0800340 }
341
Florin Corasc9940fc2019-02-05 20:55:11 -0800342 if (al->local_index != SESSION_INVALID_INDEX)
Florin Coras623eb562019-02-03 19:28:34 -0800343 {
Florin Corasd4295e62019-02-22 13:11:38 -0800344 ls = listen_session_get (al->local_index);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800345 app_worker_stop_listen_session (app_wrk, ls);
Florin Coras623eb562019-02-03 19:28:34 -0800346 }
Florin Corasc9940fc2019-02-05 20:55:11 -0800347
348 clib_bitmap_set_no_check (al->workers, app_wrk->wrk_map_index, 0);
349 if (clib_bitmap_is_zero (al->workers))
350 app_listener_cleanup (al);
Florin Coras623eb562019-02-03 19:28:34 -0800351
352 return 0;
353}
354
355int
Florin Corasa27a46e2019-02-18 13:02:28 -0800356app_worker_init_accepted (session_t * s)
357{
358 app_worker_t *app_wrk;
359 segment_manager_t *sm;
360 session_t *listener;
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000361 application_t *app;
Florin Corasa27a46e2019-02-18 13:02:28 -0800362
Nathan Skrzypczak2f0f96b2019-06-13 10:14:28 +0200363 listener = listen_session_get_from_handle (s->listener_handle);
Florin Corasa27a46e2019-02-18 13:02:28 -0800364 app_wrk = application_listener_select_worker (listener);
365 s->app_wrk_index = app_wrk->wrk_index;
Florin Coras2b81e3c2019-02-27 07:55:46 -0800366
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000367 app = application_get (app_wrk->app_index);
368 if (app->cb_fns.fifo_tuning_callback)
369 s->flags |= SESSION_F_CUSTOM_FIFO_TUNING;
370
Florin Corasa27a46e2019-02-18 13:02:28 -0800371 sm = app_worker_get_listen_segment_manager (app_wrk, listener);
Florin Coras2b81e3c2019-02-27 07:55:46 -0800372 if (app_worker_alloc_session_fifos (sm, s))
373 return -1;
374
375 return 0;
Florin Corasa27a46e2019-02-18 13:02:28 -0800376}
377
378int
379app_worker_accept_notify (app_worker_t * app_wrk, session_t * s)
380{
381 application_t *app = application_get (app_wrk->app_index);
382 return app->cb_fns.session_accept_callback (s);
383}
384
385int
386app_worker_init_connected (app_worker_t * app_wrk, session_t * s)
387{
388 application_t *app = application_get (app_wrk->app_index);
389 segment_manager_t *sm;
390
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000391 if (app->cb_fns.fifo_tuning_callback)
392 s->flags |= SESSION_F_CUSTOM_FIFO_TUNING;
393
Florin Corase6552402020-11-11 13:25:53 -0800394 /* Allocate fifos for session, unless the app is a builtin proxy */
395 if (application_is_builtin_proxy (app))
396 return 0;
397
398 sm = app_worker_get_connect_segment_manager (app_wrk);
399 return app_worker_alloc_session_fifos (sm, s);
Florin Corasa27a46e2019-02-18 13:02:28 -0800400}
401
402int
Florin Coras00e01d32019-10-21 16:07:46 -0700403app_worker_connect_notify (app_worker_t * app_wrk, session_t * s,
404 session_error_t err, u32 opaque)
Florin Corasa27a46e2019-02-18 13:02:28 -0800405{
406 application_t *app = application_get (app_wrk->app_index);
407 return app->cb_fns.session_connected_callback (app_wrk->wrk_index, opaque,
Florin Coras00e01d32019-10-21 16:07:46 -0700408 s, err);
Florin Corasa27a46e2019-02-18 13:02:28 -0800409}
410
411int
Florin Corasd50ff7f2020-04-16 04:30:22 +0000412app_worker_add_half_open (app_worker_t * app_wrk, transport_proto_t tp,
413 session_handle_t ho_handle,
414 session_handle_t wrk_handle)
415{
416 ASSERT (vlib_get_thread_index () == 0);
417 vec_validate (app_wrk->half_open_table, tp);
418 hash_set (app_wrk->half_open_table[tp], ho_handle, wrk_handle);
419 return 0;
420}
421
422int
423app_worker_del_half_open (app_worker_t * app_wrk, transport_proto_t tp,
424 session_handle_t ho_handle)
425{
426 ASSERT (vlib_get_thread_index () == 0);
427 hash_unset (app_wrk->half_open_table[tp], ho_handle);
428 return 0;
429}
430
431u64
432app_worker_lookup_half_open (app_worker_t * app_wrk, transport_proto_t tp,
433 session_handle_t ho_handle)
434{
435 u64 *ho_wrk_handlep;
436
437 /* No locking because all updates are done from main thread */
438 ho_wrk_handlep = hash_get (app_wrk->half_open_table[tp], ho_handle);
439 if (!ho_wrk_handlep)
440 return SESSION_INVALID_HANDLE;
441
442 return *ho_wrk_handlep;
443}
444
445int
Florin Corasbf7ce2c2019-03-06 14:44:42 -0800446app_worker_close_notify (app_worker_t * app_wrk, session_t * s)
447{
448 application_t *app = application_get (app_wrk->app_index);
449 app->cb_fns.session_disconnect_callback (s);
450 return 0;
451}
452
453int
Florin Coras692b9492019-07-12 15:01:53 -0700454app_worker_transport_closed_notify (app_worker_t * app_wrk, session_t * s)
455{
456 application_t *app = application_get (app_wrk->app_index);
457 if (app->cb_fns.session_transport_closed_callback)
458 app->cb_fns.session_transport_closed_callback (s);
459 return 0;
460}
461
462int
Florin Coras69b68ef2019-04-02 11:38:51 -0700463app_worker_reset_notify (app_worker_t * app_wrk, session_t * s)
464{
465 application_t *app = application_get (app_wrk->app_index);
466 app->cb_fns.session_reset_callback (s);
467 return 0;
468}
469
470int
Florin Coras70f26d52019-07-08 11:47:18 -0700471app_worker_cleanup_notify (app_worker_t * app_wrk, session_t * s,
472 session_cleanup_ntf_t ntf)
473{
474 application_t *app = application_get (app_wrk->app_index);
475 if (app->cb_fns.session_cleanup_callback)
476 app->cb_fns.session_cleanup_callback (s, ntf);
477 return 0;
478}
479
480int
Florin Corasbf7ce2c2019-03-06 14:44:42 -0800481app_worker_builtin_rx (app_worker_t * app_wrk, session_t * s)
482{
483 application_t *app = application_get (app_wrk->app_index);
484 app->cb_fns.builtin_app_rx_callback (s);
485 return 0;
486}
487
488int
Florin Coras0e573f52019-05-07 16:28:16 -0700489app_worker_builtin_tx (app_worker_t * app_wrk, session_t * s)
490{
491 application_t *app = application_get (app_wrk->app_index);
492
493 if (!app->cb_fns.builtin_app_tx_callback)
494 return 0;
495
496 app->cb_fns.builtin_app_tx_callback (s);
497 return 0;
498}
499
500int
Florin Coras49568af2019-07-31 16:46:24 -0700501app_worker_migrate_notify (app_worker_t * app_wrk, session_t * s,
502 session_handle_t new_sh)
503{
504 application_t *app = application_get (app_wrk->app_index);
505 app->cb_fns.session_migrate_callback (s, new_sh);
506 return 0;
507}
508
509int
Florin Coras623eb562019-02-03 19:28:34 -0800510app_worker_own_session (app_worker_t * app_wrk, session_t * s)
511{
512 segment_manager_t *sm;
513 svm_fifo_t *rxf, *txf;
514
515 if (s->session_state == SESSION_STATE_LISTENING)
516 return application_change_listener_owner (s, app_wrk);
517
518 s->app_wrk_index = app_wrk->wrk_index;
519
520 rxf = s->rx_fifo;
521 txf = s->tx_fifo;
522
523 if (!rxf || !txf)
524 return 0;
525
526 s->rx_fifo = 0;
527 s->tx_fifo = 0;
528
529 sm = app_worker_get_or_alloc_connect_segment_manager (app_wrk);
Florin Corasa27a46e2019-02-18 13:02:28 -0800530 if (app_worker_alloc_session_fifos (sm, s))
Florin Coras623eb562019-02-03 19:28:34 -0800531 return -1;
532
Sirshak Das28aa5392019-02-05 01:33:33 -0600533 if (!svm_fifo_is_empty_cons (rxf))
534 svm_fifo_clone (s->rx_fifo, rxf);
Florin Coras623eb562019-02-03 19:28:34 -0800535
Sirshak Das28aa5392019-02-05 01:33:33 -0600536 if (!svm_fifo_is_empty_cons (txf))
537 svm_fifo_clone (s->tx_fifo, txf);
538
Florin Coras19223e02019-03-03 14:56:05 -0800539 segment_manager_dealloc_fifos (rxf, txf);
Florin Coras623eb562019-02-03 19:28:34 -0800540
541 return 0;
542}
543
544int
Florin Coras72db6642020-04-15 01:30:46 +0000545app_worker_connect_session (app_worker_t * app_wrk, session_endpoint_t * sep,
Florin Corasc9940fc2019-02-05 20:55:11 -0800546 u32 api_context)
Florin Coras623eb562019-02-03 19:28:34 -0800547{
548 int rv;
549
550 /* Make sure we have a segment manager for connects */
Florin Coras72db6642020-04-15 01:30:46 +0000551 if (app_worker_alloc_connects_segment_manager (app_wrk))
552 return SESSION_E_ALLOC;
Florin Coras623eb562019-02-03 19:28:34 -0800553
Florin Coras72db6642020-04-15 01:30:46 +0000554 if ((rv = session_open (app_wrk->wrk_index, sep, api_context)))
Florin Coras623eb562019-02-03 19:28:34 -0800555 return rv;
556
557 return 0;
558}
559
560int
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000561app_worker_session_fifo_tuning (app_worker_t * app_wrk, session_t * s,
562 svm_fifo_t * f,
563 session_ft_action_t act, u32 len)
564{
565 application_t *app = application_get (app_wrk->app_index);
566 return app->cb_fns.fifo_tuning_callback (s, f, act, len);
567}
568
569int
Florin Coras623eb562019-02-03 19:28:34 -0800570app_worker_alloc_connects_segment_manager (app_worker_t * app_wrk)
571{
572 segment_manager_t *sm;
573
574 if (app_wrk->connects_seg_manager == APP_INVALID_SEGMENT_MANAGER_INDEX)
575 {
576 sm = app_worker_alloc_segment_manager (app_wrk);
577 if (sm == 0)
578 return -1;
579 app_wrk->connects_seg_manager = segment_manager_index (sm);
580 }
581 return 0;
582}
583
584segment_manager_t *
585app_worker_get_connect_segment_manager (app_worker_t * app)
586{
587 ASSERT (app->connects_seg_manager != (u32) ~ 0);
588 return segment_manager_get (app->connects_seg_manager);
589}
590
591segment_manager_t *
592app_worker_get_or_alloc_connect_segment_manager (app_worker_t * app_wrk)
593{
594 if (app_wrk->connects_seg_manager == (u32) ~ 0)
595 app_worker_alloc_connects_segment_manager (app_wrk);
596 return segment_manager_get (app_wrk->connects_seg_manager);
597}
598
599segment_manager_t *
600app_worker_get_listen_segment_manager (app_worker_t * app,
601 session_t * listener)
602{
603 uword *smp;
604 smp = hash_get (app->listeners_table, listen_session_get_handle (listener));
Dave Barach47d41ad2020-02-17 09:13:26 -0500605 ALWAYS_ASSERT (smp != 0);
Florin Coras623eb562019-02-03 19:28:34 -0800606 return segment_manager_get (*smp);
607}
608
609session_t *
Florin Corasc9940fc2019-02-05 20:55:11 -0800610app_worker_first_listener (app_worker_t * app_wrk, u8 fib_proto,
Florin Coras623eb562019-02-03 19:28:34 -0800611 u8 transport_proto)
612{
613 session_t *listener;
614 u64 handle;
615 u32 sm_index;
616 u8 sst;
617
618 sst = session_type_from_proto_and_ip (transport_proto,
619 fib_proto == FIB_PROTOCOL_IP4);
620
621 /* *INDENT-OFF* */
Florin Corasc9940fc2019-02-05 20:55:11 -0800622 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
Florin Coras623eb562019-02-03 19:28:34 -0800623 listener = listen_session_get_from_handle (handle);
624 if (listener->session_type == sst
Florin Corasd5c604d2019-03-18 09:06:35 -0700625 && !(listener->flags & SESSION_F_PROXY))
Florin Coras623eb562019-02-03 19:28:34 -0800626 return listener;
627 }));
628 /* *INDENT-ON* */
629
630 return 0;
631}
632
633session_t *
Florin Corasc9940fc2019-02-05 20:55:11 -0800634app_worker_proxy_listener (app_worker_t * app_wrk, u8 fib_proto,
Florin Coras623eb562019-02-03 19:28:34 -0800635 u8 transport_proto)
636{
637 session_t *listener;
638 u64 handle;
639 u32 sm_index;
640 u8 sst;
641
642 sst = session_type_from_proto_and_ip (transport_proto,
643 fib_proto == FIB_PROTOCOL_IP4);
644
645 /* *INDENT-OFF* */
Florin Corasc9940fc2019-02-05 20:55:11 -0800646 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
Florin Coras623eb562019-02-03 19:28:34 -0800647 listener = listen_session_get_from_handle (handle);
Florin Corasd5c604d2019-03-18 09:06:35 -0700648 if (listener->session_type == sst && (listener->flags & SESSION_F_PROXY))
Florin Coras623eb562019-02-03 19:28:34 -0800649 return listener;
650 }));
651 /* *INDENT-ON* */
652
653 return 0;
654}
655
656/**
657 * Send an API message to the external app, to map new segment
658 */
659int
Florin Coras2b81e3c2019-02-27 07:55:46 -0800660app_worker_add_segment_notify (app_worker_t * app_wrk, u64 segment_handle)
Florin Coras623eb562019-02-03 19:28:34 -0800661{
Florin Coras623eb562019-02-03 19:28:34 -0800662 application_t *app = application_get (app_wrk->app_index);
Florin Corasc4c4cf52019-08-24 18:17:34 -0700663
664 return app->cb_fns.add_segment_callback (app_wrk->wrk_index,
Florin Coras623eb562019-02-03 19:28:34 -0800665 segment_handle);
666}
667
Florin Coras2b81e3c2019-02-27 07:55:46 -0800668int
669app_worker_del_segment_notify (app_worker_t * app_wrk, u64 segment_handle)
670{
671 application_t *app = application_get (app_wrk->app_index);
Florin Corasc4c4cf52019-08-24 18:17:34 -0700672 return app->cb_fns.del_segment_callback (app_wrk->wrk_index,
Florin Coras2b81e3c2019-02-27 07:55:46 -0800673 segment_handle);
674}
675
Florin Coras31c99552019-03-01 13:00:58 -0800676static inline u8
Florin Coras623eb562019-02-03 19:28:34 -0800677app_worker_application_is_builtin (app_worker_t * app_wrk)
678{
679 return app_wrk->app_is_builtin;
680}
681
682static inline int
Florin Coras2b5fed82019-07-25 14:51:09 -0700683app_send_io_evt_rx (app_worker_t * app_wrk, session_t * s)
Florin Coras623eb562019-02-03 19:28:34 -0800684{
685 session_event_t *evt;
686 svm_msg_q_msg_t msg;
687 svm_msg_q_t *mq;
688
Florin Coras5c290292019-09-19 08:19:44 -0700689 if (app_worker_application_is_builtin (app_wrk))
690 return app_worker_builtin_rx (app_wrk, s);
691
Florin Coras653e43f2019-03-04 10:56:23 -0800692 if (svm_fifo_has_event (s->rx_fifo))
Florin Coras623eb562019-02-03 19:28:34 -0800693 return 0;
694
695 mq = app_wrk->event_queue;
Florin Coras2b5fed82019-07-25 14:51:09 -0700696 svm_msg_q_lock (mq);
697
698 if (PREDICT_FALSE (svm_msg_q_is_full (mq)))
699 {
700 clib_warning ("evt q full");
701 svm_msg_q_unlock (mq);
702 return -1;
703 }
Florin Coras623eb562019-02-03 19:28:34 -0800704
705 if (PREDICT_FALSE (svm_msg_q_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
706 {
707 clib_warning ("evt q rings full");
Florin Coras2b5fed82019-07-25 14:51:09 -0700708 svm_msg_q_unlock (mq);
Florin Coras623eb562019-02-03 19:28:34 -0800709 return -1;
710 }
711
712 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
Florin Coras623eb562019-02-03 19:28:34 -0800713 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Corasc0737e92019-03-04 14:19:39 -0800714 evt->session_index = s->rx_fifo->client_session_index;
Florin Corasf6c43132019-03-01 12:41:21 -0800715 evt->event_type = SESSION_IO_EVT_RX;
Florin Coras623eb562019-02-03 19:28:34 -0800716
717 (void) svm_fifo_set_event (s->rx_fifo);
Florin Coras2b5fed82019-07-25 14:51:09 -0700718 svm_msg_q_add_and_unlock (mq, &msg);
Florin Coras623eb562019-02-03 19:28:34 -0800719
Florin Coras623eb562019-02-03 19:28:34 -0800720 return 0;
721}
722
723static inline int
Florin Coras2b5fed82019-07-25 14:51:09 -0700724app_send_io_evt_tx (app_worker_t * app_wrk, session_t * s)
Florin Coras623eb562019-02-03 19:28:34 -0800725{
726 svm_msg_q_t *mq;
727 session_event_t *evt;
728 svm_msg_q_msg_t msg;
729
730 if (app_worker_application_is_builtin (app_wrk))
Florin Coras0e573f52019-05-07 16:28:16 -0700731 return app_worker_builtin_tx (app_wrk, s);
Florin Coras623eb562019-02-03 19:28:34 -0800732
733 mq = app_wrk->event_queue;
Florin Coras2b5fed82019-07-25 14:51:09 -0700734 svm_msg_q_lock (mq);
735
736 if (PREDICT_FALSE (svm_msg_q_is_full (mq)))
737 {
738 clib_warning ("evt q full");
739 svm_msg_q_unlock (mq);
740 return -1;
741 }
Florin Coras623eb562019-02-03 19:28:34 -0800742
743 if (PREDICT_FALSE (svm_msg_q_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
744 {
745 clib_warning ("evt q rings full");
Florin Coras2b5fed82019-07-25 14:51:09 -0700746 svm_msg_q_unlock (mq);
Florin Coras623eb562019-02-03 19:28:34 -0800747 return -1;
748 }
749
750 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
Florin Coras623eb562019-02-03 19:28:34 -0800751 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Corasf6c43132019-03-01 12:41:21 -0800752 evt->event_type = SESSION_IO_EVT_TX;
Florin Corasc0737e92019-03-04 14:19:39 -0800753 evt->session_index = s->tx_fifo->client_session_index;
Florin Coras623eb562019-02-03 19:28:34 -0800754
Florin Coras2b5fed82019-07-25 14:51:09 -0700755 svm_msg_q_add_and_unlock (mq, &msg);
756 return 0;
Florin Coras623eb562019-02-03 19:28:34 -0800757}
758
759/* *INDENT-OFF* */
760typedef int (app_send_evt_handler_fn) (app_worker_t *app,
Florin Coras2b5fed82019-07-25 14:51:09 -0700761 session_t *s);
Florin Coras653e43f2019-03-04 10:56:23 -0800762static app_send_evt_handler_fn * const app_send_evt_handler_fns[2] = {
Florin Coras623eb562019-02-03 19:28:34 -0800763 app_send_io_evt_rx,
Florin Coras623eb562019-02-03 19:28:34 -0800764 app_send_io_evt_tx,
765};
766/* *INDENT-ON* */
767
768/**
769 * Send event to application
770 *
Florin Coras623eb562019-02-03 19:28:34 -0800771 * Logic from queue perspective is blocking. However, if queue is full,
772 * we return.
773 */
774int
775app_worker_lock_and_send_event (app_worker_t * app, session_t * s,
776 u8 evt_type)
777{
Florin Coras2b5fed82019-07-25 14:51:09 -0700778 return app_send_evt_handler_fns[evt_type] (app, s);
Florin Coras623eb562019-02-03 19:28:34 -0800779}
780
Florin Coras623eb562019-02-03 19:28:34 -0800781u8 *
782format_app_worker_listener (u8 * s, va_list * args)
783{
784 app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
785 u64 handle = va_arg (*args, u64);
786 u32 sm_index = va_arg (*args, u32);
787 int verbose = va_arg (*args, int);
788 session_t *listener;
789 const u8 *app_name;
790 u8 *str;
791
792 if (!app_wrk)
793 {
794 if (verbose)
Florin Coras91413ac2020-10-13 07:40:42 -0700795 s = format (s, "%-40s%-25s%-10s%-15s%-15s%-10s", "Connection", "App",
Florin Coras623eb562019-02-03 19:28:34 -0800796 "Wrk", "API Client", "ListenerID", "SegManager");
797 else
Florin Coras91413ac2020-10-13 07:40:42 -0700798 s = format (s, "%-40s%-25s%-10s", "Connection", "App", "Wrk");
Florin Coras623eb562019-02-03 19:28:34 -0800799
800 return s;
801 }
802
803 app_name = application_name_from_index (app_wrk->app_index);
804 listener = listen_session_get_from_handle (handle);
Florin Coras31c99552019-03-01 13:00:58 -0800805 str = format (0, "%U", format_session, listener, verbose);
Florin Coras623eb562019-02-03 19:28:34 -0800806
807 if (verbose)
808 {
Dave Barach3e07a4a2020-04-04 10:05:48 -0400809 u8 *buf;
810 buf = format (0, "%u(%u)", app_wrk->wrk_map_index, app_wrk->wrk_index);
Florin Coras91413ac2020-10-13 07:40:42 -0700811 s = format (s, "%-40v%-25v%-10v%-15u%-15u%-10u", str, app_name,
Florin Coras623eb562019-02-03 19:28:34 -0800812 buf, app_wrk->api_client_index, handle, sm_index);
Dave Barach3e07a4a2020-04-04 10:05:48 -0400813 vec_free (buf);
Florin Coras623eb562019-02-03 19:28:34 -0800814 }
815 else
jiangxiaoming6b410e62020-10-10 15:23:54 +0800816 s = format (s, "%-40v%-25v%=10u", str, app_name, app_wrk->wrk_map_index);
817
818 vec_free (str);
Florin Coras623eb562019-02-03 19:28:34 -0800819
820 return s;
821}
822
823u8 *
824format_app_worker (u8 * s, va_list * args)
825{
826 app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
827 u32 indent = 1;
828
829 s = format (s, "%U wrk-index %u app-index %u map-index %u "
830 "api-client-index %d\n", format_white_space, indent,
831 app_wrk->wrk_index, app_wrk->app_index, app_wrk->wrk_map_index,
832 app_wrk->api_client_index);
833 return s;
834}
835
836void
837app_worker_format_connects (app_worker_t * app_wrk, int verbose)
838{
Florin Coras623eb562019-02-03 19:28:34 -0800839 segment_manager_t *sm;
Florin Coras623eb562019-02-03 19:28:34 -0800840
841 /* Header */
842 if (!app_wrk)
843 {
Florin Coras88001c62019-04-24 14:44:46 -0700844 segment_manager_format_sessions (0, verbose);
Florin Coras623eb562019-02-03 19:28:34 -0800845 return;
846 }
847
848 if (app_wrk->connects_seg_manager == (u32) ~ 0)
849 return;
850
Florin Coras623eb562019-02-03 19:28:34 -0800851 sm = segment_manager_get (app_wrk->connects_seg_manager);
Florin Coras88001c62019-04-24 14:44:46 -0700852 segment_manager_format_sessions (sm, verbose);
Florin Coras623eb562019-02-03 19:28:34 -0800853}
854
Florin Coras623eb562019-02-03 19:28:34 -0800855/*
856 * fd.io coding-style-patch-verification: ON
857 *
858 * Local Variables:
859 * eval: (c-set-style "gnu")
860 * End:
861 */