blob: 19c8fa2f2e0bf3c2bcc7677d9a6635a743a6fd4b [file] [log] [blame]
Dave Barach68b0fb02017-02-28 15:15:56 -05001/*
2 * Copyright (c) 2017 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/session/application.h>
Florin Coras6cf30ad2017-04-04 23:08:23 -070017#include <vnet/session/application_interface.h>
Florin Corascea194d2017-10-02 00:18:51 -070018#include <vnet/session/application_namespace.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050019#include <vnet/session/session.h>
20
Florin Coras15531972018-08-12 23:50:53 -070021static app_main_t app_main;
Dave Barach68b0fb02017-02-28 15:15:56 -050022
Florin Corasab2f6db2018-08-31 14:31:41 -070023static app_listener_t *
24app_listener_alloc (application_t * app)
25{
26 app_listener_t *app_listener;
27 pool_get (app->listeners, app_listener);
Dave Barachb7b92992018-10-17 10:38:51 -040028 clib_memset (app_listener, 0, sizeof (*app_listener));
Florin Corasab2f6db2018-08-31 14:31:41 -070029 app_listener->al_index = app_listener - app->listeners;
30 return app_listener;
31}
32
33static app_listener_t *
34app_listener_get (application_t * app, u32 app_listener_index)
35{
36 return pool_elt_at_index (app->listeners, app_listener_index);
37}
38
39static void
40app_listener_free (application_t * app, app_listener_t * app_listener)
41{
42 clib_bitmap_free (app_listener->workers);
43 pool_put (app->listeners, app_listener);
44 if (CLIB_DEBUG)
Dave Barachb7b92992018-10-17 10:38:51 -040045 clib_memset (app_listener, 0xfa, sizeof (*app_listener));
Florin Corasab2f6db2018-08-31 14:31:41 -070046}
47
48static app_listener_t *
49app_local_listener_alloc (application_t * app)
50{
51 app_listener_t *app_listener;
52 pool_get (app->local_listeners, app_listener);
Dave Barachb7b92992018-10-17 10:38:51 -040053 clib_memset (app_listener, 0, sizeof (*app_listener));
Florin Corasab2f6db2018-08-31 14:31:41 -070054 app_listener->al_index = app_listener - app->local_listeners;
55 return app_listener;
56}
57
58static app_listener_t *
59app_local_listener_get (application_t * app, u32 app_listener_index)
60{
61 return pool_elt_at_index (app->local_listeners, app_listener_index);
62}
63
64static void
65app_local_listener_free (application_t * app, app_listener_t * app_listener)
66{
67 clib_bitmap_free (app_listener->workers);
68 pool_put (app->local_listeners, app_listener);
69 if (CLIB_DEBUG)
Dave Barachb7b92992018-10-17 10:38:51 -040070 clib_memset (app_listener, 0xfa, sizeof (*app_listener));
Florin Corasab2f6db2018-08-31 14:31:41 -070071}
72
Florin Coras15531972018-08-12 23:50:53 -070073static app_worker_map_t *
74app_worker_map_alloc (application_t * app)
75{
76 app_worker_map_t *map;
77 pool_get (app->worker_maps, map);
Dave Barachb7b92992018-10-17 10:38:51 -040078 clib_memset (map, 0, sizeof (*map));
Florin Coras15531972018-08-12 23:50:53 -070079 return map;
80}
Dave Barach68b0fb02017-02-28 15:15:56 -050081
Florin Coras15531972018-08-12 23:50:53 -070082static u32
83app_worker_map_index (application_t * app, app_worker_map_t * map)
84{
85 return (map - app->worker_maps);
86}
87
88static void
89app_worker_map_free (application_t * app, app_worker_map_t * map)
90{
91 pool_put (app->worker_maps, map);
92}
93
94static app_worker_map_t *
95app_worker_map_get (application_t * app, u32 map_index)
96{
Florin Coras01f3f892018-12-02 12:45:53 -080097 if (pool_is_free_index (app->worker_maps, map_index))
98 return 0;
Florin Coras15531972018-08-12 23:50:53 -070099 return pool_elt_at_index (app->worker_maps, map_index);
100}
Florin Coras0bee9ce2018-03-22 21:24:31 -0700101
Florin Coras053a0e42018-11-13 15:52:38 -0800102static const u8 *
Florin Coras0bee9ce2018-03-22 21:24:31 -0700103app_get_name (application_t * app)
104{
Florin Coras0bee9ce2018-03-22 21:24:31 -0700105 return app->name;
106}
107
Florin Corascea194d2017-10-02 00:18:51 -0700108u32
109application_session_table (application_t * app, u8 fib_proto)
110{
111 app_namespace_t *app_ns;
112 app_ns = app_namespace_get (app->ns_index);
113 if (!application_has_global_scope (app))
114 return APP_INVALID_INDEX;
115 if (fib_proto == FIB_PROTOCOL_IP4)
116 return session_lookup_get_index_for_fib (fib_proto,
117 app_ns->ip4_fib_index);
118 else
119 return session_lookup_get_index_for_fib (fib_proto,
120 app_ns->ip6_fib_index);
121}
122
123u32
124application_local_session_table (application_t * app)
125{
126 app_namespace_t *app_ns;
127 if (!application_has_local_scope (app))
128 return APP_INVALID_INDEX;
129 app_ns = app_namespace_get (app->ns_index);
130 return app_ns->local_table_index;
131}
132
Florin Corasab2f6db2018-08-31 14:31:41 -0700133static void
134application_local_listener_session_endpoint (local_session_t * ll,
135 session_endpoint_t * sep)
136{
137 sep->transport_proto =
138 session_type_transport_proto (ll->listener_session_type);
139 sep->port = ll->port;
140 sep->is_ip4 = ll->listener_session_type & 1;
141}
142
Florin Corascea194d2017-10-02 00:18:51 -0700143/**
Florin Coras053a0e42018-11-13 15:52:38 -0800144 * Returns app name for app-index
Florin Corascea194d2017-10-02 00:18:51 -0700145 */
Florin Coras053a0e42018-11-13 15:52:38 -0800146const u8 *
Florin Corascea194d2017-10-02 00:18:51 -0700147application_name_from_index (u32 app_index)
148{
149 application_t *app = application_get (app_index);
150 if (!app)
151 return 0;
Florin Coras053a0e42018-11-13 15:52:38 -0800152 return app_get_name (app);
153}
154
155static void
156application_api_table_add (u32 app_index, u32 api_client_index)
157{
Florin Corasc1f5a432018-11-20 11:31:26 -0800158 if (api_client_index != APP_INVALID_INDEX)
159 hash_set (app_main.app_by_api_client_index, api_client_index, app_index);
Florin Coras053a0e42018-11-13 15:52:38 -0800160}
161
162static void
163application_api_table_del (u32 api_client_index)
164{
165 hash_unset (app_main.app_by_api_client_index, api_client_index);
Florin Corascea194d2017-10-02 00:18:51 -0700166}
167
Dave Barach68b0fb02017-02-28 15:15:56 -0500168static void
Florin Corasc1f5a432018-11-20 11:31:26 -0800169application_name_table_add (application_t * app)
Dave Barach68b0fb02017-02-28 15:15:56 -0500170{
Florin Corasc1f5a432018-11-20 11:31:26 -0800171 hash_set_mem (app_main.app_by_name, app->name, app->app_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500172}
173
174static void
Florin Corasc1f5a432018-11-20 11:31:26 -0800175application_name_table_del (application_t * app)
Dave Barach68b0fb02017-02-28 15:15:56 -0500176{
Florin Corasc1f5a432018-11-20 11:31:26 -0800177 hash_unset_mem (app_main.app_by_name, app->name);
Dave Barach68b0fb02017-02-28 15:15:56 -0500178}
179
180application_t *
181application_lookup (u32 api_client_index)
182{
183 uword *p;
Florin Coras15531972018-08-12 23:50:53 -0700184 p = hash_get (app_main.app_by_api_client_index, api_client_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500185 if (p)
Florin Coras053a0e42018-11-13 15:52:38 -0800186 return application_get_if_valid (p[0]);
Dave Barach68b0fb02017-02-28 15:15:56 -0500187
188 return 0;
189}
190
Florin Coras6cf30ad2017-04-04 23:08:23 -0700191application_t *
Florin Coras0bee9ce2018-03-22 21:24:31 -0700192application_lookup_name (const u8 * name)
193{
194 uword *p;
Florin Coras15531972018-08-12 23:50:53 -0700195 p = hash_get_mem (app_main.app_by_name, name);
Florin Coras0bee9ce2018-03-22 21:24:31 -0700196 if (p)
197 return application_get (p[0]);
198
199 return 0;
200}
201
202application_t *
Florin Coras15531972018-08-12 23:50:53 -0700203application_alloc (void)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700204{
205 application_t *app;
Florin Coras15531972018-08-12 23:50:53 -0700206 pool_get (app_main.app_pool, app);
Dave Barachb7b92992018-10-17 10:38:51 -0400207 clib_memset (app, 0, sizeof (*app));
Florin Coras15531972018-08-12 23:50:53 -0700208 app->app_index = app - app_main.app_pool;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700209 return app;
210}
211
Florin Coras15531972018-08-12 23:50:53 -0700212application_t *
213application_get (u32 app_index)
Dave Barach68b0fb02017-02-28 15:15:56 -0500214{
Florin Coras15531972018-08-12 23:50:53 -0700215 if (app_index == APP_INVALID_INDEX)
216 return 0;
217 return pool_elt_at_index (app_main.app_pool, app_index);
218}
Dave Barach68b0fb02017-02-28 15:15:56 -0500219
Florin Coras15531972018-08-12 23:50:53 -0700220application_t *
221application_get_if_valid (u32 app_index)
222{
223 if (pool_is_free_index (app_main.app_pool, app_index))
224 return 0;
Florin Corasa5464812017-04-19 13:00:05 -0700225
Florin Coras15531972018-08-12 23:50:53 -0700226 return pool_elt_at_index (app_main.app_pool, app_index);
227}
Florin Coras7999e832017-10-31 01:51:04 -0700228
Florin Corasd79b41e2017-03-04 05:37:52 -0800229static void
Florin Coras6cf30ad2017-04-04 23:08:23 -0700230application_verify_cb_fns (session_cb_vft_t * cb_fns)
Florin Corasd79b41e2017-03-04 05:37:52 -0800231{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700232 if (cb_fns->session_accept_callback == 0)
Florin Corasd79b41e2017-03-04 05:37:52 -0800233 clib_warning ("No accept callback function provided");
Florin Coras6cf30ad2017-04-04 23:08:23 -0700234 if (cb_fns->session_connected_callback == 0)
Florin Corasd79b41e2017-03-04 05:37:52 -0800235 clib_warning ("No session connected callback function provided");
236 if (cb_fns->session_disconnect_callback == 0)
237 clib_warning ("No session disconnect callback function provided");
238 if (cb_fns->session_reset_callback == 0)
239 clib_warning ("No session reset callback function provided");
240}
241
Florin Corasb384b542018-01-15 01:08:33 -0800242/**
243 * Check app config for given segment type
244 *
245 * Returns 1 on success and 0 otherwise
246 */
247static u8
248application_verify_cfg (ssvm_segment_type_t st)
249{
250 u8 is_valid;
251 if (st == SSVM_SEGMENT_MEMFD)
252 {
253 is_valid = (session_manager_get_evt_q_segment () != 0);
254 if (!is_valid)
255 clib_warning ("memfd seg: vpp's event qs IN binary api svm region");
256 return is_valid;
257 }
258 else if (st == SSVM_SEGMENT_SHM)
259 {
260 is_valid = (session_manager_get_evt_q_segment () == 0);
261 if (!is_valid)
262 clib_warning ("shm seg: vpp's event qs NOT IN binary api svm region");
263 return is_valid;
264 }
265 else
266 return 1;
267}
268
Florin Coras6cf30ad2017-04-04 23:08:23 -0700269int
Florin Coras15531972018-08-12 23:50:53 -0700270application_alloc_and_init (app_init_args_t * a)
Dave Barach68b0fb02017-02-28 15:15:56 -0500271{
Florin Corasa332c462018-01-31 06:52:17 -0800272 ssvm_segment_type_t seg_type = SSVM_SEGMENT_MEMFD;
Florin Corasb384b542018-01-15 01:08:33 -0800273 segment_manager_properties_t *props;
274 vl_api_registration_t *reg;
Florin Coras15531972018-08-12 23:50:53 -0700275 application_t *app;
276 u64 *options;
Dave Barach68b0fb02017-02-28 15:15:56 -0500277
Florin Coras15531972018-08-12 23:50:53 -0700278 app = application_alloc ();
279 options = a->options;
Florin Corasb384b542018-01-15 01:08:33 -0800280 /*
281 * Make sure we support the requested configuration
282 */
Florin Corasa332c462018-01-31 06:52:17 -0800283 if (!(options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_IS_BUILTIN))
284 {
Florin Coras15531972018-08-12 23:50:53 -0700285 reg = vl_api_client_index_to_registration (a->api_client_index);
Florin Corasa332c462018-01-31 06:52:17 -0800286 if (!reg)
287 return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
288 if (vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
289 seg_type = SSVM_SEGMENT_SHM;
290 }
291 else
292 {
Florin Coras99368312018-08-02 10:45:44 -0700293 if (options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
294 {
295 clib_warning ("mq eventfds can only be used if socket transport is "
296 "used for api");
297 return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
298 }
Florin Corasa332c462018-01-31 06:52:17 -0800299 seg_type = SSVM_SEGMENT_PRIVATE;
300 }
Florin Corasb384b542018-01-15 01:08:33 -0800301
Florin Corasa332c462018-01-31 06:52:17 -0800302 if (!application_verify_cfg (seg_type))
Florin Corasb384b542018-01-15 01:08:33 -0800303 return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
Dave Barach68b0fb02017-02-28 15:15:56 -0500304
Florin Coras15531972018-08-12 23:50:53 -0700305 /* Check that the obvious things are properly set up */
306 application_verify_cb_fns (a->session_cb_vft);
307
Florin Coras15531972018-08-12 23:50:53 -0700308 app->flags = options[APP_OPTIONS_FLAGS];
309 app->cb_fns = *a->session_cb_vft;
310 app->ns_index = options[APP_OPTIONS_NAMESPACE];
311 app->proxied_transports = options[APP_OPTIONS_PROXY_TRANSPORT];
312 app->name = vec_dup (a->name);
313
314 /* If no scope enabled, default to global */
315 if (!application_has_global_scope (app)
316 && !application_has_local_scope (app))
317 app->flags |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
318
Florin Corasa332c462018-01-31 06:52:17 -0800319 props = application_segment_manager_properties (app);
320 segment_manager_properties_init (props);
Florin Coras15531972018-08-12 23:50:53 -0700321 props->segment_size = options[APP_OPTIONS_ADD_SEGMENT_SIZE];
322 props->prealloc_fifos = options[APP_OPTIONS_PREALLOC_FIFO_PAIRS];
Florin Corasb384b542018-01-15 01:08:33 -0800323 if (options[APP_OPTIONS_ADD_SEGMENT_SIZE])
324 {
325 props->add_segment_size = options[APP_OPTIONS_ADD_SEGMENT_SIZE];
326 props->add_segment = 1;
327 }
328 if (options[APP_OPTIONS_RX_FIFO_SIZE])
329 props->rx_fifo_size = options[APP_OPTIONS_RX_FIFO_SIZE];
330 if (options[APP_OPTIONS_TX_FIFO_SIZE])
331 props->tx_fifo_size = options[APP_OPTIONS_TX_FIFO_SIZE];
Florin Corasf8f516a2018-02-08 15:10:09 -0800332 if (options[APP_OPTIONS_EVT_QUEUE_SIZE])
333 props->evt_q_size = options[APP_OPTIONS_EVT_QUEUE_SIZE];
Florin Coras99368312018-08-02 10:45:44 -0700334 if (options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
335 props->use_mq_eventfd = 1;
Florin Coras58d36f02018-03-09 13:05:53 -0800336 if (options[APP_OPTIONS_TLS_ENGINE])
337 app->tls_engine = options[APP_OPTIONS_TLS_ENGINE];
Florin Corasa332c462018-01-31 06:52:17 -0800338 props->segment_type = seg_type;
Dave Barach68b0fb02017-02-28 15:15:56 -0500339
Florin Coras15531972018-08-12 23:50:53 -0700340 /* Add app to lookup by api_client_index table */
Florin Corasc1f5a432018-11-20 11:31:26 -0800341 if (!application_is_builtin (app))
342 application_api_table_add (app->app_index, a->api_client_index);
343 else
344 application_name_table_add (app);
345
346 a->app_index = app->app_index;
Florin Corasa332c462018-01-31 06:52:17 -0800347
Florin Coras15531972018-08-12 23:50:53 -0700348 APP_DBG ("New app name: %v api index: %u index %u", app->name,
349 app->api_client_index, app->app_index);
350
351 return 0;
352}
353
354void
355application_free (application_t * app)
356{
357 app_worker_map_t *wrk_map;
358 app_worker_t *app_wrk;
Florin Corasab2f6db2018-08-31 14:31:41 -0700359 u32 table_index;
360 local_session_t *ll;
361 session_endpoint_t sep;
Florin Coras15531972018-08-12 23:50:53 -0700362
363 /*
364 * The app event queue allocated in first segment is cleared with
365 * the segment manager. No need to explicitly free it.
366 */
367 APP_DBG ("Delete app name %v api index: %d index: %d", app->name,
368 app->api_client_index, app->app_index);
369
370 if (application_is_proxy (app))
371 application_remove_proxy (app);
372
Florin Corasab2f6db2018-08-31 14:31:41 -0700373 /*
374 * Free workers
375 */
376
Florin Coras15531972018-08-12 23:50:53 -0700377 /* *INDENT-OFF* */
378 pool_flush (wrk_map, app->worker_maps, ({
379 app_wrk = app_worker_get (wrk_map->wrk_index);
380 app_worker_free (app_wrk);
381 }));
382 /* *INDENT-ON* */
383 pool_free (app->worker_maps);
384
Florin Corasab2f6db2018-08-31 14:31:41 -0700385 /*
386 * Free local listeners. Global table unbinds stop local listeners
387 * as well, but if we have only local binds, these won't be cleaned up.
388 * Don't bother with local accepted sessions, we clean them when
389 * cleaning up the worker.
390 */
391 table_index = application_local_session_table (app);
392 /* *INDENT-OFF* */
393 pool_foreach (ll, app->local_listen_sessions, ({
394 application_local_listener_session_endpoint (ll, &sep);
395 session_lookup_del_session_endpoint (table_index, &sep);
396 }));
397 /* *INDENT-ON* */
398 pool_free (app->local_listen_sessions);
399
400 /*
401 * Cleanup remaining state
402 */
Florin Corasc1f5a432018-11-20 11:31:26 -0800403 if (application_is_builtin (app))
404 application_name_table_del (app);
Florin Coras15531972018-08-12 23:50:53 -0700405 vec_free (app->name);
406 vec_free (app->tls_cert);
407 vec_free (app->tls_key);
408 pool_put (app_main.app_pool, app);
409}
410
Florin Coras053a0e42018-11-13 15:52:38 -0800411void
412application_detach_process (application_t * app, u32 api_client_index)
413{
414 vnet_app_worker_add_del_args_t _args = { 0 }, *args = &_args;
415 app_worker_map_t *wrk_map;
416 u32 *wrks = 0, *wrk_index;
417 app_worker_t *app_wrk;
418
419 if (api_client_index == ~0)
420 {
421 application_free (app);
422 return;
423 }
424
425 APP_DBG ("Detaching for app %v index %u api client index %u", app->name,
426 app->app_index, app->api_client_index);
427
428 /* *INDENT-OFF* */
429 pool_foreach (wrk_map, app->worker_maps, ({
430 app_wrk = app_worker_get (wrk_map->wrk_index);
Florin Corasc1f5a432018-11-20 11:31:26 -0800431 if (app_wrk->api_client_index == api_client_index)
Florin Coras053a0e42018-11-13 15:52:38 -0800432 vec_add1 (wrks, app_wrk->wrk_index);
433 }));
434 /* *INDENT-ON* */
435
436 if (!vec_len (wrks))
437 {
438 clib_warning ("no workers for app %u api_index %u", app->app_index,
439 api_client_index);
440 return;
441 }
442
443 args->app_index = app->app_index;
Florin Corasc1f5a432018-11-20 11:31:26 -0800444 args->api_client_index = api_client_index;
Florin Coras053a0e42018-11-13 15:52:38 -0800445 vec_foreach (wrk_index, wrks)
446 {
447 app_wrk = app_worker_get (wrk_index[0]);
Florin Coras349f8ca2018-11-20 16:52:49 -0800448 args->wrk_map_index = app_wrk->wrk_map_index;
Florin Coras053a0e42018-11-13 15:52:38 -0800449 args->is_add = 0;
450 vnet_app_worker_add_del (args);
451 }
452 vec_free (wrks);
453}
454
Florin Coras15531972018-08-12 23:50:53 -0700455app_worker_t *
456application_get_worker (application_t * app, u32 wrk_map_index)
457{
458 app_worker_map_t *map;
459 map = app_worker_map_get (app, wrk_map_index);
460 if (!map)
461 return 0;
462 return app_worker_get (map->wrk_index);
463}
464
465app_worker_t *
466application_get_default_worker (application_t * app)
467{
468 return application_get_worker (app, 0);
469}
470
Florin Coras053a0e42018-11-13 15:52:38 -0800471u32
472application_n_workers (application_t * app)
473{
474 return pool_elts (app->worker_maps);
475}
476
Florin Coras15531972018-08-12 23:50:53 -0700477app_worker_t *
Florin Corasab2f6db2018-08-31 14:31:41 -0700478application_listener_select_worker (stream_session_t * ls, u8 is_local)
479{
480 app_listener_t *app_listener;
481 application_t *app;
482 u32 wrk_index;
483
484 app = application_get (ls->app_index);
485 if (!is_local)
486 app_listener = app_listener_get (app, ls->listener_db_index);
487 else
488 app_listener = app_local_listener_get (app, ls->listener_db_index);
489
490 wrk_index = clib_bitmap_next_set (app_listener->workers,
491 app_listener->accept_rotor + 1);
492 if (wrk_index == ~0)
493 wrk_index = clib_bitmap_first_set (app_listener->workers);
494
495 ASSERT (wrk_index != ~0);
496 app_listener->accept_rotor = wrk_index;
497 return application_get_worker (app, wrk_index);
498}
499
500app_worker_t *
Florin Coras15531972018-08-12 23:50:53 -0700501app_worker_alloc (application_t * app)
502{
503 app_worker_t *app_wrk;
504 pool_get (app_main.workers, app_wrk);
Dave Barachb7b92992018-10-17 10:38:51 -0400505 clib_memset (app_wrk, 0, sizeof (*app_wrk));
Florin Coras15531972018-08-12 23:50:53 -0700506 app_wrk->wrk_index = app_wrk - app_main.workers;
507 app_wrk->app_index = app->app_index;
508 app_wrk->wrk_map_index = ~0;
509 app_wrk->connects_seg_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
510 app_wrk->first_segment_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
511 app_wrk->local_segment_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
512 APP_DBG ("New app %v worker %u", app_get_name (app), app_wrk->wrk_index);
513 return app_wrk;
514}
515
516app_worker_t *
517app_worker_get (u32 wrk_index)
518{
519 return pool_elt_at_index (app_main.workers, wrk_index);
520}
521
522app_worker_t *
523app_worker_get_if_valid (u32 wrk_index)
524{
525 if (pool_is_free_index (app_main.workers, wrk_index))
526 return 0;
527 return pool_elt_at_index (app_main.workers, wrk_index);
528}
529
530void
531app_worker_free (app_worker_t * app_wrk)
532{
533 application_t *app = application_get (app_wrk->app_index);
534 vnet_unbind_args_t _a, *a = &_a;
535 u64 handle, *handles = 0;
536 segment_manager_t *sm;
537 u32 sm_index;
538 int i;
539
540 /*
541 * Listener cleanup
542 */
543
544 /* *INDENT-OFF* */
545 hash_foreach (handle, sm_index, app_wrk->listeners_table,
546 ({
547 vec_add1 (handles, handle);
548 sm = segment_manager_get (sm_index);
549 sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
550 }));
551 /* *INDENT-ON* */
552
553 for (i = 0; i < vec_len (handles); i++)
554 {
555 a->app_index = app->app_index;
Florin Corasab2f6db2018-08-31 14:31:41 -0700556 a->wrk_map_index = app_wrk->wrk_map_index;
Florin Coras15531972018-08-12 23:50:53 -0700557 a->handle = handles[i];
558 /* seg manager is removed when unbind completes */
559 vnet_unbind (a);
560 }
561
562 /*
563 * Connects segment manager cleanup
564 */
565
566 if (app_wrk->connects_seg_manager != APP_INVALID_SEGMENT_MANAGER_INDEX)
567 {
568 sm = segment_manager_get (app_wrk->connects_seg_manager);
569 sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
570 segment_manager_init_del (sm);
571 }
572
573 /* If first segment manager is used by a listener */
574 if (app_wrk->first_segment_manager != APP_INVALID_SEGMENT_MANAGER_INDEX
575 && app_wrk->first_segment_manager != app_wrk->connects_seg_manager)
576 {
577 sm = segment_manager_get (app_wrk->first_segment_manager);
Florin Coras400ded32018-10-03 01:00:57 -0700578 sm->first_is_protected = 0;
579 sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
Florin Coras15531972018-08-12 23:50:53 -0700580 /* .. and has no fifos, e.g. it might be used for redirected sessions,
581 * remove it */
582 if (!segment_manager_has_fifos (sm))
Florin Coras400ded32018-10-03 01:00:57 -0700583 segment_manager_del (sm);
Florin Coras15531972018-08-12 23:50:53 -0700584 }
585
586 /*
587 * Local sessions
588 */
Florin Corasab2f6db2018-08-31 14:31:41 -0700589 app_worker_local_sessions_free (app_wrk);
Florin Coras15531972018-08-12 23:50:53 -0700590
591 pool_put (app_main.workers, app_wrk);
592 if (CLIB_DEBUG)
Dave Barachb7b92992018-10-17 10:38:51 -0400593 clib_memset (app_wrk, 0xfe, sizeof (*app_wrk));
Florin Coras15531972018-08-12 23:50:53 -0700594}
595
596int
597app_worker_alloc_and_init (application_t * app, app_worker_t ** wrk)
598{
599 app_worker_map_t *wrk_map;
600 app_worker_t *app_wrk;
601 segment_manager_t *sm;
602 int rv;
603
604 app_wrk = app_worker_alloc (app);
605 wrk_map = app_worker_map_alloc (app);
606 wrk_map->wrk_index = app_wrk->wrk_index;
607 app_wrk->wrk_map_index = app_worker_map_index (app, wrk_map);
608
609 /*
610 * Setup first segment manager
611 */
612 sm = segment_manager_new ();
613 sm->app_wrk_index = app_wrk->wrk_index;
614
615 if ((rv = segment_manager_init (sm, app->sm_properties.segment_size,
616 app->sm_properties.prealloc_fifos)))
617 {
618 app_worker_free (app_wrk);
619 return rv;
620 }
Florin Corasc87c91d2017-08-16 19:55:49 -0700621 sm->first_is_protected = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -0500622
Florin Corascea194d2017-10-02 00:18:51 -0700623 /*
Florin Coras15531972018-08-12 23:50:53 -0700624 * Setup app worker
Florin Corascea194d2017-10-02 00:18:51 -0700625 */
Florin Coras15531972018-08-12 23:50:53 -0700626 app_wrk->first_segment_manager = segment_manager_index (sm);
627 app_wrk->listeners_table = hash_create (0, sizeof (u64));
628 app_wrk->event_queue = segment_manager_event_queue (sm);
629 app_wrk->app_is_builtin = application_is_builtin (app);
Dave Barach68b0fb02017-02-28 15:15:56 -0500630
Florin Corasf8f516a2018-02-08 15:10:09 -0800631 /*
632 * Segment manager for local sessions
633 */
634 sm = segment_manager_new ();
Florin Coras15531972018-08-12 23:50:53 -0700635 sm->app_wrk_index = app_wrk->wrk_index;
636 app_wrk->local_segment_manager = segment_manager_index (sm);
637 app_wrk->local_connects = hash_create (0, sizeof (u64));
638
639 *wrk = app_wrk;
Florin Corasf8f516a2018-02-08 15:10:09 -0800640
Florin Coras6cf30ad2017-04-04 23:08:23 -0700641 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500642}
643
Florin Corasab2f6db2018-08-31 14:31:41 -0700644application_t *
645app_worker_get_app (u32 wrk_index)
646{
647 app_worker_t *app_wrk;
648 app_wrk = app_worker_get_if_valid (wrk_index);
649 if (!app_wrk)
650 return 0;
651 return application_get_if_valid (app_wrk->app_index);
652}
653
Florin Coras6cf30ad2017-04-04 23:08:23 -0700654static segment_manager_t *
Florin Corasab2f6db2018-08-31 14:31:41 -0700655app_worker_alloc_segment_manager (app_worker_t * app_wrk)
Dave Barach68b0fb02017-02-28 15:15:56 -0500656{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700657 segment_manager_t *sm = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500658
Florin Corasc87c91d2017-08-16 19:55:49 -0700659 /* If the first segment manager is not in use, don't allocate a new one */
Florin Coras15531972018-08-12 23:50:53 -0700660 if (app_wrk->first_segment_manager != APP_INVALID_SEGMENT_MANAGER_INDEX
661 && app_wrk->first_segment_manager_in_use == 0)
Dave Barach68b0fb02017-02-28 15:15:56 -0500662 {
Florin Coras15531972018-08-12 23:50:53 -0700663 sm = segment_manager_get (app_wrk->first_segment_manager);
664 app_wrk->first_segment_manager_in_use = 1;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700665 return sm;
Dave Barach68b0fb02017-02-28 15:15:56 -0500666 }
667
Florin Coras6cf30ad2017-04-04 23:08:23 -0700668 sm = segment_manager_new ();
Florin Coras15531972018-08-12 23:50:53 -0700669 sm->app_wrk_index = app_wrk->wrk_index;
Florin Coras0e9c33b2017-08-14 22:33:41 -0700670
Florin Coras6cf30ad2017-04-04 23:08:23 -0700671 return sm;
672}
673
Florin Coras6cf30ad2017-04-04 23:08:23 -0700674int
Florin Corasab2f6db2018-08-31 14:31:41 -0700675app_worker_start_listen (app_worker_t * app_wrk, stream_session_t * ls)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700676{
677 segment_manager_t *sm;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700678
Florin Coras6cf30ad2017-04-04 23:08:23 -0700679 /* Allocate segment manager. All sessions derived out of a listen session
680 * have fifos allocated by the same segment manager. */
Florin Corasab2f6db2018-08-31 14:31:41 -0700681 if (!(sm = app_worker_alloc_segment_manager (app_wrk)))
682 return -1;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700683
684 /* Add to app's listener table. Useful to find all child listeners
685 * when app goes down, although, just for unbinding this is not needed */
Florin Corasab2f6db2018-08-31 14:31:41 -0700686 hash_set (app_wrk->listeners_table, listen_session_get_handle (ls),
687 segment_manager_index (sm));
Florin Coras6cf30ad2017-04-04 23:08:23 -0700688
Florin Corasab2f6db2018-08-31 14:31:41 -0700689 if (!ls->server_rx_fifo
690 && session_transport_service_type (ls) == TRANSPORT_SERVICE_CL)
Florin Coras7fb0fe12018-04-09 09:24:52 -0700691 {
Florin Corasab2f6db2018-08-31 14:31:41 -0700692 if (session_alloc_fifos (sm, ls))
693 return -1;
Florin Coras7fb0fe12018-04-09 09:24:52 -0700694 }
Florin Coras6cf30ad2017-04-04 23:08:23 -0700695 return 0;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700696}
697
Florin Coras6cf30ad2017-04-04 23:08:23 -0700698int
Florin Corasab2f6db2018-08-31 14:31:41 -0700699app_worker_stop_listen (app_worker_t * app_wrk, session_handle_t handle)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700700{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700701 segment_manager_t *sm;
Florin Corasab2f6db2018-08-31 14:31:41 -0700702 uword *sm_indexp;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700703
Florin Corasab2f6db2018-08-31 14:31:41 -0700704 sm_indexp = hash_get (app_wrk->listeners_table, handle);
705 if (PREDICT_FALSE (!sm_indexp))
Florin Coras15531972018-08-12 23:50:53 -0700706 {
707 clib_warning ("listener handle was removed %llu!", handle);
708 return -1;
709 }
Florin Coras6cf30ad2017-04-04 23:08:23 -0700710
Florin Corasab2f6db2018-08-31 14:31:41 -0700711 sm = segment_manager_get (*sm_indexp);
712 if (app_wrk->first_segment_manager == *sm_indexp)
Florin Coras0e9c33b2017-08-14 22:33:41 -0700713 {
Florin Corasc87c91d2017-08-16 19:55:49 -0700714 /* Delete sessions but don't remove segment manager */
Florin Coras15531972018-08-12 23:50:53 -0700715 app_wrk->first_segment_manager_in_use = 0;
Florin Corasc87c91d2017-08-16 19:55:49 -0700716 segment_manager_del_sessions (sm);
717 }
718 else
719 {
720 segment_manager_init_del (sm);
Florin Coras0e9c33b2017-08-14 22:33:41 -0700721 }
Florin Coras15531972018-08-12 23:50:53 -0700722 hash_unset (app_wrk->listeners_table, handle);
Florin Corasab2f6db2018-08-31 14:31:41 -0700723
724 return 0;
725}
726
727/**
728 * Start listening local transport endpoint for requested transport.
729 *
730 * Creates a 'dummy' stream session with state LISTENING to be used in session
731 * lookups, prior to establishing connection. Requests transport to build
732 * it's own specific listening connection.
733 */
734int
735application_start_listen (application_t * app,
Florin Coras5665ced2018-10-25 18:03:45 -0700736 session_endpoint_cfg_t * sep_ext,
Florin Corasab2f6db2018-08-31 14:31:41 -0700737 session_handle_t * res)
738{
739 app_listener_t *app_listener;
740 u32 table_index, fib_proto;
741 session_endpoint_t *sep;
742 app_worker_t *app_wrk;
743 stream_session_t *ls;
744 session_handle_t lh;
745 session_type_t sst;
746
747 /*
748 * Check if sep is already listened on
749 */
750 sep = (session_endpoint_t *) sep_ext;
751 fib_proto = session_endpoint_fib_proto (sep);
752 table_index = application_session_table (app, fib_proto);
753 lh = session_lookup_endpoint_listener (table_index, sep, 1);
754 if (lh != SESSION_INVALID_HANDLE)
755 {
756 ls = listen_session_get_from_handle (lh);
757 if (ls->app_index != app->app_index)
758 return VNET_API_ERROR_ADDRESS_IN_USE;
759
760 app_wrk = app_worker_get (sep_ext->app_wrk_index);
761 if (ls->app_wrk_index == app_wrk->wrk_index)
762 return VNET_API_ERROR_ADDRESS_IN_USE;
763
764 if (app_worker_start_listen (app_wrk, ls))
765 return -1;
766
767 app_listener = app_listener_get (app, ls->listener_db_index);
768 app_listener->workers = clib_bitmap_set (app_listener->workers,
769 app_wrk->wrk_map_index, 1);
770
771 *res = listen_session_get_handle (ls);
772 return 0;
773 }
774
775 /*
776 * Allocate new listener for application
777 */
778 sst = session_type_from_proto_and_ip (sep_ext->transport_proto,
779 sep_ext->is_ip4);
780 ls = listen_session_new (0, sst);
781 ls->app_index = app->app_index;
Florin Coras74cac882018-09-07 09:13:15 -0700782 lh = listen_session_get_handle (ls);
Florin Corasab2f6db2018-08-31 14:31:41 -0700783 if (session_listen (ls, sep_ext))
784 goto err;
785
Florin Coras74cac882018-09-07 09:13:15 -0700786
787 ls = listen_session_get_from_handle (lh);
Florin Corasab2f6db2018-08-31 14:31:41 -0700788 app_listener = app_listener_alloc (app);
789 ls->listener_db_index = app_listener->al_index;
790
791 /*
792 * Setup app worker as a listener
793 */
794 app_wrk = app_worker_get (sep_ext->app_wrk_index);
795 ls->app_wrk_index = app_wrk->wrk_index;
796 if (app_worker_start_listen (app_wrk, ls))
797 goto err;
798 app_listener->workers = clib_bitmap_set (app_listener->workers,
799 app_wrk->wrk_map_index, 1);
800
Florin Coras74cac882018-09-07 09:13:15 -0700801 *res = lh;
Florin Corasab2f6db2018-08-31 14:31:41 -0700802 return 0;
803
804err:
805 listen_session_del (ls);
806 return -1;
807}
808
809/**
810 * Stop listening on session associated to handle
811 *
812 * @param handle listener handle
813 * @param app_index index of the app owning the handle.
814 * @param app_wrk_index index of the worker requesting the stop
815 */
816int
817application_stop_listen (u32 app_index, u32 app_wrk_index,
818 session_handle_t handle)
819{
820 app_listener_t *app_listener;
821 stream_session_t *listener;
822 app_worker_t *app_wrk;
823 application_t *app;
824
825 listener = listen_session_get_from_handle (handle);
826 app = application_get (app_index);
827 if (PREDICT_FALSE (!app || app->app_index != listener->app_index))
828 {
829 clib_warning ("app doesn't own handle %llu!", handle);
830 return -1;
831 }
832
833 app_listener = app_listener_get (app, listener->listener_db_index);
834 if (!clib_bitmap_get (app_listener->workers, app_wrk_index))
835 {
Florin Coras053a0e42018-11-13 15:52:38 -0800836 clib_warning ("worker %u not listening on handle %lu", app_wrk_index,
837 handle);
Florin Corasab2f6db2018-08-31 14:31:41 -0700838 return 0;
839 }
840
841 app_wrk = application_get_worker (app, app_wrk_index);
842 app_worker_stop_listen (app_wrk, handle);
843 clib_bitmap_set_no_check (app_listener->workers, app_wrk_index, 0);
844
845 if (clib_bitmap_is_zero (app_listener->workers))
846 {
847 session_stop_listen (listener);
848 app_listener_free (app, app_listener);
849 listen_session_del (listener);
850 }
Florin Coras6cf30ad2017-04-04 23:08:23 -0700851
Dave Barach68b0fb02017-02-28 15:15:56 -0500852 return 0;
853}
854
Florin Coras6cf30ad2017-04-04 23:08:23 -0700855int
Florin Coras15531972018-08-12 23:50:53 -0700856app_worker_open_session (app_worker_t * app, session_endpoint_t * sep,
857 u32 api_context)
Dave Barach68b0fb02017-02-28 15:15:56 -0500858{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700859 int rv;
860
861 /* Make sure we have a segment manager for connects */
Florin Coras15531972018-08-12 23:50:53 -0700862 app_worker_alloc_connects_segment_manager (app);
Florin Coras371ca502018-02-21 12:07:41 -0800863
Florin Coras15531972018-08-12 23:50:53 -0700864 if ((rv = session_open (app->wrk_index, sep, api_context)))
Florin Coras371ca502018-02-21 12:07:41 -0800865 return rv;
866
867 return 0;
868}
869
870int
Florin Coras15531972018-08-12 23:50:53 -0700871app_worker_alloc_connects_segment_manager (app_worker_t * app_wrk)
Florin Coras371ca502018-02-21 12:07:41 -0800872{
873 segment_manager_t *sm;
874
Florin Coras15531972018-08-12 23:50:53 -0700875 if (app_wrk->connects_seg_manager == APP_INVALID_SEGMENT_MANAGER_INDEX)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700876 {
Florin Corasab2f6db2018-08-31 14:31:41 -0700877 sm = app_worker_alloc_segment_manager (app_wrk);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700878 if (sm == 0)
879 return -1;
Florin Coras15531972018-08-12 23:50:53 -0700880 app_wrk->connects_seg_manager = segment_manager_index (sm);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700881 }
Florin Coras6cf30ad2017-04-04 23:08:23 -0700882 return 0;
883}
884
885segment_manager_t *
Florin Coras15531972018-08-12 23:50:53 -0700886app_worker_get_connect_segment_manager (app_worker_t * app)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700887{
888 ASSERT (app->connects_seg_manager != (u32) ~ 0);
889 return segment_manager_get (app->connects_seg_manager);
890}
891
892segment_manager_t *
Florin Coras15531972018-08-12 23:50:53 -0700893app_worker_get_listen_segment_manager (app_worker_t * app,
Florin Corasa44d6b12018-10-03 14:29:10 -0700894 stream_session_t * listener)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700895{
896 uword *smp;
Florin Corasa44d6b12018-10-03 14:29:10 -0700897 smp = hash_get (app->listeners_table, listen_session_get_handle (listener));
Florin Coras6cf30ad2017-04-04 23:08:23 -0700898 ASSERT (smp != 0);
899 return segment_manager_get (*smp);
900}
901
Florin Coras15531972018-08-12 23:50:53 -0700902clib_error_t *
903vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a)
904{
905 svm_fifo_segment_private_t *fs;
906 app_worker_map_t *wrk_map;
907 app_worker_t *app_wrk;
908 segment_manager_t *sm;
909 application_t *app;
910 int rv;
911
912 app = application_get (a->app_index);
913 if (!app)
914 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
915 "App %u does not exist", a->app_index);
916
917 if (a->is_add)
918 {
919 if ((rv = app_worker_alloc_and_init (app, &app_wrk)))
920 return clib_error_return_code (0, rv, 0, "app wrk init: %d", rv);
Florin Coras053a0e42018-11-13 15:52:38 -0800921
922 /* Map worker api index to the app */
Florin Corasc1f5a432018-11-20 11:31:26 -0800923 app_wrk->api_client_index = a->api_client_index;
924 application_api_table_add (app->app_index, a->api_client_index);
Florin Coras053a0e42018-11-13 15:52:38 -0800925
Florin Coras15531972018-08-12 23:50:53 -0700926 sm = segment_manager_get (app_wrk->first_segment_manager);
927 fs = segment_manager_get_segment_w_lock (sm, 0);
928 a->segment = &fs->ssvm;
Florin Corasfa76a762018-11-29 12:40:10 -0800929 a->segment_handle = segment_manager_segment_handle (sm, fs);
Florin Coras15531972018-08-12 23:50:53 -0700930 segment_manager_segment_reader_unlock (sm);
931 a->evt_q = app_wrk->event_queue;
Florin Coras349f8ca2018-11-20 16:52:49 -0800932 a->wrk_map_index = app_wrk->wrk_map_index;
Florin Coras15531972018-08-12 23:50:53 -0700933 }
934 else
935 {
Florin Coras349f8ca2018-11-20 16:52:49 -0800936 wrk_map = app_worker_map_get (app, a->wrk_map_index);
Florin Coras15531972018-08-12 23:50:53 -0700937 if (!wrk_map)
938 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
939 "App %u does not have worker %u",
Florin Coras349f8ca2018-11-20 16:52:49 -0800940 app->app_index, a->wrk_map_index);
Florin Coras15531972018-08-12 23:50:53 -0700941 app_wrk = app_worker_get (wrk_map->wrk_index);
Florin Coras15531972018-08-12 23:50:53 -0700942 if (!app_wrk)
943 return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
Florin Coras349f8ca2018-11-20 16:52:49 -0800944 "No worker %u", a->wrk_map_index);
Florin Corasc1f5a432018-11-20 11:31:26 -0800945 application_api_table_del (app_wrk->api_client_index);
Florin Coras15531972018-08-12 23:50:53 -0700946 app_worker_free (app_wrk);
Florin Coras053a0e42018-11-13 15:52:38 -0800947 app_worker_map_free (app, wrk_map);
948 if (application_n_workers (app) == 0)
949 application_free (app);
Florin Coras15531972018-08-12 23:50:53 -0700950 }
951 return 0;
952}
953
Florin Corasf8f516a2018-02-08 15:10:09 -0800954segment_manager_t *
Florin Coras15531972018-08-12 23:50:53 -0700955application_get_local_segment_manager (app_worker_t * app)
Florin Corasf8f516a2018-02-08 15:10:09 -0800956{
957 return segment_manager_get (app->local_segment_manager);
958}
959
960segment_manager_t *
Florin Coras15531972018-08-12 23:50:53 -0700961application_get_local_segment_manager_w_session (app_worker_t * app,
Florin Corasf8f516a2018-02-08 15:10:09 -0800962 local_session_t * ls)
963{
964 stream_session_t *listener;
965 if (application_local_session_listener_has_transport (ls))
966 {
Florin Coras5c9083d2018-04-13 06:39:07 -0700967 listener = listen_session_get (ls->listener_index);
Florin Coras15531972018-08-12 23:50:53 -0700968 return app_worker_get_listen_segment_manager (app, listener);
Florin Corasf8f516a2018-02-08 15:10:09 -0800969 }
970 return segment_manager_get (app->local_segment_manager);
971}
972
Dave Barach52851e62017-08-07 09:35:25 -0400973int
974application_is_proxy (application_t * app)
975{
Florin Coras7999e832017-10-31 01:51:04 -0700976 return (app->flags & APP_OPTIONS_FLAGS_IS_PROXY);
977}
978
979int
980application_is_builtin (application_t * app)
981{
982 return (app->flags & APP_OPTIONS_FLAGS_IS_BUILTIN);
983}
984
985int
986application_is_builtin_proxy (application_t * app)
987{
988 return (application_is_proxy (app) && application_is_builtin (app));
Dave Barach52851e62017-08-07 09:35:25 -0400989}
990
Florin Corascea194d2017-10-02 00:18:51 -0700991u8
992application_has_local_scope (application_t * app)
993{
994 return app->flags & APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
995}
996
997u8
998application_has_global_scope (application_t * app)
999{
1000 return app->flags & APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1001}
1002
Florin Coras60116992018-08-27 09:52:18 -07001003u8
1004application_use_mq_for_ctrl (application_t * app)
1005{
1006 return app->flags & APP_OPTIONS_FLAGS_USE_MQ_FOR_CTRL_MSGS;
1007}
1008
Florin Coras15531972018-08-12 23:50:53 -07001009/**
1010 * Send an API message to the external app, to map new segment
1011 */
1012int
Florin Corasfa76a762018-11-29 12:40:10 -08001013app_worker_add_segment_notify (u32 app_wrk_index, u64 segment_handle)
Florin Coras15531972018-08-12 23:50:53 -07001014{
1015 app_worker_t *app_wrk = app_worker_get (app_wrk_index);
1016 application_t *app = application_get (app_wrk->app_index);
Florin Corasfa76a762018-11-29 12:40:10 -08001017 return app->cb_fns.add_segment_callback (app_wrk->api_client_index,
1018 segment_handle);
Florin Coras15531972018-08-12 23:50:53 -07001019}
1020
Florin Coras1c710452017-10-17 00:03:13 -07001021u32
Florin Coras15531972018-08-12 23:50:53 -07001022application_n_listeners (app_worker_t * app)
Florin Coras1c710452017-10-17 00:03:13 -07001023{
1024 return hash_elts (app->listeners_table);
1025}
1026
1027stream_session_t *
Florin Coras15531972018-08-12 23:50:53 -07001028app_worker_first_listener (app_worker_t * app, u8 fib_proto,
1029 u8 transport_proto)
Florin Coras1c710452017-10-17 00:03:13 -07001030{
Florin Coras7999e832017-10-31 01:51:04 -07001031 stream_session_t *listener;
Florin Coras1c710452017-10-17 00:03:13 -07001032 u64 handle;
1033 u32 sm_index;
Florin Coras7999e832017-10-31 01:51:04 -07001034 u8 sst;
1035
1036 sst = session_type_from_proto_and_ip (transport_proto,
1037 fib_proto == FIB_PROTOCOL_IP4);
Florin Coras1c710452017-10-17 00:03:13 -07001038
1039 /* *INDENT-OFF* */
1040 hash_foreach (handle, sm_index, app->listeners_table, ({
Florin Coras7999e832017-10-31 01:51:04 -07001041 listener = listen_session_get_from_handle (handle);
Florin Corasc3ddea82017-11-27 03:12:00 -08001042 if (listener->session_type == sst
Florin Corasab2f6db2018-08-31 14:31:41 -07001043 && listener->enqueue_epoch != SESSION_PROXY_LISTENER_INDEX)
Florin Coras7999e832017-10-31 01:51:04 -07001044 return listener;
Florin Coras1c710452017-10-17 00:03:13 -07001045 }));
1046 /* *INDENT-ON* */
1047
1048 return 0;
1049}
1050
Florin Coras15531972018-08-12 23:50:53 -07001051u8
1052app_worker_application_is_builtin (app_worker_t * app_wrk)
1053{
1054 return app_wrk->app_is_builtin;
1055}
1056
Florin Coras19b1f6a2017-12-11 03:37:03 -08001057stream_session_t *
Florin Coras15531972018-08-12 23:50:53 -07001058application_proxy_listener (app_worker_t * app, u8 fib_proto,
Florin Coras19b1f6a2017-12-11 03:37:03 -08001059 u8 transport_proto)
1060{
1061 stream_session_t *listener;
1062 u64 handle;
1063 u32 sm_index;
1064 u8 sst;
1065
1066 sst = session_type_from_proto_and_ip (transport_proto,
1067 fib_proto == FIB_PROTOCOL_IP4);
1068
1069 /* *INDENT-OFF* */
1070 hash_foreach (handle, sm_index, app->listeners_table, ({
1071 listener = listen_session_get_from_handle (handle);
1072 if (listener->session_type == sst
Florin Corasab2f6db2018-08-31 14:31:41 -07001073 && listener->enqueue_epoch == SESSION_PROXY_LISTENER_INDEX)
Florin Coras19b1f6a2017-12-11 03:37:03 -08001074 return listener;
1075 }));
1076 /* *INDENT-ON* */
1077
1078 return 0;
1079}
1080
Florin Coras7999e832017-10-31 01:51:04 -07001081static clib_error_t *
1082application_start_stop_proxy_fib_proto (application_t * app, u8 fib_proto,
1083 u8 transport_proto, u8 is_start)
1084{
Florin Coras7999e832017-10-31 01:51:04 -07001085 app_namespace_t *app_ns = app_namespace_get (app->ns_index);
1086 u8 is_ip4 = (fib_proto == FIB_PROTOCOL_IP4);
Florin Coras5665ced2018-10-25 18:03:45 -07001087 session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
Florin Coras7999e832017-10-31 01:51:04 -07001088 transport_connection_t *tc;
Florin Coras15531972018-08-12 23:50:53 -07001089 app_worker_t *app_wrk;
Florin Coras7999e832017-10-31 01:51:04 -07001090 stream_session_t *s;
1091 u64 handle;
1092
Florin Coras15531972018-08-12 23:50:53 -07001093 /* TODO decide if we want proxy to be enabled for all workers */
1094 app_wrk = application_get_default_worker (app);
Florin Coras7999e832017-10-31 01:51:04 -07001095 if (is_start)
1096 {
Florin Coras15531972018-08-12 23:50:53 -07001097 s = app_worker_first_listener (app_wrk, fib_proto, transport_proto);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001098 if (!s)
1099 {
1100 sep.is_ip4 = is_ip4;
1101 sep.fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1102 sep.sw_if_index = app_ns->sw_if_index;
1103 sep.transport_proto = transport_proto;
Florin Corasab2f6db2018-08-31 14:31:41 -07001104 sep.app_wrk_index = app_wrk->wrk_index; /* only default */
1105 application_start_listen (app, &sep, &handle);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001106 s = listen_session_get_from_handle (handle);
Florin Corasab2f6db2018-08-31 14:31:41 -07001107 s->enqueue_epoch = SESSION_PROXY_LISTENER_INDEX;
Florin Coras19b1f6a2017-12-11 03:37:03 -08001108 }
Florin Coras7999e832017-10-31 01:51:04 -07001109 }
1110 else
1111 {
Florin Coras15531972018-08-12 23:50:53 -07001112 s = application_proxy_listener (app_wrk, fib_proto, transport_proto);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001113 ASSERT (s);
Florin Coras7999e832017-10-31 01:51:04 -07001114 }
Florin Coras19b1f6a2017-12-11 03:37:03 -08001115
Florin Coras7999e832017-10-31 01:51:04 -07001116 tc = listen_session_get_transport (s);
1117
1118 if (!ip_is_zero (&tc->lcl_ip, 1))
1119 {
Florin Corasdbd44562017-11-09 19:30:17 -08001120 u32 sti;
1121 sep.is_ip4 = is_ip4;
1122 sep.fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1123 sep.transport_proto = transport_proto;
1124 sep.port = 0;
1125 sti = session_lookup_get_index_for_fib (fib_proto, sep.fib_index);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001126 if (is_start)
Florin Corasab2f6db2018-08-31 14:31:41 -07001127 session_lookup_add_session_endpoint (sti,
1128 (session_endpoint_t *) & sep,
1129 s->session_index);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001130 else
Florin Corasab2f6db2018-08-31 14:31:41 -07001131 session_lookup_del_session_endpoint (sti,
1132 (session_endpoint_t *) & sep);
Florin Coras7999e832017-10-31 01:51:04 -07001133 }
Florin Coras19b1f6a2017-12-11 03:37:03 -08001134
Florin Coras7999e832017-10-31 01:51:04 -07001135 return 0;
1136}
1137
Florin Coras19b1f6a2017-12-11 03:37:03 -08001138static void
1139application_start_stop_proxy_local_scope (application_t * app,
1140 u8 transport_proto, u8 is_start)
1141{
1142 session_endpoint_t sep = SESSION_ENDPOINT_NULL;
1143 app_namespace_t *app_ns;
1144 app_ns = app_namespace_get (app->ns_index);
1145 sep.is_ip4 = 1;
1146 sep.transport_proto = transport_proto;
1147 sep.port = 0;
1148
1149 if (is_start)
1150 {
1151 session_lookup_add_session_endpoint (app_ns->local_table_index, &sep,
Florin Coras15531972018-08-12 23:50:53 -07001152 app->app_index);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001153 sep.is_ip4 = 0;
1154 session_lookup_add_session_endpoint (app_ns->local_table_index, &sep,
Florin Coras15531972018-08-12 23:50:53 -07001155 app->app_index);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001156 }
1157 else
1158 {
1159 session_lookup_del_session_endpoint (app_ns->local_table_index, &sep);
1160 sep.is_ip4 = 0;
1161 session_lookup_del_session_endpoint (app_ns->local_table_index, &sep);
1162 }
1163}
1164
Florin Coras7999e832017-10-31 01:51:04 -07001165void
Florin Coras561af9b2017-12-09 10:19:43 -08001166application_start_stop_proxy (application_t * app,
1167 transport_proto_t transport_proto, u8 is_start)
Florin Coras7999e832017-10-31 01:51:04 -07001168{
Florin Coras7999e832017-10-31 01:51:04 -07001169 if (application_has_local_scope (app))
Florin Coras19b1f6a2017-12-11 03:37:03 -08001170 application_start_stop_proxy_local_scope (app, transport_proto, is_start);
Florin Coras7999e832017-10-31 01:51:04 -07001171
1172 if (application_has_global_scope (app))
1173 {
1174 application_start_stop_proxy_fib_proto (app, FIB_PROTOCOL_IP4,
1175 transport_proto, is_start);
1176 application_start_stop_proxy_fib_proto (app, FIB_PROTOCOL_IP6,
1177 transport_proto, is_start);
1178 }
1179}
1180
1181void
1182application_setup_proxy (application_t * app)
1183{
1184 u16 transports = app->proxied_transports;
Florin Coras561af9b2017-12-09 10:19:43 -08001185 transport_proto_t tp;
1186
Florin Coras7999e832017-10-31 01:51:04 -07001187 ASSERT (application_is_proxy (app));
Florin Coras561af9b2017-12-09 10:19:43 -08001188
1189 /* *INDENT-OFF* */
1190 transport_proto_foreach (tp, ({
1191 if (transports & (1 << tp))
1192 application_start_stop_proxy (app, tp, 1);
1193 }));
1194 /* *INDENT-ON* */
Florin Coras7999e832017-10-31 01:51:04 -07001195}
1196
1197void
1198application_remove_proxy (application_t * app)
1199{
1200 u16 transports = app->proxied_transports;
Florin Coras561af9b2017-12-09 10:19:43 -08001201 transport_proto_t tp;
1202
Florin Coras7999e832017-10-31 01:51:04 -07001203 ASSERT (application_is_proxy (app));
Florin Coras561af9b2017-12-09 10:19:43 -08001204
1205 /* *INDENT-OFF* */
1206 transport_proto_foreach (tp, ({
1207 if (transports & (1 << tp))
1208 application_start_stop_proxy (app, tp, 0);
1209 }));
1210 /* *INDENT-ON* */
Florin Coras7999e832017-10-31 01:51:04 -07001211}
1212
Florin Corasa332c462018-01-31 06:52:17 -08001213segment_manager_properties_t *
1214application_segment_manager_properties (application_t * app)
1215{
1216 return &app->sm_properties;
1217}
1218
1219segment_manager_properties_t *
1220application_get_segment_manager_properties (u32 app_index)
1221{
1222 application_t *app = application_get (app_index);
1223 return &app->sm_properties;
1224}
1225
Florin Coras3c2fed52018-07-04 04:15:05 -07001226static inline int
1227app_enqueue_evt (svm_msg_q_t * mq, svm_msg_q_msg_t * msg, u8 lock)
1228{
Florin Coras52207f12018-07-12 14:48:06 -07001229 if (PREDICT_FALSE (svm_msg_q_is_full (mq)))
Florin Coras3c2fed52018-07-04 04:15:05 -07001230 {
1231 clib_warning ("evt q full");
1232 svm_msg_q_free_msg (mq, msg);
1233 if (lock)
1234 svm_msg_q_unlock (mq);
1235 return -1;
1236 }
Florin Coras52207f12018-07-12 14:48:06 -07001237
1238 if (lock)
1239 {
1240 svm_msg_q_add_and_unlock (mq, msg);
1241 return 0;
1242 }
1243
1244 /* Even when not locking the ring, we must wait for queue mutex */
1245 if (svm_msg_q_add (mq, msg, SVM_Q_WAIT))
1246 {
1247 clib_warning ("msg q add returned");
1248 return -1;
1249 }
Florin Coras3c2fed52018-07-04 04:15:05 -07001250 return 0;
1251}
1252
1253static inline int
Florin Coras15531972018-08-12 23:50:53 -07001254app_send_io_evt_rx (app_worker_t * app_wrk, stream_session_t * s, u8 lock)
Florin Coras3c2fed52018-07-04 04:15:05 -07001255{
Florin Coras52207f12018-07-12 14:48:06 -07001256 session_event_t *evt;
Florin Coras3c2fed52018-07-04 04:15:05 -07001257 svm_msg_q_msg_t msg;
1258 svm_msg_q_t *mq;
1259
Florin Coras460dce62018-07-27 05:45:06 -07001260 if (PREDICT_FALSE (s->session_state != SESSION_STATE_READY
1261 && s->session_state != SESSION_STATE_LISTENING))
Florin Coras3c2fed52018-07-04 04:15:05 -07001262 {
1263 /* Session is closed so app will never clean up. Flush rx fifo */
Florin Coras84099552018-07-22 12:59:30 -07001264 if (s->session_state == SESSION_STATE_CLOSED)
1265 svm_fifo_dequeue_drop_all (s->server_rx_fifo);
Florin Coras3c2fed52018-07-04 04:15:05 -07001266 return 0;
1267 }
1268
Florin Coras15531972018-08-12 23:50:53 -07001269 if (app_worker_application_is_builtin (app_wrk))
1270 {
1271 application_t *app = application_get (app_wrk->app_index);
1272 return app->cb_fns.builtin_app_rx_callback (s);
1273 }
Florin Coras3c2fed52018-07-04 04:15:05 -07001274
Florin Coras54693d22018-07-17 10:46:29 -07001275 if (svm_fifo_has_event (s->server_rx_fifo)
1276 || svm_fifo_is_empty (s->server_rx_fifo))
Florin Coras3c2fed52018-07-04 04:15:05 -07001277 return 0;
1278
Florin Coras15531972018-08-12 23:50:53 -07001279 mq = app_wrk->event_queue;
Florin Coras3c2fed52018-07-04 04:15:05 -07001280 if (lock)
1281 svm_msg_q_lock (mq);
1282
1283 if (PREDICT_FALSE (svm_msg_q_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
1284 {
1285 clib_warning ("evt q rings full");
1286 if (lock)
1287 svm_msg_q_unlock (mq);
1288 return -1;
1289 }
1290
1291 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
1292 ASSERT (!svm_msg_q_msg_is_invalid (&msg));
1293
Florin Coras52207f12018-07-12 14:48:06 -07001294 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Coras3c2fed52018-07-04 04:15:05 -07001295 evt->fifo = s->server_rx_fifo;
1296 evt->event_type = FIFO_EVENT_APP_RX;
1297
Florin Coras41c9e042018-09-11 00:10:41 -07001298 (void) svm_fifo_set_event (s->server_rx_fifo);
1299
Florin Coras54693d22018-07-17 10:46:29 -07001300 if (app_enqueue_evt (mq, &msg, lock))
1301 return -1;
Florin Coras54693d22018-07-17 10:46:29 -07001302 return 0;
Florin Coras3c2fed52018-07-04 04:15:05 -07001303}
1304
1305static inline int
Florin Coras15531972018-08-12 23:50:53 -07001306app_send_io_evt_tx (app_worker_t * app_wrk, stream_session_t * s, u8 lock)
Florin Coras3c2fed52018-07-04 04:15:05 -07001307{
1308 svm_msg_q_t *mq;
Florin Coras52207f12018-07-12 14:48:06 -07001309 session_event_t *evt;
Florin Coras3c2fed52018-07-04 04:15:05 -07001310 svm_msg_q_msg_t msg;
1311
Florin Coras15531972018-08-12 23:50:53 -07001312 if (app_worker_application_is_builtin (app_wrk))
Florin Coras3c2fed52018-07-04 04:15:05 -07001313 return 0;
1314
Florin Coras15531972018-08-12 23:50:53 -07001315 mq = app_wrk->event_queue;
Florin Coras3c2fed52018-07-04 04:15:05 -07001316 if (lock)
1317 svm_msg_q_lock (mq);
1318
1319 if (PREDICT_FALSE (svm_msg_q_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
1320 {
1321 clib_warning ("evt q rings full");
1322 if (lock)
1323 svm_msg_q_unlock (mq);
1324 return -1;
1325 }
1326
1327 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
1328 ASSERT (!svm_msg_q_msg_is_invalid (&msg));
1329
Florin Coras52207f12018-07-12 14:48:06 -07001330 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Coras3c2fed52018-07-04 04:15:05 -07001331 evt->event_type = FIFO_EVENT_APP_TX;
1332 evt->fifo = s->server_tx_fifo;
1333
1334 return app_enqueue_evt (mq, &msg, lock);
1335}
1336
1337/* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07001338typedef int (app_send_evt_handler_fn) (app_worker_t *app,
Florin Coras3c2fed52018-07-04 04:15:05 -07001339 stream_session_t *s,
1340 u8 lock);
Florin Coras460dce62018-07-27 05:45:06 -07001341static app_send_evt_handler_fn * const app_send_evt_handler_fns[3] = {
Florin Coras3c2fed52018-07-04 04:15:05 -07001342 app_send_io_evt_rx,
Florin Coras460dce62018-07-27 05:45:06 -07001343 0,
Florin Coras3c2fed52018-07-04 04:15:05 -07001344 app_send_io_evt_tx,
1345};
1346/* *INDENT-ON* */
1347
1348/**
1349 * Send event to application
1350 *
Florin Coras21795132018-09-09 09:40:51 -07001351 * Logic from queue perspective is non-blocking. If there's
1352 * not enough space to enqueue a message, we return.
Florin Coras3c2fed52018-07-04 04:15:05 -07001353 */
1354int
Florin Corasab2f6db2018-08-31 14:31:41 -07001355app_worker_send_event (app_worker_t * app, stream_session_t * s, u8 evt_type)
Florin Coras3c2fed52018-07-04 04:15:05 -07001356{
1357 ASSERT (app && evt_type <= FIFO_EVENT_APP_TX);
1358 return app_send_evt_handler_fns[evt_type] (app, s, 0 /* lock */ );
1359}
1360
Florin Coras21795132018-09-09 09:40:51 -07001361/**
1362 * Send event to application
1363 *
1364 * Logic from queue perspective is blocking. However, if queue is full,
1365 * we return.
1366 */
Florin Coras3c2fed52018-07-04 04:15:05 -07001367int
Florin Corasab2f6db2018-08-31 14:31:41 -07001368app_worker_lock_and_send_event (app_worker_t * app, stream_session_t * s,
1369 u8 evt_type)
Florin Coras3c2fed52018-07-04 04:15:05 -07001370{
1371 return app_send_evt_handler_fns[evt_type] (app, s, 1 /* lock */ );
1372}
1373
Florin Corasf8f516a2018-02-08 15:10:09 -08001374local_session_t *
Florin Corasab2f6db2018-08-31 14:31:41 -07001375application_local_session_alloc (app_worker_t * app_wrk)
Florin Corasf8f516a2018-02-08 15:10:09 -08001376{
1377 local_session_t *s;
Florin Corasab2f6db2018-08-31 14:31:41 -07001378 pool_get (app_wrk->local_sessions, s);
Dave Barachb7b92992018-10-17 10:38:51 -04001379 clib_memset (s, 0, sizeof (*s));
Florin Corasab2f6db2018-08-31 14:31:41 -07001380 s->app_wrk_index = app_wrk->wrk_index;
1381 s->session_index = s - app_wrk->local_sessions;
Florin Corasf8f516a2018-02-08 15:10:09 -08001382 s->session_type = session_type_from_proto_and_ip (TRANSPORT_PROTO_NONE, 0);
1383 return s;
1384}
1385
1386void
Florin Corasab2f6db2018-08-31 14:31:41 -07001387application_local_session_free (app_worker_t * app, local_session_t * s)
Florin Corasf8f516a2018-02-08 15:10:09 -08001388{
1389 pool_put (app->local_sessions, s);
1390 if (CLIB_DEBUG)
Dave Barachb7b92992018-10-17 10:38:51 -04001391 clib_memset (s, 0xfc, sizeof (*s));
Florin Corasf8f516a2018-02-08 15:10:09 -08001392}
1393
1394local_session_t *
Florin Coras15531972018-08-12 23:50:53 -07001395application_get_local_session (app_worker_t * app_wrk, u32 session_index)
Florin Corasf8f516a2018-02-08 15:10:09 -08001396{
Florin Coras15531972018-08-12 23:50:53 -07001397 if (pool_is_free_index (app_wrk->local_sessions, session_index))
Florin Coras99368312018-08-02 10:45:44 -07001398 return 0;
Florin Coras15531972018-08-12 23:50:53 -07001399 return pool_elt_at_index (app_wrk->local_sessions, session_index);
Florin Corasf8f516a2018-02-08 15:10:09 -08001400}
1401
1402local_session_t *
1403application_get_local_session_from_handle (session_handle_t handle)
1404{
Florin Coras15531972018-08-12 23:50:53 -07001405 app_worker_t *server_wrk;
1406 u32 session_index, server_wrk_index;
1407 local_session_parse_handle (handle, &server_wrk_index, &session_index);
1408 server_wrk = app_worker_get_if_valid (server_wrk_index);
1409 if (!server_wrk)
Florin Corasfcbda892018-08-23 19:27:03 -07001410 return 0;
Florin Coras15531972018-08-12 23:50:53 -07001411 return application_get_local_session (server_wrk, session_index);
Florin Corasf8f516a2018-02-08 15:10:09 -08001412}
1413
Florin Coras60116992018-08-27 09:52:18 -07001414local_session_t *
Florin Corasab2f6db2018-08-31 14:31:41 -07001415application_local_listen_session_alloc (application_t * app)
Florin Coras60116992018-08-27 09:52:18 -07001416{
Florin Corasab2f6db2018-08-31 14:31:41 -07001417 local_session_t *ll;
1418 pool_get (app->local_listen_sessions, ll);
Dave Barachb7b92992018-10-17 10:38:51 -04001419 clib_memset (ll, 0, sizeof (*ll));
Florin Corasab2f6db2018-08-31 14:31:41 -07001420 return ll;
Florin Coras60116992018-08-27 09:52:18 -07001421}
1422
Florin Corasab2f6db2018-08-31 14:31:41 -07001423u32
1424application_local_listener_index (application_t * app, local_session_t * ll)
Florin Corasf8f516a2018-02-08 15:10:09 -08001425{
Florin Corasab2f6db2018-08-31 14:31:41 -07001426 return (ll - app->local_listen_sessions);
1427}
1428
1429void
1430application_local_listen_session_free (application_t * app,
1431 local_session_t * ll)
1432{
1433 pool_put (app->local_listen_sessions, ll);
1434 if (CLIB_DEBUG)
Dave Barachb7b92992018-10-17 10:38:51 -04001435 clib_memset (ll, 0xfb, sizeof (*ll));
Florin Corasf8f516a2018-02-08 15:10:09 -08001436}
1437
1438int
Florin Corasab2f6db2018-08-31 14:31:41 -07001439application_start_local_listen (application_t * app,
Florin Coras5665ced2018-10-25 18:03:45 -07001440 session_endpoint_cfg_t * sep_ext,
Florin Corasf8f516a2018-02-08 15:10:09 -08001441 session_handle_t * handle)
1442{
Florin Corasab2f6db2018-08-31 14:31:41 -07001443 app_listener_t *app_listener;
1444 session_endpoint_t *sep;
1445 app_worker_t *app_wrk;
Florin Corasf8f516a2018-02-08 15:10:09 -08001446 session_handle_t lh;
1447 local_session_t *ll;
1448 u32 table_index;
1449
Florin Corasab2f6db2018-08-31 14:31:41 -07001450 sep = (session_endpoint_t *) sep_ext;
Florin Coras15531972018-08-12 23:50:53 -07001451 table_index = application_local_session_table (app);
Florin Corasab2f6db2018-08-31 14:31:41 -07001452 app_wrk = app_worker_get (sep_ext->app_wrk_index);
Florin Corasf8f516a2018-02-08 15:10:09 -08001453
1454 /* An exact sep match, as opposed to session_lookup_local_listener */
1455 lh = session_lookup_endpoint_listener (table_index, sep, 1);
1456 if (lh != SESSION_INVALID_HANDLE)
Florin Corasab2f6db2018-08-31 14:31:41 -07001457 {
1458 ll = application_get_local_listener_w_handle (lh);
1459 if (ll->app_index != app->app_index)
1460 return VNET_API_ERROR_ADDRESS_IN_USE;
Florin Corasf8f516a2018-02-08 15:10:09 -08001461
Florin Corasab2f6db2018-08-31 14:31:41 -07001462 if (ll->app_wrk_index == app_wrk->wrk_index)
1463 return VNET_API_ERROR_ADDRESS_IN_USE;
1464
1465 app_listener = app_local_listener_get (app, ll->listener_db_index);
1466 app_listener->workers = clib_bitmap_set (app_listener->workers,
1467 app_wrk->wrk_map_index, 1);
1468 *handle = application_local_session_handle (ll);
1469 return 0;
1470 }
1471
1472 ll = application_local_listen_session_alloc (app);
Florin Corasf8f516a2018-02-08 15:10:09 -08001473 ll->session_type = session_type_from_proto_and_ip (TRANSPORT_PROTO_NONE, 0);
Florin Coras15531972018-08-12 23:50:53 -07001474 ll->app_wrk_index = app_wrk->app_index;
Florin Corasab2f6db2018-08-31 14:31:41 -07001475 ll->session_index = application_local_listener_index (app, ll);
1476 ll->port = sep_ext->port;
Florin Corasf8f516a2018-02-08 15:10:09 -08001477 /* Store the original session type for the unbind */
1478 ll->listener_session_type =
Florin Corasab2f6db2018-08-31 14:31:41 -07001479 session_type_from_proto_and_ip (sep_ext->transport_proto,
1480 sep_ext->is_ip4);
Florin Coras5fda7a32018-02-14 08:04:31 -08001481 ll->transport_listener_index = ~0;
Florin Corasab2f6db2018-08-31 14:31:41 -07001482 ll->app_index = app->app_index;
1483
1484 app_listener = app_local_listener_alloc (app);
1485 ll->listener_db_index = app_listener->al_index;
1486 app_listener->workers = clib_bitmap_set (app_listener->workers,
1487 app_wrk->wrk_map_index, 1);
Florin Corasf8f516a2018-02-08 15:10:09 -08001488
1489 *handle = application_local_session_handle (ll);
1490 session_lookup_add_session_endpoint (table_index, sep, *handle);
1491
1492 return 0;
1493}
1494
1495/**
1496 * Clean up local session table. If we have a listener session use it to
1497 * find the port and proto. If not, the handle must be a local table handle
1498 * so parse it.
1499 */
1500int
Florin Corasab2f6db2018-08-31 14:31:41 -07001501application_stop_local_listen (u32 app_index, u32 wrk_map_index,
1502 session_handle_t lh)
Florin Corasf8f516a2018-02-08 15:10:09 -08001503{
1504 session_endpoint_t sep = SESSION_ENDPOINT_NULL;
Florin Corasab2f6db2018-08-31 14:31:41 -07001505 u32 table_index, ll_index, server_index;
1506 app_listener_t *app_listener;
Florin Coras15531972018-08-12 23:50:53 -07001507 app_worker_t *server_wrk;
Florin Corasf8f516a2018-02-08 15:10:09 -08001508 stream_session_t *sl = 0;
1509 local_session_t *ll, *ls;
Florin Coras15531972018-08-12 23:50:53 -07001510 application_t *server;
Florin Corasf8f516a2018-02-08 15:10:09 -08001511
Florin Coras15531972018-08-12 23:50:53 -07001512 server = application_get (app_index);
Florin Corasf8f516a2018-02-08 15:10:09 -08001513 table_index = application_local_session_table (server);
1514
1515 /* We have both local and global table binds. Figure from global what
1516 * the sep we should be cleaning up is.
1517 */
1518 if (!session_handle_is_local (lh))
1519 {
1520 sl = listen_session_get_from_handle (lh);
1521 if (!sl || listen_session_get_local_session_endpoint (sl, &sep))
1522 {
1523 clib_warning ("broken listener");
1524 return -1;
1525 }
1526 lh = session_lookup_endpoint_listener (table_index, &sep, 0);
1527 if (lh == SESSION_INVALID_HANDLE)
1528 return -1;
1529 }
1530
Florin Corasab2f6db2018-08-31 14:31:41 -07001531 local_session_parse_handle (lh, &server_index, &ll_index);
1532 if (PREDICT_FALSE (server_index != app_index))
Florin Coras15531972018-08-12 23:50:53 -07001533 {
1534 clib_warning ("app %u does not own local handle 0x%lx", app_index, lh);
Florin Corasab2f6db2018-08-31 14:31:41 -07001535 return -1;
Florin Coras15531972018-08-12 23:50:53 -07001536 }
Florin Corasab2f6db2018-08-31 14:31:41 -07001537
1538 ll = application_get_local_listen_session (server, ll_index);
Florin Coras15531972018-08-12 23:50:53 -07001539 if (PREDICT_FALSE (!ll))
Florin Corasf8f516a2018-02-08 15:10:09 -08001540 {
1541 clib_warning ("no local listener");
1542 return -1;
1543 }
Florin Corasf8f516a2018-02-08 15:10:09 -08001544
Florin Corasab2f6db2018-08-31 14:31:41 -07001545 app_listener = app_local_listener_get (server, ll->listener_db_index);
1546 if (!clib_bitmap_get (app_listener->workers, wrk_map_index))
1547 {
1548 clib_warning ("app wrk %u not listening on handle %lu", wrk_map_index,
1549 lh);
1550 return -1;
1551 }
1552
1553 server_wrk = application_get_worker (server, wrk_map_index);
Florin Corasf8f516a2018-02-08 15:10:09 -08001554 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07001555 pool_foreach (ls, server_wrk->local_sessions, ({
Florin Corasf8f516a2018-02-08 15:10:09 -08001556 if (ls->listener_index == ll->session_index)
Florin Coras15531972018-08-12 23:50:53 -07001557 application_local_session_disconnect (server_wrk->app_index, ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001558 }));
1559 /* *INDENT-ON* */
Florin Corasab2f6db2018-08-31 14:31:41 -07001560
1561 clib_bitmap_set_no_check (app_listener->workers, wrk_map_index, 0);
1562 if (clib_bitmap_is_zero (app_listener->workers))
1563 {
1564 app_local_listener_free (server, app_listener);
1565 application_local_listener_session_endpoint (ll, &sep);
1566 session_lookup_del_session_endpoint (table_index, &sep);
1567 application_local_listen_session_free (server, ll);
1568 }
Florin Corasf8f516a2018-02-08 15:10:09 -08001569
1570 return 0;
1571}
1572
Florin Coras99368312018-08-02 10:45:44 -07001573static void
1574application_local_session_fix_eventds (svm_msg_q_t * sq, svm_msg_q_t * cq)
1575{
1576 int fd;
1577
1578 /*
1579 * segment manager initializes only the producer eventds, since vpp is
1580 * typically the producer. But for local sessions, we also pass to the
1581 * apps the mqs they listen on for events from peer apps, so they are also
1582 * consumer fds.
1583 */
1584 fd = svm_msg_q_get_producer_eventfd (sq);
1585 svm_msg_q_set_consumer_eventfd (sq, fd);
1586 fd = svm_msg_q_get_producer_eventfd (cq);
1587 svm_msg_q_set_consumer_eventfd (cq, fd);
1588}
1589
Florin Corasf8f516a2018-02-08 15:10:09 -08001590int
Florin Coras15531972018-08-12 23:50:53 -07001591application_local_session_connect (app_worker_t * client_wrk,
1592 app_worker_t * server_wrk,
Florin Corasf8f516a2018-02-08 15:10:09 -08001593 local_session_t * ll, u32 opaque)
1594{
1595 u32 seg_size, evt_q_sz, evt_q_elts, margin = 16 << 10;
Florin Corasd85de682018-11-29 17:02:29 -08001596 u32 round_rx_fifo_sz, round_tx_fifo_sz, sm_index;
Florin Corasf8f516a2018-02-08 15:10:09 -08001597 segment_manager_properties_t *props, *cprops;
1598 int rv, has_transport, seg_index;
1599 svm_fifo_segment_private_t *seg;
Florin Coras15531972018-08-12 23:50:53 -07001600 application_t *server, *client;
Florin Corasf8f516a2018-02-08 15:10:09 -08001601 segment_manager_t *sm;
1602 local_session_t *ls;
Florin Coras3c2fed52018-07-04 04:15:05 -07001603 svm_msg_q_t *sq, *cq;
Florin Corasfa76a762018-11-29 12:40:10 -08001604 u64 segment_handle;
Florin Corasf8f516a2018-02-08 15:10:09 -08001605
Florin Corasab2f6db2018-08-31 14:31:41 -07001606 ls = application_local_session_alloc (server_wrk);
Florin Coras15531972018-08-12 23:50:53 -07001607 server = application_get (server_wrk->app_index);
1608 client = application_get (client_wrk->app_index);
Florin Corasf8f516a2018-02-08 15:10:09 -08001609
1610 props = application_segment_manager_properties (server);
1611 cprops = application_segment_manager_properties (client);
1612 evt_q_elts = props->evt_q_size + cprops->evt_q_size;
Florin Coras3c2fed52018-07-04 04:15:05 -07001613 evt_q_sz = segment_manager_evt_q_expected_size (evt_q_elts);
Florin Coras54693d22018-07-17 10:46:29 -07001614 round_rx_fifo_sz = 1 << max_log2 (props->rx_fifo_size);
1615 round_tx_fifo_sz = 1 << max_log2 (props->tx_fifo_size);
1616 seg_size = round_rx_fifo_sz + round_tx_fifo_sz + evt_q_sz + margin;
Florin Corasf8f516a2018-02-08 15:10:09 -08001617
1618 has_transport = session_has_transport ((stream_session_t *) ll);
1619 if (!has_transport)
1620 {
1621 /* Local sessions don't have backing transport */
1622 ls->port = ll->port;
Florin Coras15531972018-08-12 23:50:53 -07001623 sm = application_get_local_segment_manager (server_wrk);
Florin Corasf8f516a2018-02-08 15:10:09 -08001624 }
1625 else
1626 {
1627 stream_session_t *sl = (stream_session_t *) ll;
1628 transport_connection_t *tc;
1629 tc = listen_session_get_transport (sl);
1630 ls->port = tc->lcl_port;
Florin Coras15531972018-08-12 23:50:53 -07001631 sm = app_worker_get_listen_segment_manager (server_wrk, sl);
Florin Corasf8f516a2018-02-08 15:10:09 -08001632 }
1633
1634 seg_index = segment_manager_add_segment (sm, seg_size);
1635 if (seg_index < 0)
1636 {
1637 clib_warning ("failed to add new cut-through segment");
1638 return seg_index;
1639 }
1640 seg = segment_manager_get_segment_w_lock (sm, seg_index);
Florin Coras99368312018-08-02 10:45:44 -07001641 sq = segment_manager_alloc_queue (seg, props);
1642 cq = segment_manager_alloc_queue (seg, cprops);
1643
1644 if (props->use_mq_eventfd)
1645 application_local_session_fix_eventds (sq, cq);
1646
Florin Corasf8f516a2018-02-08 15:10:09 -08001647 ls->server_evt_q = pointer_to_uword (sq);
1648 ls->client_evt_q = pointer_to_uword (cq);
1649 rv = segment_manager_try_alloc_fifos (seg, props->rx_fifo_size,
1650 props->tx_fifo_size,
1651 &ls->server_rx_fifo,
1652 &ls->server_tx_fifo);
1653 if (rv)
1654 {
1655 clib_warning ("failed to add fifos in cut-through segment");
1656 segment_manager_segment_reader_unlock (sm);
1657 goto failed;
1658 }
Florin Corasd85de682018-11-29 17:02:29 -08001659 sm_index = segment_manager_index (sm);
Florin Coras326b81e2018-10-04 19:03:05 -07001660 ls->server_rx_fifo->ct_session_index = ls->session_index;
1661 ls->server_tx_fifo->ct_session_index = ls->session_index;
Florin Corasd85de682018-11-29 17:02:29 -08001662 ls->server_rx_fifo->segment_manager = sm_index;
1663 ls->server_tx_fifo->segment_manager = sm_index;
1664 ls->server_rx_fifo->segment_index = seg_index;
1665 ls->server_tx_fifo->segment_index = seg_index;
Florin Corasf8f516a2018-02-08 15:10:09 -08001666 ls->svm_segment_index = seg_index;
1667 ls->listener_index = ll->session_index;
Florin Coras15531972018-08-12 23:50:53 -07001668 ls->client_wrk_index = client_wrk->wrk_index;
Florin Corasf8f516a2018-02-08 15:10:09 -08001669 ls->client_opaque = opaque;
1670 ls->listener_session_type = ll->session_type;
Florin Corasab2f6db2018-08-31 14:31:41 -07001671 ls->session_state = SESSION_STATE_READY;
Florin Corasf8f516a2018-02-08 15:10:09 -08001672
Florin Corasfa76a762018-11-29 12:40:10 -08001673 segment_handle = segment_manager_segment_handle (sm, seg);
Florin Corasc1f5a432018-11-20 11:31:26 -08001674 if ((rv = server->cb_fns.add_segment_callback (server_wrk->api_client_index,
Florin Corasfa76a762018-11-29 12:40:10 -08001675 segment_handle)))
Florin Corasf8f516a2018-02-08 15:10:09 -08001676 {
1677 clib_warning ("failed to notify server of new segment");
1678 segment_manager_segment_reader_unlock (sm);
1679 goto failed;
1680 }
1681 segment_manager_segment_reader_unlock (sm);
1682 if ((rv = server->cb_fns.session_accept_callback ((stream_session_t *) ls)))
1683 {
1684 clib_warning ("failed to send accept cut-through notify to server");
1685 goto failed;
1686 }
1687 if (server->flags & APP_OPTIONS_FLAGS_IS_BUILTIN)
1688 application_local_session_connect_notify (ls);
1689
1690 return 0;
1691
1692failed:
1693 if (!has_transport)
1694 segment_manager_del_segment (sm, seg);
1695 return rv;
1696}
1697
David Johnsond9818dd2018-12-14 14:53:41 -05001698static u64
Florin Corasf8f516a2018-02-08 15:10:09 -08001699application_client_local_connect_key (local_session_t * ls)
1700{
David Johnsond9818dd2018-12-14 14:53:41 -05001701 return (((u64) ls->app_wrk_index) << 32 | (u64) ls->session_index);
Florin Corasf8f516a2018-02-08 15:10:09 -08001702}
1703
1704static void
David Johnsond9818dd2018-12-14 14:53:41 -05001705application_client_local_connect_key_parse (u64 key, u32 * app_wrk_index,
Florin Corasf8f516a2018-02-08 15:10:09 -08001706 u32 * session_index)
1707{
Florin Coras15531972018-08-12 23:50:53 -07001708 *app_wrk_index = key >> 32;
Florin Corasf8f516a2018-02-08 15:10:09 -08001709 *session_index = key & 0xFFFFFFFF;
1710}
1711
1712int
1713application_local_session_connect_notify (local_session_t * ls)
1714{
1715 svm_fifo_segment_private_t *seg;
Florin Coras15531972018-08-12 23:50:53 -07001716 app_worker_t *client_wrk, *server_wrk;
Florin Corasf8f516a2018-02-08 15:10:09 -08001717 segment_manager_t *sm;
Florin Coras15531972018-08-12 23:50:53 -07001718 application_t *client;
Florin Corasf8f516a2018-02-08 15:10:09 -08001719 int rv, is_fail = 0;
Florin Corasfa76a762018-11-29 12:40:10 -08001720 u64 segment_handle;
David Johnsond9818dd2018-12-14 14:53:41 -05001721 u64 client_key;
Florin Corasf8f516a2018-02-08 15:10:09 -08001722
Florin Coras15531972018-08-12 23:50:53 -07001723 client_wrk = app_worker_get (ls->client_wrk_index);
1724 server_wrk = app_worker_get (ls->app_wrk_index);
1725 client = application_get (client_wrk->app_index);
1726
1727 sm = application_get_local_segment_manager_w_session (server_wrk, ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001728 seg = segment_manager_get_segment_w_lock (sm, ls->svm_segment_index);
Florin Corasfa76a762018-11-29 12:40:10 -08001729 segment_handle = segment_manager_segment_handle (sm, seg);
Florin Corasc1f5a432018-11-20 11:31:26 -08001730 if ((rv = client->cb_fns.add_segment_callback (client_wrk->api_client_index,
Florin Corasfa76a762018-11-29 12:40:10 -08001731 segment_handle)))
Florin Corasf8f516a2018-02-08 15:10:09 -08001732 {
1733 clib_warning ("failed to notify client %u of new segment",
Florin Coras15531972018-08-12 23:50:53 -07001734 ls->client_wrk_index);
Florin Corasf8f516a2018-02-08 15:10:09 -08001735 segment_manager_segment_reader_unlock (sm);
Florin Coras15531972018-08-12 23:50:53 -07001736 application_local_session_disconnect (ls->client_wrk_index, ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001737 is_fail = 1;
1738 }
1739 else
1740 {
1741 segment_manager_segment_reader_unlock (sm);
1742 }
1743
Florin Coras15531972018-08-12 23:50:53 -07001744 client->cb_fns.session_connected_callback (client_wrk->wrk_index,
1745 ls->client_opaque,
Florin Corasf8f516a2018-02-08 15:10:09 -08001746 (stream_session_t *) ls,
1747 is_fail);
1748
1749 client_key = application_client_local_connect_key (ls);
Florin Coras15531972018-08-12 23:50:53 -07001750 hash_set (client_wrk->local_connects, client_key, client_key);
Florin Corasf8f516a2018-02-08 15:10:09 -08001751 return 0;
1752}
1753
1754int
Florin Coras15531972018-08-12 23:50:53 -07001755application_local_session_cleanup (app_worker_t * client_wrk,
1756 app_worker_t * server_wrk,
Florin Corasf6647e02018-03-23 22:56:43 -07001757 local_session_t * ls)
Florin Corasf8f516a2018-02-08 15:10:09 -08001758{
1759 svm_fifo_segment_private_t *seg;
Florin Corasa44d6b12018-10-03 14:29:10 -07001760 stream_session_t *listener;
Florin Corasf8f516a2018-02-08 15:10:09 -08001761 segment_manager_t *sm;
David Johnsond9818dd2018-12-14 14:53:41 -05001762 u64 client_key;
Florin Corasf6647e02018-03-23 22:56:43 -07001763 u8 has_transport;
1764
Florin Corasa44d6b12018-10-03 14:29:10 -07001765 /* Retrieve listener transport type as it is the one that decides where
1766 * the fifos are allocated */
1767 has_transport = application_local_session_listener_has_transport (ls);
Florin Corasf6647e02018-03-23 22:56:43 -07001768 if (!has_transport)
Florin Coras15531972018-08-12 23:50:53 -07001769 sm = application_get_local_segment_manager_w_session (server_wrk, ls);
Florin Corasf6647e02018-03-23 22:56:43 -07001770 else
Florin Corasa44d6b12018-10-03 14:29:10 -07001771 {
1772 listener = listen_session_get (ls->listener_index);
1773 sm = app_worker_get_listen_segment_manager (server_wrk, listener);
1774 }
Florin Corasf6647e02018-03-23 22:56:43 -07001775
1776 seg = segment_manager_get_segment (sm, ls->svm_segment_index);
Florin Coras15531972018-08-12 23:50:53 -07001777 if (client_wrk)
Florin Corasa44d6b12018-10-03 14:29:10 -07001778 {
1779 client_key = application_client_local_connect_key (ls);
1780 hash_unset (client_wrk->local_connects, client_key);
1781 }
Florin Corasf6647e02018-03-23 22:56:43 -07001782
1783 if (!has_transport)
1784 {
Florin Coras15531972018-08-12 23:50:53 -07001785 application_t *server = application_get (server_wrk->app_index);
Florin Corasfa76a762018-11-29 12:40:10 -08001786 u64 segment_handle = segment_manager_segment_handle (sm, seg);
Florin Corasc1f5a432018-11-20 11:31:26 -08001787 server->cb_fns.del_segment_callback (server_wrk->api_client_index,
Florin Corasfa76a762018-11-29 12:40:10 -08001788 segment_handle);
Florin Coras15531972018-08-12 23:50:53 -07001789 if (client_wrk)
1790 {
1791 application_t *client = application_get (client_wrk->app_index);
Florin Corasc1f5a432018-11-20 11:31:26 -08001792 client->cb_fns.del_segment_callback (client_wrk->api_client_index,
Florin Corasfa76a762018-11-29 12:40:10 -08001793 segment_handle);
Florin Coras15531972018-08-12 23:50:53 -07001794 }
Florin Corasf6647e02018-03-23 22:56:43 -07001795 segment_manager_del_segment (sm, seg);
1796 }
1797
Florin Corasab2f6db2018-08-31 14:31:41 -07001798 application_local_session_free (server_wrk, ls);
Florin Corasf6647e02018-03-23 22:56:43 -07001799
1800 return 0;
1801}
1802
1803int
Florin Corasab2f6db2018-08-31 14:31:41 -07001804application_local_session_disconnect (u32 app_index, local_session_t * ls)
Florin Corasf6647e02018-03-23 22:56:43 -07001805{
Florin Coras15531972018-08-12 23:50:53 -07001806 app_worker_t *client_wrk, *server_wrk;
Florin Corasab2f6db2018-08-31 14:31:41 -07001807 u8 is_server = 0, is_client = 0;
1808 application_t *app;
1809
1810 app = application_get_if_valid (app_index);
1811 if (!app)
1812 return 0;
Florin Corasf8f516a2018-02-08 15:10:09 -08001813
Florin Coras15531972018-08-12 23:50:53 -07001814 client_wrk = app_worker_get_if_valid (ls->client_wrk_index);
1815 server_wrk = app_worker_get (ls->app_wrk_index);
1816
Florin Corasab2f6db2018-08-31 14:31:41 -07001817 if (server_wrk->app_index == app_index)
1818 is_server = 1;
1819 else if (client_wrk && client_wrk->app_index == app_index)
1820 is_client = 1;
1821
1822 if (!is_server && !is_client)
1823 {
1824 clib_warning ("app %u is neither client nor server for session 0x%lx",
1825 app_index, application_local_session_handle (ls));
1826 return VNET_API_ERROR_INVALID_VALUE;
1827 }
Florin Corasf8f516a2018-02-08 15:10:09 -08001828
1829 if (ls->session_state == SESSION_STATE_CLOSED)
Florin Coras15531972018-08-12 23:50:53 -07001830 return application_local_session_cleanup (client_wrk, server_wrk, ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001831
Florin Corasab2f6db2018-08-31 14:31:41 -07001832 if (app_index == ls->client_wrk_index)
Florin Corasf8f516a2018-02-08 15:10:09 -08001833 {
Florin Coras15531972018-08-12 23:50:53 -07001834 mq_send_local_session_disconnected_cb (ls->app_wrk_index, ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001835 }
1836 else
1837 {
Florin Coras15531972018-08-12 23:50:53 -07001838 if (!client_wrk)
Florin Corasf8f516a2018-02-08 15:10:09 -08001839 {
Florin Coras15531972018-08-12 23:50:53 -07001840 return application_local_session_cleanup (client_wrk, server_wrk,
1841 ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001842 }
1843 else if (ls->session_state < SESSION_STATE_READY)
1844 {
Florin Coras15531972018-08-12 23:50:53 -07001845 application_t *client = application_get (client_wrk->app_index);
1846 client->cb_fns.session_connected_callback (client_wrk->wrk_index,
Florin Corasf8f516a2018-02-08 15:10:09 -08001847 ls->client_opaque,
1848 (stream_session_t *) ls,
1849 1 /* is_fail */ );
1850 ls->session_state = SESSION_STATE_CLOSED;
Florin Coras15531972018-08-12 23:50:53 -07001851 return application_local_session_cleanup (client_wrk, server_wrk,
1852 ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001853 }
1854 else
1855 {
Florin Coras15531972018-08-12 23:50:53 -07001856 mq_send_local_session_disconnected_cb (client_wrk->wrk_index, ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001857 }
1858 }
1859
1860 ls->session_state = SESSION_STATE_CLOSED;
1861
1862 return 0;
1863}
1864
Florin Corasf6647e02018-03-23 22:56:43 -07001865int
Florin Coras15531972018-08-12 23:50:53 -07001866application_local_session_disconnect_w_index (u32 app_wrk_index, u32 ls_index)
Florin Corasf6647e02018-03-23 22:56:43 -07001867{
Florin Coras15531972018-08-12 23:50:53 -07001868 app_worker_t *app_wrk;
Florin Corasf6647e02018-03-23 22:56:43 -07001869 local_session_t *ls;
Florin Coras15531972018-08-12 23:50:53 -07001870 app_wrk = app_worker_get (app_wrk_index);
1871 ls = application_get_local_session (app_wrk, ls_index);
1872 return application_local_session_disconnect (app_wrk_index, ls);
Florin Corasf6647e02018-03-23 22:56:43 -07001873}
1874
Florin Corasf8f516a2018-02-08 15:10:09 -08001875void
Florin Corasab2f6db2018-08-31 14:31:41 -07001876app_worker_local_sessions_free (app_worker_t * app_wrk)
Florin Corasf8f516a2018-02-08 15:10:09 -08001877{
Florin Corasab2f6db2018-08-31 14:31:41 -07001878 u32 index, server_wrk_index, session_index;
Florin Corasf8f516a2018-02-08 15:10:09 -08001879 u64 handle, *handles = 0;
Florin Coras15531972018-08-12 23:50:53 -07001880 app_worker_t *server_wrk;
Florin Corasab2f6db2018-08-31 14:31:41 -07001881 segment_manager_t *sm;
1882 local_session_t *ls;
Florin Corasf8f516a2018-02-08 15:10:09 -08001883 int i;
1884
1885 /*
Florin Corasf8f516a2018-02-08 15:10:09 -08001886 * Local sessions
1887 */
Florin Coras15531972018-08-12 23:50:53 -07001888 if (app_wrk->local_sessions)
Florin Corasf8f516a2018-02-08 15:10:09 -08001889 {
1890 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07001891 pool_foreach (ls, app_wrk->local_sessions, ({
1892 application_local_session_disconnect (app_wrk->wrk_index, ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001893 }));
1894 /* *INDENT-ON* */
1895 }
1896
1897 /*
1898 * Local connects
1899 */
1900 vec_reset_length (handles);
1901 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07001902 hash_foreach (handle, index, app_wrk->local_connects, ({
Florin Corasf8f516a2018-02-08 15:10:09 -08001903 vec_add1 (handles, handle);
1904 }));
1905 /* *INDENT-ON* */
1906
1907 for (i = 0; i < vec_len (handles); i++)
1908 {
Florin Coras15531972018-08-12 23:50:53 -07001909 application_client_local_connect_key_parse (handles[i],
1910 &server_wrk_index,
Florin Corasf8f516a2018-02-08 15:10:09 -08001911 &session_index);
Florin Coras15531972018-08-12 23:50:53 -07001912 server_wrk = app_worker_get_if_valid (server_wrk_index);
1913 if (server_wrk)
Florin Corasf8f516a2018-02-08 15:10:09 -08001914 {
Florin Coras15531972018-08-12 23:50:53 -07001915 ls = application_get_local_session (server_wrk, session_index);
1916 application_local_session_disconnect (app_wrk->wrk_index, ls);
Florin Corasf8f516a2018-02-08 15:10:09 -08001917 }
1918 }
1919
Florin Coras15531972018-08-12 23:50:53 -07001920 sm = segment_manager_get (app_wrk->local_segment_manager);
1921 sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
Florin Corasf8f516a2018-02-08 15:10:09 -08001922 segment_manager_del (sm);
1923}
1924
Florin Coras371ca502018-02-21 12:07:41 -08001925clib_error_t *
1926vnet_app_add_tls_cert (vnet_app_add_tls_cert_args_t * a)
1927{
1928 application_t *app;
1929 app = application_get (a->app_index);
1930 if (!app)
1931 return clib_error_return_code (0, VNET_API_ERROR_APPLICATION_NOT_ATTACHED,
1932 0, "app %u doesn't exist", a->app_index);
1933 app->tls_cert = vec_dup (a->cert);
1934 return 0;
1935}
1936
1937clib_error_t *
1938vnet_app_add_tls_key (vnet_app_add_tls_key_args_t * a)
1939{
1940 application_t *app;
1941 app = application_get (a->app_index);
1942 if (!app)
1943 return clib_error_return_code (0, VNET_API_ERROR_APPLICATION_NOT_ATTACHED,
1944 0, "app %u doesn't exist", a->app_index);
1945 app->tls_key = vec_dup (a->key);
1946 return 0;
1947}
1948
Dave Barach68b0fb02017-02-28 15:15:56 -05001949u8 *
Florin Coras15531972018-08-12 23:50:53 -07001950format_app_worker_listener (u8 * s, va_list * args)
Dave Barach68b0fb02017-02-28 15:15:56 -05001951{
Florin Coras15531972018-08-12 23:50:53 -07001952 app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
Florin Coras6cf30ad2017-04-04 23:08:23 -07001953 u64 handle = va_arg (*args, u64);
Florin Corasf8f516a2018-02-08 15:10:09 -08001954 u32 sm_index = va_arg (*args, u32);
Dave Barach68b0fb02017-02-28 15:15:56 -05001955 int verbose = va_arg (*args, int);
Florin Coras6cf30ad2017-04-04 23:08:23 -07001956 stream_session_t *listener;
Florin Coras053a0e42018-11-13 15:52:38 -08001957 const u8 *app_name;
1958 u8 *str;
Dave Barach68b0fb02017-02-28 15:15:56 -05001959
Florin Coras15531972018-08-12 23:50:53 -07001960 if (!app_wrk)
Dave Barach68b0fb02017-02-28 15:15:56 -05001961 {
1962 if (verbose)
Florin Corasab2f6db2018-08-31 14:31:41 -07001963 s = format (s, "%-40s%-25s%=10s%-15s%-15s%-10s", "Connection", "App",
1964 "Wrk", "API Client", "ListenerID", "SegManager");
Dave Barach68b0fb02017-02-28 15:15:56 -05001965 else
Florin Corasab2f6db2018-08-31 14:31:41 -07001966 s = format (s, "%-40s%-25s%=10s", "Connection", "App", "Wrk");
Dave Barach68b0fb02017-02-28 15:15:56 -05001967
1968 return s;
1969 }
1970
Florin Corasc1f5a432018-11-20 11:31:26 -08001971 app_name = application_name_from_index (app_wrk->app_index);
Florin Coras6cf30ad2017-04-04 23:08:23 -07001972 listener = listen_session_get_from_handle (handle);
1973 str = format (0, "%U", format_stream_session, listener, verbose);
Dave Barach68b0fb02017-02-28 15:15:56 -05001974
Dave Barach68b0fb02017-02-28 15:15:56 -05001975 if (verbose)
1976 {
Florin Coras74cac882018-09-07 09:13:15 -07001977 char buf[32];
1978 sprintf (buf, "%u(%u)", app_wrk->wrk_map_index, app_wrk->wrk_index);
1979 s = format (s, "%-40s%-25s%=10s%-15u%-15u%-10u", str, app_name,
Florin Corasc1f5a432018-11-20 11:31:26 -08001980 buf, app_wrk->api_client_index, handle, sm_index);
Dave Barach68b0fb02017-02-28 15:15:56 -05001981 }
1982 else
Florin Corasab2f6db2018-08-31 14:31:41 -07001983 s = format (s, "%-40s%-25s%=10u", str, app_name, app_wrk->wrk_map_index);
Florin Coras6cf30ad2017-04-04 23:08:23 -07001984
Florin Coras6cf30ad2017-04-04 23:08:23 -07001985 return s;
1986}
1987
Florin Coras15531972018-08-12 23:50:53 -07001988static void
1989application_format_listeners (application_t * app, int verbose)
1990{
1991 vlib_main_t *vm = vlib_get_main ();
1992 app_worker_map_t *wrk_map;
1993 app_worker_t *app_wrk;
1994 u32 sm_index;
1995 u64 handle;
1996
1997 if (!app)
1998 {
1999 vlib_cli_output (vm, "%U", format_app_worker_listener, 0 /* header */ ,
2000 0, 0, verbose);
2001 return;
2002 }
2003
2004 /* *INDENT-OFF* */
2005 pool_foreach (wrk_map, app->worker_maps, ({
2006 app_wrk = app_worker_get (wrk_map->wrk_index);
2007 if (hash_elts (app_wrk->listeners_table) == 0)
2008 continue;
2009 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
2010 vlib_cli_output (vm, "%U", format_app_worker_listener, app_wrk,
2011 handle, sm_index, verbose);
2012 }));
2013 }));
2014 /* *INDENT-ON* */
2015}
2016
2017static void
2018app_worker_format_connects (app_worker_t * app_wrk, int verbose)
Florin Coras6cf30ad2017-04-04 23:08:23 -07002019{
Florin Corasa332c462018-01-31 06:52:17 -08002020 svm_fifo_segment_private_t *fifo_segment;
Florin Coras6cf30ad2017-04-04 23:08:23 -07002021 vlib_main_t *vm = vlib_get_main ();
2022 segment_manager_t *sm;
Florin Coras053a0e42018-11-13 15:52:38 -08002023 const u8 *app_name;
Florin Coras053a0e42018-11-13 15:52:38 -08002024 u8 *s = 0;
Florin Coras6cf30ad2017-04-04 23:08:23 -07002025
2026 /* Header */
Florin Coras15531972018-08-12 23:50:53 -07002027 if (!app_wrk)
Florin Coras6cf30ad2017-04-04 23:08:23 -07002028 {
2029 if (verbose)
2030 vlib_cli_output (vm, "%-40s%-20s%-15s%-10s", "Connection", "App",
2031 "API Client", "SegManager");
2032 else
2033 vlib_cli_output (vm, "%-40s%-20s", "Connection", "App");
2034 return;
2035 }
2036
Florin Coras15531972018-08-12 23:50:53 -07002037 if (app_wrk->connects_seg_manager == (u32) ~ 0)
Florin Coras6cf30ad2017-04-04 23:08:23 -07002038 return;
2039
Florin Corasc1f5a432018-11-20 11:31:26 -08002040 app_name = application_name_from_index (app_wrk->app_index);
Florin Coras6cf30ad2017-04-04 23:08:23 -07002041
2042 /* Across all fifo segments */
Florin Coras15531972018-08-12 23:50:53 -07002043 sm = segment_manager_get (app_wrk->connects_seg_manager);
Florin Coras6cf30ad2017-04-04 23:08:23 -07002044
Florin Corasa332c462018-01-31 06:52:17 -08002045 /* *INDENT-OFF* */
2046 segment_manager_foreach_segment_w_lock (fifo_segment, sm, ({
2047 svm_fifo_t *fifo;
2048 u8 *str;
2049
2050 fifo = svm_fifo_segment_get_fifo_list (fifo_segment);
2051 while (fifo)
Florin Corasc1f5a432018-11-20 11:31:26 -08002052 {
2053 u32 session_index, thread_index;
2054 stream_session_t *session;
Florin Coras6cf30ad2017-04-04 23:08:23 -07002055
Florin Corasc1f5a432018-11-20 11:31:26 -08002056 session_index = fifo->master_session_index;
2057 thread_index = fifo->master_thread_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -07002058
Florin Corasc1f5a432018-11-20 11:31:26 -08002059 session = session_get (session_index, thread_index);
2060 str = format (0, "%U", format_stream_session, session, verbose);
Florin Coras6cf30ad2017-04-04 23:08:23 -07002061
Florin Corasc1f5a432018-11-20 11:31:26 -08002062 if (verbose)
2063 s = format (s, "%-40s%-20s%-15u%-10u", str, app_name,
2064 app_wrk->api_client_index, app_wrk->connects_seg_manager);
2065 else
2066 s = format (s, "%-40s%-20s", str, app_name);
Florin Coras6cf30ad2017-04-04 23:08:23 -07002067
Florin Corasc1f5a432018-11-20 11:31:26 -08002068 vlib_cli_output (vm, "%v", s);
2069 vec_reset_length (s);
2070 vec_free (str);
Dave Barach10d8cc62017-05-30 09:30:07 -04002071
Florin Corasc1f5a432018-11-20 11:31:26 -08002072 fifo = fifo->next;
2073 }
Florin Corasa332c462018-01-31 06:52:17 -08002074 vec_free (s);
2075 }));
2076 /* *INDENT-ON* */
Florin Coras6cf30ad2017-04-04 23:08:23 -07002077
Florin Coras6cf30ad2017-04-04 23:08:23 -07002078}
2079
Florin Coras15531972018-08-12 23:50:53 -07002080static void
2081application_format_connects (application_t * app, int verbose)
2082{
2083 app_worker_map_t *wrk_map;
2084 app_worker_t *app_wrk;
2085
2086 if (!app)
2087 {
2088 app_worker_format_connects (0, verbose);
2089 return;
2090 }
2091
2092 /* *INDENT-OFF* */
2093 pool_foreach (wrk_map, app->worker_maps, ({
2094 app_wrk = app_worker_get (wrk_map->wrk_index);
2095 app_worker_format_connects (app_wrk, verbose);
2096 }));
2097 /* *INDENT-ON* */
2098}
2099
2100static void
2101app_worker_format_local_sessions (app_worker_t * app_wrk, int verbose)
Florin Corasf8f516a2018-02-08 15:10:09 -08002102{
2103 vlib_main_t *vm = vlib_get_main ();
2104 local_session_t *ls;
2105 transport_proto_t tp;
2106 u8 *conn = 0;
2107
2108 /* Header */
Florin Coras15531972018-08-12 23:50:53 -07002109 if (app_wrk == 0)
Florin Corasf8f516a2018-02-08 15:10:09 -08002110 {
2111 vlib_cli_output (vm, "%-40s%-15s%-20s", "Connection", "ServerApp",
2112 "ClientApp");
2113 return;
2114 }
2115
Florin Coras15531972018-08-12 23:50:53 -07002116 if (!pool_elts (app_wrk->local_sessions)
2117 && !pool_elts (app_wrk->local_connects))
2118 return;
2119
Florin Corasf8f516a2018-02-08 15:10:09 -08002120 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07002121 pool_foreach (ls, app_wrk->local_sessions, ({
Florin Corasf8f516a2018-02-08 15:10:09 -08002122 tp = session_type_transport_proto(ls->listener_session_type);
2123 conn = format (0, "[L][%U] *:%u", format_transport_proto_short, tp,
2124 ls->port);
Florin Coras15531972018-08-12 23:50:53 -07002125 vlib_cli_output (vm, "%-40v%-15u%-20u", conn, ls->app_wrk_index,
2126 ls->client_wrk_index);
Florin Corasf8f516a2018-02-08 15:10:09 -08002127 vec_reset_length (conn);
2128 }));
2129 /* *INDENT-ON* */
2130
2131 vec_free (conn);
2132}
2133
Florin Coras15531972018-08-12 23:50:53 -07002134static void
2135application_format_local_sessions (application_t * app, int verbose)
2136{
Florin Corasab2f6db2018-08-31 14:31:41 -07002137 vlib_main_t *vm = vlib_get_main ();
Florin Coras15531972018-08-12 23:50:53 -07002138 app_worker_map_t *wrk_map;
2139 app_worker_t *app_wrk;
Florin Corasab2f6db2018-08-31 14:31:41 -07002140 transport_proto_t tp;
2141 local_session_t *ls;
2142 u8 *conn = 0;
Florin Coras15531972018-08-12 23:50:53 -07002143
2144 if (!app)
2145 {
2146 app_worker_format_local_sessions (0, verbose);
2147 return;
2148 }
2149
Florin Corasab2f6db2018-08-31 14:31:41 -07002150 /*
2151 * Format local listeners
2152 */
2153
2154 /* *INDENT-OFF* */
2155 pool_foreach (ls, app->local_listen_sessions, ({
2156 tp = session_type_transport_proto (ls->listener_session_type);
2157 conn = format (0, "[L][%U] *:%u", format_transport_proto_short, tp,
2158 ls->port);
2159 vlib_cli_output (vm, "%-40v%-15u%-20s", conn, ls->app_wrk_index, "*");
2160 vec_reset_length (conn);
2161 }));
2162 /* *INDENT-ON* */
2163
2164 /*
2165 * Format local accepted/connected sessions
2166 */
Florin Coras15531972018-08-12 23:50:53 -07002167 /* *INDENT-OFF* */
2168 pool_foreach (wrk_map, app->worker_maps, ({
2169 app_wrk = app_worker_get (wrk_map->wrk_index);
2170 app_worker_format_local_sessions (app_wrk, verbose);
2171 }));
2172 /* *INDENT-ON* */
2173}
2174
2175static void
2176app_worker_format_local_connects (app_worker_t * app, int verbose)
Florin Corasf8f516a2018-02-08 15:10:09 -08002177{
2178 vlib_main_t *vm = vlib_get_main ();
Florin Coras15531972018-08-12 23:50:53 -07002179 u32 app_wrk_index, session_index;
2180 app_worker_t *server_wrk;
Florin Corasf8f516a2018-02-08 15:10:09 -08002181 local_session_t *ls;
David Johnsond9818dd2018-12-14 14:53:41 -05002182 u64 client_key;
Florin Corasf8f516a2018-02-08 15:10:09 -08002183 u64 value;
2184
2185 /* Header */
2186 if (app == 0)
2187 {
2188 if (verbose)
2189 vlib_cli_output (vm, "%-40s%-15s%-20s%-10s", "Connection", "App",
2190 "Peer App", "SegManager");
2191 else
2192 vlib_cli_output (vm, "%-40s%-15s%-20s", "Connection", "App",
2193 "Peer App");
2194 return;
2195 }
2196
Florin Coras15531972018-08-12 23:50:53 -07002197 if (!app->local_connects)
2198 return;
2199
Florin Corasf8f516a2018-02-08 15:10:09 -08002200 /* *INDENT-OFF* */
2201 hash_foreach (client_key, value, app->local_connects, ({
Florin Coras15531972018-08-12 23:50:53 -07002202 application_client_local_connect_key_parse (client_key, &app_wrk_index,
Florin Corasf8f516a2018-02-08 15:10:09 -08002203 &session_index);
Florin Coras15531972018-08-12 23:50:53 -07002204 server_wrk = app_worker_get (app_wrk_index);
2205 ls = application_get_local_session (server_wrk, session_index);
2206 vlib_cli_output (vm, "%-40s%-15s%-20s", "TODO", ls->app_wrk_index,
2207 ls->client_wrk_index);
2208 }));
2209 /* *INDENT-ON* */
2210}
2211
2212static void
2213application_format_local_connects (application_t * app, int verbose)
2214{
2215 app_worker_map_t *wrk_map;
2216 app_worker_t *app_wrk;
2217
2218 if (!app)
2219 {
2220 app_worker_format_local_connects (0, verbose);
2221 return;
2222 }
2223
2224 /* *INDENT-OFF* */
2225 pool_foreach (wrk_map, app->worker_maps, ({
2226 app_wrk = app_worker_get (wrk_map->wrk_index);
2227 app_worker_format_local_connects (app_wrk, verbose);
Florin Corasf8f516a2018-02-08 15:10:09 -08002228 }));
2229 /* *INDENT-ON* */
2230}
2231
Florin Coras6cf30ad2017-04-04 23:08:23 -07002232u8 *
Florin Coras349f8ca2018-11-20 16:52:49 -08002233format_application_worker (u8 * s, va_list * args)
2234{
2235 app_worker_t *app_wrk = va_arg (*args, app_worker_t *);
2236 u32 indent = 1;
2237
2238 s = format (s, "%U wrk-index %u app-index %u map-index %u "
2239 "api-client-index %d\n", format_white_space, indent,
2240 app_wrk->wrk_index, app_wrk->app_index, app_wrk->wrk_map_index,
2241 app_wrk->api_client_index);
2242 return s;
2243}
2244
2245u8 *
Florin Coras6cf30ad2017-04-04 23:08:23 -07002246format_application (u8 * s, va_list * args)
2247{
2248 application_t *app = va_arg (*args, application_t *);
2249 CLIB_UNUSED (int verbose) = va_arg (*args, int);
Florin Corasad0c77f2017-11-09 18:00:15 -08002250 segment_manager_properties_t *props;
Florin Coras053a0e42018-11-13 15:52:38 -08002251 const u8 *app_ns_name, *app_name;
Florin Coras349f8ca2018-11-20 16:52:49 -08002252 app_worker_map_t *wrk_map;
2253 app_worker_t *app_wrk;
Florin Coras6cf30ad2017-04-04 23:08:23 -07002254
2255 if (app == 0)
2256 {
Florin Coras349f8ca2018-11-20 16:52:49 -08002257 if (!verbose)
Florin Corasc1f5a432018-11-20 11:31:26 -08002258 s = format (s, "%-10s%-20s%-40s", "Index", "Name", "Namespace");
Florin Coras6cf30ad2017-04-04 23:08:23 -07002259 return s;
2260 }
2261
Florin Coras0bee9ce2018-03-22 21:24:31 -07002262 app_name = app_get_name (app);
Florin Corascea194d2017-10-02 00:18:51 -07002263 app_ns_name = app_namespace_id_from_index (app->ns_index);
Florin Corasa332c462018-01-31 06:52:17 -08002264 props = application_segment_manager_properties (app);
Florin Coras349f8ca2018-11-20 16:52:49 -08002265 if (!verbose)
2266 {
2267 s = format (s, "%-10u%-20s%-40s", app->app_index, app_name,
2268 app_ns_name);
2269 return s;
2270 }
2271
2272 s = format (s, "app-name %s app-index %u ns-index %u seg-size %U\n",
2273 app_name, app->app_index, app->ns_index,
2274 format_memory_size, props->add_segment_size);
2275 s = format (s, "rx-fifo-size %U tx-fifo-size %U workers:\n",
2276 format_memory_size, props->rx_fifo_size,
2277 format_memory_size, props->tx_fifo_size);
2278
2279 /* *INDENT-OFF* */
2280 pool_foreach (wrk_map, app->worker_maps, ({
2281 app_wrk = app_worker_get (wrk_map->wrk_index);
2282 s = format (s, "%U", format_application_worker, app_wrk);
2283 }));
2284 /* *INDENT-ON* */
2285
Dave Barach68b0fb02017-02-28 15:15:56 -05002286 return s;
2287}
2288
Florin Corasf8f516a2018-02-08 15:10:09 -08002289void
2290application_format_all_listeners (vlib_main_t * vm, int do_local, int verbose)
2291{
2292 application_t *app;
Florin Corasf8f516a2018-02-08 15:10:09 -08002293
Florin Coras15531972018-08-12 23:50:53 -07002294 if (!pool_elts (app_main.app_pool))
Florin Corasf8f516a2018-02-08 15:10:09 -08002295 {
2296 vlib_cli_output (vm, "No active server bindings");
2297 return;
2298 }
2299
2300 if (do_local)
2301 {
2302 application_format_local_sessions (0, verbose);
2303 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07002304 pool_foreach (app, app_main.app_pool, ({
Florin Corasf8f516a2018-02-08 15:10:09 -08002305 application_format_local_sessions (app, verbose);
2306 }));
2307 /* *INDENT-ON* */
2308 }
2309 else
2310 {
Florin Coras15531972018-08-12 23:50:53 -07002311 application_format_listeners (0, verbose);
Florin Corasf8f516a2018-02-08 15:10:09 -08002312
2313 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07002314 pool_foreach (app, app_main.app_pool, ({
2315 application_format_listeners (app, verbose);
Florin Corasf8f516a2018-02-08 15:10:09 -08002316 }));
2317 /* *INDENT-ON* */
2318 }
2319}
2320
2321void
2322application_format_all_clients (vlib_main_t * vm, int do_local, int verbose)
2323{
2324 application_t *app;
2325
Florin Coras15531972018-08-12 23:50:53 -07002326 if (!pool_elts (app_main.app_pool))
Florin Corasf8f516a2018-02-08 15:10:09 -08002327 {
2328 vlib_cli_output (vm, "No active apps");
2329 return;
2330 }
2331
2332 if (do_local)
2333 {
2334 application_format_local_connects (0, verbose);
2335
2336 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07002337 pool_foreach (app, app_main.app_pool, ({
2338 application_format_local_connects (app, verbose);
Florin Corasf8f516a2018-02-08 15:10:09 -08002339 }));
2340 /* *INDENT-ON* */
2341 }
2342 else
2343 {
2344 application_format_connects (0, verbose);
2345
2346 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07002347 pool_foreach (app, app_main.app_pool, ({
Florin Corasf8f516a2018-02-08 15:10:09 -08002348 application_format_connects (app, verbose);
2349 }));
2350 /* *INDENT-ON* */
2351 }
2352}
2353
Dave Barach68b0fb02017-02-28 15:15:56 -05002354static clib_error_t *
2355show_app_command_fn (vlib_main_t * vm, unformat_input_t * input,
2356 vlib_cli_command_t * cmd)
2357{
Florin Corasf8f516a2018-02-08 15:10:09 -08002358 int do_server = 0, do_client = 0, do_local = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05002359 application_t *app;
Florin Coras349f8ca2018-11-20 16:52:49 -08002360 u32 app_index = ~0;
Dave Barach68b0fb02017-02-28 15:15:56 -05002361 int verbose = 0;
2362
Florin Corascea194d2017-10-02 00:18:51 -07002363 session_cli_return_if_not_enabled ();
Florin Corase04c2992017-03-01 08:17:34 -08002364
Dave Barach68b0fb02017-02-28 15:15:56 -05002365 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2366 {
2367 if (unformat (input, "server"))
2368 do_server = 1;
2369 else if (unformat (input, "client"))
2370 do_client = 1;
Florin Corasf8f516a2018-02-08 15:10:09 -08002371 else if (unformat (input, "local"))
2372 do_local = 1;
Florin Coras349f8ca2018-11-20 16:52:49 -08002373 else if (unformat (input, "%u", &app_index))
2374 ;
Dave Barach68b0fb02017-02-28 15:15:56 -05002375 else if (unformat (input, "verbose"))
2376 verbose = 1;
2377 else
Florin Coras349f8ca2018-11-20 16:52:49 -08002378 return clib_error_return (0, "unknown input `%U'",
2379 format_unformat_error, input);
Dave Barach68b0fb02017-02-28 15:15:56 -05002380 }
2381
2382 if (do_server)
Florin Coras349f8ca2018-11-20 16:52:49 -08002383 {
2384 application_format_all_listeners (vm, do_local, verbose);
2385 return 0;
2386 }
Dave Barach68b0fb02017-02-28 15:15:56 -05002387
2388 if (do_client)
Florin Coras349f8ca2018-11-20 16:52:49 -08002389 {
2390 application_format_all_clients (vm, do_local, verbose);
2391 return 0;
2392 }
2393
2394 if (app_index != ~0)
2395 {
Florin Coras47c40e22018-11-26 17:01:36 -08002396 app = application_get_if_valid (app_index);
Florin Coras349f8ca2018-11-20 16:52:49 -08002397 if (!app)
2398 return clib_error_return (0, "No app with index %u", app_index);
2399
2400 vlib_cli_output (vm, "%U", format_application, app, /* verbose */ 1);
2401 return 0;
2402 }
Dave Barach68b0fb02017-02-28 15:15:56 -05002403
Florin Coras6cf30ad2017-04-04 23:08:23 -07002404 /* Print app related info */
2405 if (!do_server && !do_client)
2406 {
Florin Coras349f8ca2018-11-20 16:52:49 -08002407 vlib_cli_output (vm, "%U", format_application, 0, 0);
Florin Corascea194d2017-10-02 00:18:51 -07002408 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07002409 pool_foreach (app, app_main.app_pool, ({
Florin Coras349f8ca2018-11-20 16:52:49 -08002410 vlib_cli_output (vm, "%U", format_application, app, 0);
Florin Corascea194d2017-10-02 00:18:51 -07002411 }));
2412 /* *INDENT-ON* */
Florin Coras6cf30ad2017-04-04 23:08:23 -07002413 }
2414
Dave Barach68b0fb02017-02-28 15:15:56 -05002415 return 0;
2416}
2417
Florin Corase04c2992017-03-01 08:17:34 -08002418/* *INDENT-OFF* */
Dave Barach68b0fb02017-02-28 15:15:56 -05002419VLIB_CLI_COMMAND (show_app_command, static) =
2420{
Florin Corase04c2992017-03-01 08:17:34 -08002421 .path = "show app",
2422 .short_help = "show app [server|client] [verbose]",
2423 .function = show_app_command_fn,
2424};
2425/* *INDENT-ON* */
Dave Barach68b0fb02017-02-28 15:15:56 -05002426
2427/*
2428 * fd.io coding-style-patch-verification: ON
2429 *
2430 * Local Variables:
2431 * eval: (c-set-style "gnu")
2432 * End:
2433 */