blob: d105119c557038ff5137d2cf3e4912280ccf5045 [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>
Dave Barach68b0fb02017-02-28 15:15:56 -050018#include <vnet/session/session.h>
19
Florin Coras6cf30ad2017-04-04 23:08:23 -070020/**
Dave Barach68b0fb02017-02-28 15:15:56 -050021 * Pool from which we allocate all applications
22 */
23static application_t *app_pool;
24
Florin Coras6cf30ad2017-04-04 23:08:23 -070025/**
Dave Barach68b0fb02017-02-28 15:15:56 -050026 * Hash table of apps by api client index
27 */
28static uword *app_by_api_client_index;
29
Florin Coras6cf30ad2017-04-04 23:08:23 -070030/**
31 * Default application event queue size
32 */
33static u32 default_app_evt_queue_size = 128;
34
Dave Barach68b0fb02017-02-28 15:15:56 -050035int
36application_api_queue_is_full (application_t * app)
37{
38 unix_shared_memory_queue_t *q;
39
40 /* builtin servers are always OK */
41 if (app->api_client_index == ~0)
42 return 0;
43
44 q = vl_api_client_index_to_input_queue (app->api_client_index);
45 if (!q)
46 return 1;
47
48 if (q->cursize == q->maxsize)
49 return 1;
50 return 0;
51}
52
53static void
54application_table_add (application_t * app)
55{
56 hash_set (app_by_api_client_index, app->api_client_index, app->index);
57}
58
59static void
60application_table_del (application_t * app)
61{
62 hash_unset (app_by_api_client_index, app->api_client_index);
63}
64
65application_t *
66application_lookup (u32 api_client_index)
67{
68 uword *p;
69 p = hash_get (app_by_api_client_index, api_client_index);
70 if (p)
71 return application_get (p[0]);
72
73 return 0;
74}
75
Florin Coras6cf30ad2017-04-04 23:08:23 -070076application_t *
77application_new ()
78{
79 application_t *app;
80 pool_get (app_pool, app);
81 memset (app, 0, sizeof (*app));
82 app->index = application_get_index (app);
Florin Corasc87c91d2017-08-16 19:55:49 -070083 app->connects_seg_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
84 app->first_segment_manager = APP_INVALID_SEGMENT_MANAGER_INDEX;
Dave Wallace7b749fe2017-07-05 14:30:46 -040085 if (CLIB_DEBUG > 1)
86 clib_warning ("[%d] New app (%d)", getpid (), app->index);
Florin Coras6cf30ad2017-04-04 23:08:23 -070087 return app;
88}
89
Dave Barach68b0fb02017-02-28 15:15:56 -050090void
91application_del (application_t * app)
92{
Florin Coras6cf30ad2017-04-04 23:08:23 -070093 segment_manager_t *sm;
94 u64 handle;
95 u32 index, *handles = 0;
96 int i;
97 vnet_unbind_args_t _a, *a = &_a;
Dave Barach68b0fb02017-02-28 15:15:56 -050098
Florin Coras6cf30ad2017-04-04 23:08:23 -070099 /*
Florin Corasa5464812017-04-19 13:00:05 -0700100 * The app event queue allocated in first segment is cleared with
101 * the segment manager. No need to explicitly free it.
102 */
Dave Wallace7b749fe2017-07-05 14:30:46 -0400103 if (CLIB_DEBUG > 1)
104 clib_warning ("[%d] Delete app (%d)", getpid (), app->index);
Florin Corasa5464812017-04-19 13:00:05 -0700105
106 /*
Florin Corasc87c91d2017-08-16 19:55:49 -0700107 * Listener cleanup
Florin Coras6cf30ad2017-04-04 23:08:23 -0700108 */
Dave Barach68b0fb02017-02-28 15:15:56 -0500109
Florin Coras6cf30ad2017-04-04 23:08:23 -0700110 /* *INDENT-OFF* */
111 hash_foreach (handle, index, app->listeners_table,
112 ({
113 vec_add1 (handles, handle);
114 }));
115 /* *INDENT-ON* */
116
Florin Coras6cf30ad2017-04-04 23:08:23 -0700117 for (i = 0; i < vec_len (handles); i++)
118 {
Florin Corasf03a59a2017-06-09 21:07:32 -0700119 a->app_index = app->index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700120 a->handle = handles[i];
121 /* seg manager is removed when unbind completes */
122 vnet_unbind (a);
123 }
124
Florin Corasc87c91d2017-08-16 19:55:49 -0700125 /*
126 * Connects segment manager cleanup
127 */
128
129 if (app->connects_seg_manager != APP_INVALID_SEGMENT_MANAGER_INDEX)
130 {
131 sm = segment_manager_get (app->connects_seg_manager);
132 sm->app_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
133 segment_manager_init_del (sm);
134 }
135
136
137 /* If first segment manager is used by a listener */
138 if (app->first_segment_manager != APP_INVALID_SEGMENT_MANAGER_INDEX
139 && app->first_segment_manager != app->connects_seg_manager)
Dave Wallace7b749fe2017-07-05 14:30:46 -0400140 {
141 sm = segment_manager_get (app->first_segment_manager);
Florin Corasc87c91d2017-08-16 19:55:49 -0700142 /* .. and has no fifos, e.g. it might be used for redirected sessions,
143 * remove it */
144 if (!segment_manager_has_fifos (sm))
145 {
146 sm->app_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
147 segment_manager_del (sm);
148 }
Dave Wallace7b749fe2017-07-05 14:30:46 -0400149 }
150
Dave Barach68b0fb02017-02-28 15:15:56 -0500151 application_table_del (app);
Dave Barach68b0fb02017-02-28 15:15:56 -0500152 pool_put (app_pool, app);
153}
154
Florin Corasd79b41e2017-03-04 05:37:52 -0800155static void
Florin Coras6cf30ad2017-04-04 23:08:23 -0700156application_verify_cb_fns (session_cb_vft_t * cb_fns)
Florin Corasd79b41e2017-03-04 05:37:52 -0800157{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700158 if (cb_fns->session_accept_callback == 0)
Florin Corasd79b41e2017-03-04 05:37:52 -0800159 clib_warning ("No accept callback function provided");
Florin Coras6cf30ad2017-04-04 23:08:23 -0700160 if (cb_fns->session_connected_callback == 0)
Florin Corasd79b41e2017-03-04 05:37:52 -0800161 clib_warning ("No session connected callback function provided");
162 if (cb_fns->session_disconnect_callback == 0)
163 clib_warning ("No session disconnect callback function provided");
164 if (cb_fns->session_reset_callback == 0)
165 clib_warning ("No session reset callback function provided");
166}
167
Florin Coras6cf30ad2017-04-04 23:08:23 -0700168int
169application_init (application_t * app, u32 api_client_index, u64 * options,
170 session_cb_vft_t * cb_fns)
Dave Barach68b0fb02017-02-28 15:15:56 -0500171{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700172 segment_manager_t *sm;
173 segment_manager_properties_t *props;
Florin Corasa5464812017-04-19 13:00:05 -0700174 u32 app_evt_queue_size, first_seg_size;
Florin Corasc87c91d2017-08-16 19:55:49 -0700175 u32 default_rx_fifo_size = 16 << 10, default_tx_fifo_size = 16 << 10;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700176 int rv;
Dave Barach68b0fb02017-02-28 15:15:56 -0500177
Florin Coras6cf30ad2017-04-04 23:08:23 -0700178 app_evt_queue_size = options[APP_EVT_QUEUE_SIZE] > 0 ?
179 options[APP_EVT_QUEUE_SIZE] : default_app_evt_queue_size;
Dave Barach68b0fb02017-02-28 15:15:56 -0500180
Florin Coras6cf30ad2017-04-04 23:08:23 -0700181 /* Setup segment manager */
182 sm = segment_manager_new ();
183 sm->app_index = app->index;
184 props = &app->sm_properties;
185 props->add_segment_size = options[SESSION_OPTIONS_ADD_SEGMENT_SIZE];
186 props->rx_fifo_size = options[SESSION_OPTIONS_RX_FIFO_SIZE];
Florin Corasc87c91d2017-08-16 19:55:49 -0700187 props->rx_fifo_size =
188 props->rx_fifo_size ? props->rx_fifo_size : default_rx_fifo_size;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700189 props->tx_fifo_size = options[SESSION_OPTIONS_TX_FIFO_SIZE];
Florin Corasc87c91d2017-08-16 19:55:49 -0700190 props->tx_fifo_size =
191 props->tx_fifo_size ? props->tx_fifo_size : default_tx_fifo_size;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700192 props->add_segment = props->add_segment_size != 0;
Dave Barach10d8cc62017-05-30 09:30:07 -0400193 props->preallocated_fifo_pairs = options[APP_OPTIONS_PREALLOC_FIFO_PAIRS];
Florin Corasa5464812017-04-19 13:00:05 -0700194 props->use_private_segment = options[APP_OPTIONS_FLAGS]
195 & APP_OPTIONS_FLAGS_BUILTIN_APP;
Dave Barach2c25a622017-06-26 11:35:07 -0400196 props->private_segment_count = options[APP_OPTIONS_PRIVATE_SEGMENT_COUNT];
197 props->private_segment_size = options[APP_OPTIONS_PRIVATE_SEGMENT_SIZE];
Dave Barach68b0fb02017-02-28 15:15:56 -0500198
Florin Corasa5464812017-04-19 13:00:05 -0700199 first_seg_size = options[SESSION_OPTIONS_SEGMENT_SIZE];
200 if ((rv = segment_manager_init (sm, props, first_seg_size)))
Florin Coras6cf30ad2017-04-04 23:08:23 -0700201 return rv;
Florin Corasc87c91d2017-08-16 19:55:49 -0700202 sm->first_is_protected = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -0500203
Florin Coras6cf30ad2017-04-04 23:08:23 -0700204 app->first_segment_manager = segment_manager_index (sm);
Dave Barach68b0fb02017-02-28 15:15:56 -0500205 app->api_client_index = api_client_index;
Florin Corasa5464812017-04-19 13:00:05 -0700206 app->flags = options[APP_OPTIONS_FLAGS];
Dave Barach68b0fb02017-02-28 15:15:56 -0500207 app->cb_fns = *cb_fns;
208
Florin Corasa5464812017-04-19 13:00:05 -0700209 /* Allocate app event queue in the first shared-memory segment */
210 app->event_queue = segment_manager_alloc_queue (sm, app_evt_queue_size);
211
Florin Corasd79b41e2017-03-04 05:37:52 -0800212 /* Check that the obvious things are properly set up */
Florin Coras6cf30ad2017-04-04 23:08:23 -0700213 application_verify_cb_fns (cb_fns);
Florin Corasd79b41e2017-03-04 05:37:52 -0800214
Dave Barach68b0fb02017-02-28 15:15:56 -0500215 /* Add app to lookup by api_client_index table */
216 application_table_add (app);
217
Florin Coras6cf30ad2017-04-04 23:08:23 -0700218 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500219}
220
221application_t *
222application_get (u32 index)
223{
224 return pool_elt_at_index (app_pool, index);
225}
226
Florin Corase04c2992017-03-01 08:17:34 -0800227application_t *
228application_get_if_valid (u32 index)
229{
230 if (pool_is_free_index (app_pool, index))
231 return 0;
232
233 return pool_elt_at_index (app_pool, index);
234}
235
Dave Barach68b0fb02017-02-28 15:15:56 -0500236u32
237application_get_index (application_t * app)
238{
239 return app - app_pool;
240}
241
Florin Coras6cf30ad2017-04-04 23:08:23 -0700242static segment_manager_t *
243application_alloc_segment_manager (application_t * app)
Dave Barach68b0fb02017-02-28 15:15:56 -0500244{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700245 segment_manager_t *sm = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500246
Florin Corasc87c91d2017-08-16 19:55:49 -0700247 /* If the first segment manager is not in use, don't allocate a new one */
248 if (app->first_segment_manager != APP_INVALID_SEGMENT_MANAGER_INDEX
Florin Coras0e9c33b2017-08-14 22:33:41 -0700249 && app->first_segment_manager_in_use == 0)
Dave Barach68b0fb02017-02-28 15:15:56 -0500250 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700251 sm = segment_manager_get (app->first_segment_manager);
Florin Coras0e9c33b2017-08-14 22:33:41 -0700252 app->first_segment_manager_in_use = 1;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700253 return sm;
Dave Barach68b0fb02017-02-28 15:15:56 -0500254 }
255
Florin Coras6cf30ad2017-04-04 23:08:23 -0700256 sm = segment_manager_new ();
Florin Coras0e9c33b2017-08-14 22:33:41 -0700257 sm->properties = &app->sm_properties;
258
Florin Coras6cf30ad2017-04-04 23:08:23 -0700259 return sm;
260}
261
262/**
263 * Start listening local transport endpoint for requested transport.
264 *
265 * Creates a 'dummy' stream session with state LISTENING to be used in session
266 * lookups, prior to establishing connection. Requests transport to build
267 * it's own specific listening connection.
268 */
269int
270application_start_listen (application_t * srv, session_type_t session_type,
271 transport_endpoint_t * tep, u64 * res)
272{
273 segment_manager_t *sm;
274 stream_session_t *s;
275 u64 handle;
276
277 s = listen_session_new (session_type);
278 s->app_index = srv->index;
279
280 if (stream_session_listen (s, tep))
281 goto err;
282
283 /* Allocate segment manager. All sessions derived out of a listen session
284 * have fifos allocated by the same segment manager. */
285 sm = application_alloc_segment_manager (srv);
286 if (sm == 0)
287 goto err;
288
289 /* Add to app's listener table. Useful to find all child listeners
290 * when app goes down, although, just for unbinding this is not needed */
291 handle = listen_session_get_handle (s);
292 hash_set (srv->listeners_table, handle, segment_manager_index (sm));
293
294 *res = handle;
295 return 0;
296
297err:
298 listen_session_del (s);
299 return -1;
300}
301
302/**
303 * Stop listening on session associated to handle
304 */
305int
306application_stop_listen (application_t * srv, u64 handle)
307{
308 stream_session_t *listener;
309 uword *indexp;
310 segment_manager_t *sm;
311
312 if (srv && hash_get (srv->listeners_table, handle) == 0)
313 {
314 clib_warning ("app doesn't own handle %llu!", handle);
315 return -1;
316 }
317
318 listener = listen_session_get_from_handle (handle);
319 stream_session_stop_listen (listener);
320
321 indexp = hash_get (srv->listeners_table, handle);
322 ASSERT (indexp);
323
324 sm = segment_manager_get (*indexp);
Florin Coras0e9c33b2017-08-14 22:33:41 -0700325 if (srv->first_segment_manager == *indexp)
326 {
Florin Corasc87c91d2017-08-16 19:55:49 -0700327 /* Delete sessions but don't remove segment manager */
Florin Coras0e9c33b2017-08-14 22:33:41 -0700328 srv->first_segment_manager_in_use = 0;
Florin Corasc87c91d2017-08-16 19:55:49 -0700329 segment_manager_del_sessions (sm);
330 }
331 else
332 {
333 segment_manager_init_del (sm);
Florin Coras0e9c33b2017-08-14 22:33:41 -0700334 }
Florin Coras6cf30ad2017-04-04 23:08:23 -0700335 hash_unset (srv->listeners_table, handle);
336 listen_session_del (listener);
337
Dave Barach68b0fb02017-02-28 15:15:56 -0500338 return 0;
339}
340
Florin Coras6cf30ad2017-04-04 23:08:23 -0700341int
342application_open_session (application_t * app, session_type_t sst,
343 transport_endpoint_t * tep, u32 api_context)
Dave Barach68b0fb02017-02-28 15:15:56 -0500344{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700345 segment_manager_t *sm;
346 transport_connection_t *tc = 0;
347 int rv;
348
349 /* Make sure we have a segment manager for connects */
350 if (app->connects_seg_manager == (u32) ~ 0)
351 {
352 sm = application_alloc_segment_manager (app);
353 if (sm == 0)
354 return -1;
355 app->connects_seg_manager = segment_manager_index (sm);
356 }
357
358 if ((rv = stream_session_open (app->index, sst, tep, &tc)))
359 return rv;
360
361 /* Store api_context for when the reply comes. Not the nicest thing
Florin Corasab0289a2017-08-14 11:25:25 -0700362 * but better than allocating a separate half-open pool. */
Florin Coras6cf30ad2017-04-04 23:08:23 -0700363 tc->s_index = api_context;
364
365 return 0;
366}
367
368segment_manager_t *
369application_get_connect_segment_manager (application_t * app)
370{
371 ASSERT (app->connects_seg_manager != (u32) ~ 0);
372 return segment_manager_get (app->connects_seg_manager);
373}
374
375segment_manager_t *
376application_get_listen_segment_manager (application_t * app,
377 stream_session_t * s)
378{
379 uword *smp;
380 smp = hash_get (app->listeners_table, listen_session_get_handle (s));
381 ASSERT (smp != 0);
382 return segment_manager_get (*smp);
383}
384
385static u8 *
386app_get_name_from_reg_index (application_t * app)
387{
388 u8 *app_name;
389
Dave Barach68b0fb02017-02-28 15:15:56 -0500390 vl_api_registration_t *regp;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700391 regp = vl_api_client_index_to_registration (app->api_client_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500392 if (!regp)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700393 app_name = format (0, "builtin-%d%c", app->index, 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500394 else
Florin Coras6cf30ad2017-04-04 23:08:23 -0700395 app_name = format (0, "%s%c", regp->name, 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500396
Florin Coras6cf30ad2017-04-04 23:08:23 -0700397 return app_name;
Dave Barach68b0fb02017-02-28 15:15:56 -0500398}
399
Dave Barach52851e62017-08-07 09:35:25 -0400400int
401application_is_proxy (application_t * app)
402{
403 return !(app->flags & APP_OPTIONS_FLAGS_IS_PROXY);
404}
405
Florin Corasc87c91d2017-08-16 19:55:49 -0700406int
407application_add_segment_notify (u32 app_index, u32 fifo_segment_index)
408{
409 application_t *app = application_get (app_index);
410 u32 seg_size = 0;
411 u8 *seg_name;
412
413 /* Send an API message to the external app, to map new segment */
414 ASSERT (app->cb_fns.add_segment_callback);
415
416 segment_manager_get_segment_info (fifo_segment_index, &seg_name, &seg_size);
417 return app->cb_fns.add_segment_callback (app->api_client_index, seg_name,
418 seg_size);
419}
420
Dave Barach68b0fb02017-02-28 15:15:56 -0500421u8 *
Florin Coras6cf30ad2017-04-04 23:08:23 -0700422format_application_listener (u8 * s, va_list * args)
Dave Barach68b0fb02017-02-28 15:15:56 -0500423{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700424 application_t *app = va_arg (*args, application_t *);
425 u64 handle = va_arg (*args, u64);
426 u32 index = va_arg (*args, u32);
Dave Barach68b0fb02017-02-28 15:15:56 -0500427 int verbose = va_arg (*args, int);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700428 stream_session_t *listener;
429 u8 *app_name, *str;
Dave Barach68b0fb02017-02-28 15:15:56 -0500430
Florin Coras6cf30ad2017-04-04 23:08:23 -0700431 if (app == 0)
Dave Barach68b0fb02017-02-28 15:15:56 -0500432 {
433 if (verbose)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700434 s = format (s, "%-40s%-20s%-15s%-15s%-10s", "Connection", "App",
435 "API Client", "ListenerID", "SegManager");
Dave Barach68b0fb02017-02-28 15:15:56 -0500436 else
Florin Coras6cf30ad2017-04-04 23:08:23 -0700437 s = format (s, "%-40s%-20s", "Connection", "App");
Dave Barach68b0fb02017-02-28 15:15:56 -0500438
439 return s;
440 }
441
Florin Coras6cf30ad2017-04-04 23:08:23 -0700442 app_name = app_get_name_from_reg_index (app);
443 listener = listen_session_get_from_handle (handle);
444 str = format (0, "%U", format_stream_session, listener, verbose);
Dave Barach68b0fb02017-02-28 15:15:56 -0500445
Dave Barach68b0fb02017-02-28 15:15:56 -0500446 if (verbose)
447 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700448 s = format (s, "%-40s%-20s%-15u%-15u%-10u", str, app_name,
449 app->api_client_index, handle, index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500450 }
451 else
Florin Coras6cf30ad2017-04-04 23:08:23 -0700452 s = format (s, "%-40s%-20s", str, app_name);
453
454 vec_free (app_name);
455 return s;
456}
457
458void
459application_format_connects (application_t * app, int verbose)
460{
461 vlib_main_t *vm = vlib_get_main ();
462 segment_manager_t *sm;
463 u8 *app_name, *s = 0;
Dave Barach10d8cc62017-05-30 09:30:07 -0400464 int j;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700465
466 /* Header */
467 if (app == 0)
468 {
469 if (verbose)
470 vlib_cli_output (vm, "%-40s%-20s%-15s%-10s", "Connection", "App",
471 "API Client", "SegManager");
472 else
473 vlib_cli_output (vm, "%-40s%-20s", "Connection", "App");
474 return;
475 }
476
477 /* make sure */
478 if (app->connects_seg_manager == (u32) ~ 0)
479 return;
480
481 app_name = app_get_name_from_reg_index (app);
482
483 /* Across all fifo segments */
484 sm = segment_manager_get (app->connects_seg_manager);
485 for (j = 0; j < vec_len (sm->segment_indices); j++)
486 {
487 svm_fifo_segment_private_t *fifo_segment;
Dave Barach10d8cc62017-05-30 09:30:07 -0400488 svm_fifo_t *fifo;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700489 u8 *str;
490
Florin Corasc87c91d2017-08-16 19:55:49 -0700491 fifo_segment = svm_fifo_segment_get_segment (sm->segment_indices[j]);
Dave Barach10d8cc62017-05-30 09:30:07 -0400492 fifo = svm_fifo_segment_get_fifo_list (fifo_segment);
493 while (fifo)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700494 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700495 u32 session_index, thread_index;
496 stream_session_t *session;
497
Florin Corasa5464812017-04-19 13:00:05 -0700498 session_index = fifo->master_session_index;
499 thread_index = fifo->master_thread_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700500
501 session = stream_session_get (session_index, thread_index);
502 str = format (0, "%U", format_stream_session, session, verbose);
503
504 if (verbose)
505 s = format (s, "%-40s%-20s%-15u%-10u", str, app_name,
506 app->api_client_index, app->connects_seg_manager);
507 else
508 s = format (s, "%-40s%-20s", str, app_name);
509
510 vlib_cli_output (vm, "%v", s);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700511 vec_reset_length (s);
512 vec_free (str);
Dave Barach10d8cc62017-05-30 09:30:07 -0400513
514 fifo = fifo->next;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700515 }
516 vec_free (s);
517 }
518
519 vec_free (app_name);
520}
521
522u8 *
523format_application (u8 * s, va_list * args)
524{
525 application_t *app = va_arg (*args, application_t *);
526 CLIB_UNUSED (int verbose) = va_arg (*args, int);
527 u8 *app_name;
528
529 if (app == 0)
530 {
531 if (verbose)
532 s = format (s, "%-10s%-20s%-15s%-15s%-15s%-15s", "Index", "Name",
533 "API Client", "Add seg size", "Rx fifo size",
534 "Tx fifo size");
535 else
536 s = format (s, "%-10s%-20s%-20s", "Index", "Name", "API Client");
537 return s;
538 }
539
540 app_name = app_get_name_from_reg_index (app);
541 if (verbose)
542 s = format (s, "%-10d%-20s%-15d%-15d%-15d%-15d", app->index, app_name,
543 app->api_client_index, app->sm_properties.add_segment_size,
544 app->sm_properties.rx_fifo_size,
545 app->sm_properties.tx_fifo_size);
546 else
547 s = format (s, "%-10d%-20s%-20d", app->index, app_name,
548 app->api_client_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500549 return s;
550}
551
552static clib_error_t *
553show_app_command_fn (vlib_main_t * vm, unformat_input_t * input,
554 vlib_cli_command_t * cmd)
555{
556 application_t *app;
557 int do_server = 0;
558 int do_client = 0;
559 int verbose = 0;
560
Florin Coras6cf30ad2017-04-04 23:08:23 -0700561 if (!session_manager_is_enabled ())
Florin Corase04c2992017-03-01 08:17:34 -0800562 {
563 clib_error_return (0, "session layer is not enabled");
564 }
565
Dave Barach68b0fb02017-02-28 15:15:56 -0500566 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
567 {
568 if (unformat (input, "server"))
569 do_server = 1;
570 else if (unformat (input, "client"))
571 do_client = 1;
572 else if (unformat (input, "verbose"))
573 verbose = 1;
574 else
575 break;
576 }
577
578 if (do_server)
579 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700580 u64 handle;
581 u32 index;
Dave Barach68b0fb02017-02-28 15:15:56 -0500582 if (pool_elts (app_pool))
583 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700584 vlib_cli_output (vm, "%U", format_application_listener,
585 0 /* header */ , 0, 0,
Dave Barach68b0fb02017-02-28 15:15:56 -0500586 verbose);
587 /* *INDENT-OFF* */
588 pool_foreach (app, app_pool,
589 ({
Florin Coras6cf30ad2017-04-04 23:08:23 -0700590 /* App's listener sessions */
591 if (hash_elts (app->listeners_table) == 0)
592 continue;
593 hash_foreach (handle, index, app->listeners_table,
594 ({
595 vlib_cli_output (vm, "%U", format_application_listener, app,
596 handle, index, verbose);
597 }));
Dave Barach68b0fb02017-02-28 15:15:56 -0500598 }));
599 /* *INDENT-ON* */
600 }
601 else
602 vlib_cli_output (vm, "No active server bindings");
603 }
604
605 if (do_client)
606 {
607 if (pool_elts (app_pool))
608 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700609 application_format_connects (0, verbose);
610
Dave Barach68b0fb02017-02-28 15:15:56 -0500611 /* *INDENT-OFF* */
612 pool_foreach (app, app_pool,
613 ({
Florin Coras6cf30ad2017-04-04 23:08:23 -0700614 if (app->connects_seg_manager == (u32)~0)
615 continue;
616 application_format_connects (app, verbose);
Dave Barach68b0fb02017-02-28 15:15:56 -0500617 }));
618 /* *INDENT-ON* */
619 }
620 else
Florin Corase04c2992017-03-01 08:17:34 -0800621 vlib_cli_output (vm, "No active client bindings");
Dave Barach68b0fb02017-02-28 15:15:56 -0500622 }
623
Florin Coras6cf30ad2017-04-04 23:08:23 -0700624 /* Print app related info */
625 if (!do_server && !do_client)
626 {
627 vlib_cli_output (vm, "%U", format_application, 0, verbose);
628 pool_foreach (app, app_pool, (
629 {
630 vlib_cli_output (vm, "%U",
631 format_application, app,
632 verbose);
633 }
634 ));
635 }
636
Dave Barach68b0fb02017-02-28 15:15:56 -0500637 return 0;
638}
639
Florin Corase04c2992017-03-01 08:17:34 -0800640/* *INDENT-OFF* */
Dave Barach68b0fb02017-02-28 15:15:56 -0500641VLIB_CLI_COMMAND (show_app_command, static) =
642{
Florin Corase04c2992017-03-01 08:17:34 -0800643 .path = "show app",
644 .short_help = "show app [server|client] [verbose]",
645 .function = show_app_command_fn,
646};
647/* *INDENT-ON* */
Dave Barach68b0fb02017-02-28 15:15:56 -0500648
649/*
650 * fd.io coding-style-patch-verification: ON
651 *
652 * Local Variables:
653 * eval: (c-set-style "gnu")
654 * End:
655 */