blob: 3bf722b81a04835889870ee0d92128a3c4b51b4c [file] [log] [blame]
Dave Barach68b0fb02017-02-28 15:15:56 -05001/*
Florin Coras288eaab2019-02-03 15:26:14 -08002 * Copyright (c) 2017-2019 Cisco and/or its affiliates.
Dave Barach68b0fb02017-02-28 15:15:56 -05003 * 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 Corasc1a42652019-02-08 18:27:29 -080023#define app_interface_check_thread_and_barrier(_fn, _arg) \
24 if (PREDICT_FALSE (!vlib_thread_is_main_w_barrier ())) \
25 { \
26 vlib_rpc_call_main_thread (_fn, (u8 *) _arg, sizeof(*_arg)); \
27 return 0; \
28 }
29
Florin Corasc9940fc2019-02-05 20:55:11 -080030static void
31application_local_listener_session_endpoint (local_session_t * ll,
32 session_endpoint_t * sep)
33{
34 sep->transport_proto =
35 session_type_transport_proto (ll->listener_session_type);
36 sep->port = ll->port;
37 sep->is_ip4 = ll->listener_session_type & 1;
38}
39
Florin Corasab2f6db2018-08-31 14:31:41 -070040static app_listener_t *
41app_listener_alloc (application_t * app)
42{
43 app_listener_t *app_listener;
44 pool_get (app->listeners, app_listener);
Dave Barachb7b92992018-10-17 10:38:51 -040045 clib_memset (app_listener, 0, sizeof (*app_listener));
Florin Corasab2f6db2018-08-31 14:31:41 -070046 app_listener->al_index = app_listener - app->listeners;
Florin Corasc9940fc2019-02-05 20:55:11 -080047 app_listener->app_index = app->app_index;
48 app_listener->session_index = SESSION_INVALID_INDEX;
49 app_listener->local_index = SESSION_INVALID_INDEX;
Florin Corasab2f6db2018-08-31 14:31:41 -070050 return app_listener;
51}
52
Florin Corasc9940fc2019-02-05 20:55:11 -080053app_listener_t *
Florin Corasab2f6db2018-08-31 14:31:41 -070054app_listener_get (application_t * app, u32 app_listener_index)
55{
56 return pool_elt_at_index (app->listeners, app_listener_index);
57}
58
59static void
60app_listener_free (application_t * app, app_listener_t * app_listener)
61{
62 clib_bitmap_free (app_listener->workers);
63 pool_put (app->listeners, app_listener);
64 if (CLIB_DEBUG)
Dave Barachb7b92992018-10-17 10:38:51 -040065 clib_memset (app_listener, 0xfa, sizeof (*app_listener));
Florin Corasab2f6db2018-08-31 14:31:41 -070066}
67
Florin Corasc9940fc2019-02-05 20:55:11 -080068local_session_t *
69application_local_listen_session_alloc (application_t * app)
Florin Corasab2f6db2018-08-31 14:31:41 -070070{
Florin Corasc9940fc2019-02-05 20:55:11 -080071 local_session_t *ll;
72 pool_get_zero (app->local_listen_sessions, ll);
73 ll->session_index = ll - app->local_listen_sessions;
74 ll->session_type = session_type_from_proto_and_ip (TRANSPORT_PROTO_NONE, 0);
75 ll->app_index = app->app_index;
Florin Coras222e1f412019-02-16 20:47:32 -080076 ll->session_state = SESSION_STATE_LISTENING;
Florin Corasc9940fc2019-02-05 20:55:11 -080077 return ll;
Florin Corasab2f6db2018-08-31 14:31:41 -070078}
79
Florin Corasc9940fc2019-02-05 20:55:11 -080080void
81application_local_listen_session_free (application_t * app,
82 local_session_t * ll)
Florin Corasab2f6db2018-08-31 14:31:41 -070083{
Florin Corasc9940fc2019-02-05 20:55:11 -080084 pool_put (app->local_listen_sessions, ll);
85 if (CLIB_DEBUG)
86 clib_memset (ll, 0xfb, sizeof (*ll));
87}
88
89static u32
90app_listener_id (app_listener_t * al)
91{
92 ASSERT (al->app_index < 1 << 16 && al->al_index < 1 << 16);
93 return (al->app_index << 16 | al->al_index);
94}
95
96session_handle_t
97app_listener_handle (app_listener_t * al)
98{
99 return ((u64) SESSION_LISTENER_PREFIX << 32 | (u64) app_listener_id (al));
Florin Corasab2f6db2018-08-31 14:31:41 -0700100}
101
102static void
Florin Corasc9940fc2019-02-05 20:55:11 -0800103app_listener_id_parse (u32 listener_id, u32 * app_index,
104 u32 * app_listener_index)
Florin Corasab2f6db2018-08-31 14:31:41 -0700105{
Florin Corasc9940fc2019-02-05 20:55:11 -0800106 *app_index = listener_id >> 16;
107 *app_listener_index = listener_id & 0xFFFF;
108}
109
110void
111app_listener_handle_parse (session_handle_t handle, u32 * app_index,
112 u32 * app_listener_index)
113{
114 app_listener_id_parse (handle & 0xFFFFFFFF, app_index, app_listener_index);
115}
116
117static app_listener_t *
118app_listener_get_w_id (u32 listener_id)
119{
120 u32 app_index, app_listener_index;
121 application_t *app;
122
123 app_listener_id_parse (listener_id, &app_index, &app_listener_index);
124 app = application_get_if_valid (app_index);
125 if (!app)
126 return 0;
127 return app_listener_get (app, app_listener_index);
128}
129
130app_listener_t *
131app_listener_get_w_session (session_t * ls)
132{
133 application_t *app;
134
135 app = application_get_if_valid (ls->app_index);
136 if (!app)
137 return 0;
138 return app_listener_get (app, ls->al_index);
139}
140
141app_listener_t *
142app_listener_get_w_handle (session_handle_t handle)
143{
144
145 if (handle >> 32 != SESSION_LISTENER_PREFIX)
146 return 0;
147
148 return app_listener_get_w_id (handle & 0xFFFFFFFF);
149}
150
151app_listener_t *
152app_listener_lookup (application_t * app, session_endpoint_cfg_t * sep_ext)
153{
154 u32 table_index, fib_proto;
155 session_endpoint_t *sep;
156 session_handle_t handle;
157 local_session_t *ll;
158 session_t *ls;
159
160 sep = (session_endpoint_t *) sep_ext;
161 if (application_has_local_scope (app) && session_endpoint_is_local (sep))
162 {
163 table_index = application_local_session_table (app);
164 handle = session_lookup_endpoint_listener (table_index, sep, 1);
165 if (handle != SESSION_INVALID_HANDLE)
166 {
167 ll = application_get_local_listener_w_handle (handle);
168 return app_listener_get_w_session ((session_t *) ll);
169 }
170 }
171
172 fib_proto = session_endpoint_fib_proto (sep);
173 table_index = application_session_table (app, fib_proto);
174 handle = session_lookup_endpoint_listener (table_index, sep, 1);
175 if (handle != SESSION_INVALID_HANDLE)
176 {
177 ls = listen_session_get_from_handle (handle);
178 return app_listener_get_w_session ((session_t *) ls);
179 }
180
181 return 0;
182}
183
184int
185app_listener_alloc_and_init (application_t * app,
186 session_endpoint_cfg_t * sep,
187 app_listener_t ** listener)
188{
189 app_listener_t *app_listener;
190 local_session_t *ll = 0;
191 session_handle_t lh;
192 session_type_t st;
193 session_t *ls = 0;
Florin Corasa27a46e2019-02-18 13:02:28 -0800194 u32 al_index;
Florin Corasc9940fc2019-02-05 20:55:11 -0800195 int rv;
196
197 app_listener = app_listener_alloc (app);
Florin Corasa27a46e2019-02-18 13:02:28 -0800198 al_index = app_listener->al_index;
Florin Corasc9940fc2019-02-05 20:55:11 -0800199 st = session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4);
200
201 /*
202 * Add session endpoint to local session table. Only binds to "inaddr_any"
203 * (i.e., zero address) are added to local scope table.
204 */
205 if (application_has_local_scope (app)
206 && session_endpoint_is_local ((session_endpoint_t *) sep))
207 {
208 u32 table_index;
209
210 ll = application_local_listen_session_alloc (app);
211 ll->port = sep->port;
212 /* Store the original session type for the unbind */
213 ll->listener_session_type = st;
214 table_index = application_local_session_table (app);
215 lh = application_local_session_handle (ll);
216 session_lookup_add_session_endpoint (table_index,
217 (session_endpoint_t *) sep, lh);
218 app_listener->local_index = ll->session_index;
219 ll->al_index = app_listener->al_index;
220 }
221
222 if (application_has_global_scope (app))
223 {
224 /*
225 * Start listening on local endpoint for requested transport and scope.
226 * Creates a stream session with state LISTENING to be used in session
227 * lookups, prior to establishing connection. Requests transport to
228 * build it's own specific listening connection.
229 */
230 ls = listen_session_new (0, st);
231 ls->app_index = app->app_index;
232 ls->app_wrk_index = sep->app_wrk_index;
233
234 /* Listen pool can be reallocated if the transport is
235 * recursive (tls) */
236 lh = session_handle (ls);
237
238 if ((rv = session_listen (ls, sep)))
239 {
240 ls = session_get_from_handle (lh);
241 session_free (ls);
242 return rv;
243 }
Florin Corasa27a46e2019-02-18 13:02:28 -0800244 ls = session_get_from_handle (lh);
245 app_listener = app_listener_get (app, al_index);
Florin Corasc9940fc2019-02-05 20:55:11 -0800246 app_listener->session_index = ls->session_index;
Florin Corasa27a46e2019-02-18 13:02:28 -0800247 ls->al_index = al_index;
Florin Corasc9940fc2019-02-05 20:55:11 -0800248 }
249
250 if (!ll && !ls)
251 {
252 app_listener_free (app, app_listener);
253 return -1;
254 }
255
256 *listener = app_listener;
257 return 0;
258}
259
260void
261app_listener_cleanup (app_listener_t * al)
262{
263 application_t *app = application_get (al->app_index);
264
265 if (al->session_index != SESSION_INVALID_INDEX)
266 {
267 session_t *ls = session_get (al->session_index, 0);
268 session_stop_listen (ls);
269 listen_session_del (ls);
270 }
271 if (al->local_index != SESSION_INVALID_INDEX)
272 {
273 session_endpoint_t sep = SESSION_ENDPOINT_NULL;
274 local_session_t *ll;
275 u32 table_index;
276
277 table_index = application_local_session_table (app);
278 ll = application_get_local_listen_session (app, al->local_index);
279 application_local_listener_session_endpoint (ll, &sep);
280 session_lookup_del_session_endpoint (table_index, &sep);
281 application_local_listen_session_free (app, ll);
282 }
283 app_listener_free (app, al);
284}
285
286app_worker_t *
287app_listener_select_worker (app_listener_t * al)
288{
289 application_t *app;
290 u32 wrk_index;
291
292 app = application_get (al->app_index);
293 wrk_index = clib_bitmap_next_set (al->workers, al->accept_rotor + 1);
294 if (wrk_index == ~0)
295 wrk_index = clib_bitmap_first_set (al->workers);
296
297 ASSERT (wrk_index != ~0);
298 al->accept_rotor = wrk_index;
299 return application_get_worker (app, wrk_index);
300}
301
302session_t *
303app_listener_get_session (app_listener_t * al)
304{
305 if (al->session_index == SESSION_INVALID_INDEX)
306 return 0;
307
308 return listen_session_get (al->session_index);
Florin Corasab2f6db2018-08-31 14:31:41 -0700309}
310
Florin Coras15531972018-08-12 23:50:53 -0700311static app_worker_map_t *
312app_worker_map_alloc (application_t * app)
313{
314 app_worker_map_t *map;
315 pool_get (app->worker_maps, map);
Dave Barachb7b92992018-10-17 10:38:51 -0400316 clib_memset (map, 0, sizeof (*map));
Florin Coras15531972018-08-12 23:50:53 -0700317 return map;
318}
Dave Barach68b0fb02017-02-28 15:15:56 -0500319
Florin Coras15531972018-08-12 23:50:53 -0700320static u32
321app_worker_map_index (application_t * app, app_worker_map_t * map)
322{
323 return (map - app->worker_maps);
324}
325
326static void
327app_worker_map_free (application_t * app, app_worker_map_t * map)
328{
329 pool_put (app->worker_maps, map);
330}
331
332static app_worker_map_t *
333app_worker_map_get (application_t * app, u32 map_index)
334{
Florin Coras01f3f892018-12-02 12:45:53 -0800335 if (pool_is_free_index (app->worker_maps, map_index))
336 return 0;
Florin Coras15531972018-08-12 23:50:53 -0700337 return pool_elt_at_index (app->worker_maps, map_index);
338}
Florin Coras0bee9ce2018-03-22 21:24:31 -0700339
Florin Coras053a0e42018-11-13 15:52:38 -0800340static const u8 *
Florin Coras0bee9ce2018-03-22 21:24:31 -0700341app_get_name (application_t * app)
342{
Florin Coras0bee9ce2018-03-22 21:24:31 -0700343 return app->name;
344}
345
Florin Corascea194d2017-10-02 00:18:51 -0700346u32
347application_session_table (application_t * app, u8 fib_proto)
348{
349 app_namespace_t *app_ns;
350 app_ns = app_namespace_get (app->ns_index);
351 if (!application_has_global_scope (app))
352 return APP_INVALID_INDEX;
353 if (fib_proto == FIB_PROTOCOL_IP4)
354 return session_lookup_get_index_for_fib (fib_proto,
355 app_ns->ip4_fib_index);
356 else
357 return session_lookup_get_index_for_fib (fib_proto,
358 app_ns->ip6_fib_index);
359}
360
361u32
362application_local_session_table (application_t * app)
363{
364 app_namespace_t *app_ns;
365 if (!application_has_local_scope (app))
366 return APP_INVALID_INDEX;
367 app_ns = app_namespace_get (app->ns_index);
368 return app_ns->local_table_index;
369}
370
Florin Corascea194d2017-10-02 00:18:51 -0700371/**
Florin Coras053a0e42018-11-13 15:52:38 -0800372 * Returns app name for app-index
Florin Corascea194d2017-10-02 00:18:51 -0700373 */
Florin Coras053a0e42018-11-13 15:52:38 -0800374const u8 *
Florin Corascea194d2017-10-02 00:18:51 -0700375application_name_from_index (u32 app_index)
376{
377 application_t *app = application_get (app_index);
378 if (!app)
379 return 0;
Florin Coras053a0e42018-11-13 15:52:38 -0800380 return app_get_name (app);
381}
382
383static void
384application_api_table_add (u32 app_index, u32 api_client_index)
385{
Florin Corasc1f5a432018-11-20 11:31:26 -0800386 if (api_client_index != APP_INVALID_INDEX)
387 hash_set (app_main.app_by_api_client_index, api_client_index, app_index);
Florin Coras053a0e42018-11-13 15:52:38 -0800388}
389
390static void
391application_api_table_del (u32 api_client_index)
392{
393 hash_unset (app_main.app_by_api_client_index, api_client_index);
Florin Corascea194d2017-10-02 00:18:51 -0700394}
395
Dave Barach68b0fb02017-02-28 15:15:56 -0500396static void
Florin Corasc1f5a432018-11-20 11:31:26 -0800397application_name_table_add (application_t * app)
Dave Barach68b0fb02017-02-28 15:15:56 -0500398{
Florin Corasc1f5a432018-11-20 11:31:26 -0800399 hash_set_mem (app_main.app_by_name, app->name, app->app_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500400}
401
402static void
Florin Corasc1f5a432018-11-20 11:31:26 -0800403application_name_table_del (application_t * app)
Dave Barach68b0fb02017-02-28 15:15:56 -0500404{
Florin Corasc1f5a432018-11-20 11:31:26 -0800405 hash_unset_mem (app_main.app_by_name, app->name);
Dave Barach68b0fb02017-02-28 15:15:56 -0500406}
407
408application_t *
409application_lookup (u32 api_client_index)
410{
411 uword *p;
Florin Coras15531972018-08-12 23:50:53 -0700412 p = hash_get (app_main.app_by_api_client_index, api_client_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500413 if (p)
Florin Coras053a0e42018-11-13 15:52:38 -0800414 return application_get_if_valid (p[0]);
Dave Barach68b0fb02017-02-28 15:15:56 -0500415
416 return 0;
417}
418
Florin Coras6cf30ad2017-04-04 23:08:23 -0700419application_t *
Florin Coras0bee9ce2018-03-22 21:24:31 -0700420application_lookup_name (const u8 * name)
421{
422 uword *p;
Florin Coras15531972018-08-12 23:50:53 -0700423 p = hash_get_mem (app_main.app_by_name, name);
Florin Coras0bee9ce2018-03-22 21:24:31 -0700424 if (p)
425 return application_get (p[0]);
426
427 return 0;
428}
429
Florin Corasc1a42652019-02-08 18:27:29 -0800430static application_t *
Florin Coras15531972018-08-12 23:50:53 -0700431application_alloc (void)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700432{
433 application_t *app;
Florin Coras15531972018-08-12 23:50:53 -0700434 pool_get (app_main.app_pool, app);
Dave Barachb7b92992018-10-17 10:38:51 -0400435 clib_memset (app, 0, sizeof (*app));
Florin Coras15531972018-08-12 23:50:53 -0700436 app->app_index = app - app_main.app_pool;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700437 return app;
438}
439
Florin Coras15531972018-08-12 23:50:53 -0700440application_t *
441application_get (u32 app_index)
Dave Barach68b0fb02017-02-28 15:15:56 -0500442{
Florin Coras15531972018-08-12 23:50:53 -0700443 if (app_index == APP_INVALID_INDEX)
444 return 0;
445 return pool_elt_at_index (app_main.app_pool, app_index);
446}
Dave Barach68b0fb02017-02-28 15:15:56 -0500447
Florin Coras15531972018-08-12 23:50:53 -0700448application_t *
449application_get_if_valid (u32 app_index)
450{
451 if (pool_is_free_index (app_main.app_pool, app_index))
452 return 0;
Florin Corasa5464812017-04-19 13:00:05 -0700453
Florin Coras15531972018-08-12 23:50:53 -0700454 return pool_elt_at_index (app_main.app_pool, app_index);
455}
Florin Coras7999e832017-10-31 01:51:04 -0700456
Florin Corasd79b41e2017-03-04 05:37:52 -0800457static void
Florin Coras6cf30ad2017-04-04 23:08:23 -0700458application_verify_cb_fns (session_cb_vft_t * cb_fns)
Florin Corasd79b41e2017-03-04 05:37:52 -0800459{
Florin Coras6cf30ad2017-04-04 23:08:23 -0700460 if (cb_fns->session_accept_callback == 0)
Florin Corasd79b41e2017-03-04 05:37:52 -0800461 clib_warning ("No accept callback function provided");
Florin Coras6cf30ad2017-04-04 23:08:23 -0700462 if (cb_fns->session_connected_callback == 0)
Florin Corasd79b41e2017-03-04 05:37:52 -0800463 clib_warning ("No session connected callback function provided");
464 if (cb_fns->session_disconnect_callback == 0)
465 clib_warning ("No session disconnect callback function provided");
466 if (cb_fns->session_reset_callback == 0)
467 clib_warning ("No session reset callback function provided");
468}
469
Florin Corasb384b542018-01-15 01:08:33 -0800470/**
471 * Check app config for given segment type
472 *
473 * Returns 1 on success and 0 otherwise
474 */
475static u8
476application_verify_cfg (ssvm_segment_type_t st)
477{
478 u8 is_valid;
479 if (st == SSVM_SEGMENT_MEMFD)
480 {
481 is_valid = (session_manager_get_evt_q_segment () != 0);
482 if (!is_valid)
483 clib_warning ("memfd seg: vpp's event qs IN binary api svm region");
484 return is_valid;
485 }
486 else if (st == SSVM_SEGMENT_SHM)
487 {
488 is_valid = (session_manager_get_evt_q_segment () == 0);
489 if (!is_valid)
490 clib_warning ("shm seg: vpp's event qs NOT IN binary api svm region");
491 return is_valid;
492 }
493 else
494 return 1;
495}
496
Florin Corasc1a42652019-02-08 18:27:29 -0800497static int
Florin Coras15531972018-08-12 23:50:53 -0700498application_alloc_and_init (app_init_args_t * a)
Dave Barach68b0fb02017-02-28 15:15:56 -0500499{
Florin Corasa332c462018-01-31 06:52:17 -0800500 ssvm_segment_type_t seg_type = SSVM_SEGMENT_MEMFD;
Florin Corasb384b542018-01-15 01:08:33 -0800501 segment_manager_properties_t *props;
502 vl_api_registration_t *reg;
Florin Coras15531972018-08-12 23:50:53 -0700503 application_t *app;
504 u64 *options;
Dave Barach68b0fb02017-02-28 15:15:56 -0500505
Florin Coras15531972018-08-12 23:50:53 -0700506 app = application_alloc ();
507 options = a->options;
Florin Corasb384b542018-01-15 01:08:33 -0800508 /*
509 * Make sure we support the requested configuration
510 */
Florin Corasa332c462018-01-31 06:52:17 -0800511 if (!(options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_IS_BUILTIN))
512 {
Florin Coras15531972018-08-12 23:50:53 -0700513 reg = vl_api_client_index_to_registration (a->api_client_index);
Florin Corasa332c462018-01-31 06:52:17 -0800514 if (!reg)
515 return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
516 if (vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
517 seg_type = SSVM_SEGMENT_SHM;
518 }
519 else
520 {
Florin Coras99368312018-08-02 10:45:44 -0700521 if (options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
522 {
523 clib_warning ("mq eventfds can only be used if socket transport is "
524 "used for api");
525 return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
526 }
Florin Corasa332c462018-01-31 06:52:17 -0800527 seg_type = SSVM_SEGMENT_PRIVATE;
528 }
Florin Corasb384b542018-01-15 01:08:33 -0800529
Florin Corasa332c462018-01-31 06:52:17 -0800530 if (!application_verify_cfg (seg_type))
Florin Corasb384b542018-01-15 01:08:33 -0800531 return VNET_API_ERROR_APP_UNSUPPORTED_CFG;
Dave Barach68b0fb02017-02-28 15:15:56 -0500532
Florin Coras15531972018-08-12 23:50:53 -0700533 /* Check that the obvious things are properly set up */
534 application_verify_cb_fns (a->session_cb_vft);
535
Florin Coras15531972018-08-12 23:50:53 -0700536 app->flags = options[APP_OPTIONS_FLAGS];
537 app->cb_fns = *a->session_cb_vft;
538 app->ns_index = options[APP_OPTIONS_NAMESPACE];
539 app->proxied_transports = options[APP_OPTIONS_PROXY_TRANSPORT];
540 app->name = vec_dup (a->name);
541
542 /* If no scope enabled, default to global */
543 if (!application_has_global_scope (app)
544 && !application_has_local_scope (app))
545 app->flags |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
546
Florin Corasa332c462018-01-31 06:52:17 -0800547 props = application_segment_manager_properties (app);
548 segment_manager_properties_init (props);
Florin Coras15531972018-08-12 23:50:53 -0700549 props->segment_size = options[APP_OPTIONS_ADD_SEGMENT_SIZE];
550 props->prealloc_fifos = options[APP_OPTIONS_PREALLOC_FIFO_PAIRS];
Florin Corasb384b542018-01-15 01:08:33 -0800551 if (options[APP_OPTIONS_ADD_SEGMENT_SIZE])
552 {
553 props->add_segment_size = options[APP_OPTIONS_ADD_SEGMENT_SIZE];
554 props->add_segment = 1;
555 }
556 if (options[APP_OPTIONS_RX_FIFO_SIZE])
557 props->rx_fifo_size = options[APP_OPTIONS_RX_FIFO_SIZE];
558 if (options[APP_OPTIONS_TX_FIFO_SIZE])
559 props->tx_fifo_size = options[APP_OPTIONS_TX_FIFO_SIZE];
Florin Corasf8f516a2018-02-08 15:10:09 -0800560 if (options[APP_OPTIONS_EVT_QUEUE_SIZE])
561 props->evt_q_size = options[APP_OPTIONS_EVT_QUEUE_SIZE];
Florin Coras99368312018-08-02 10:45:44 -0700562 if (options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
563 props->use_mq_eventfd = 1;
Florin Coras58d36f02018-03-09 13:05:53 -0800564 if (options[APP_OPTIONS_TLS_ENGINE])
565 app->tls_engine = options[APP_OPTIONS_TLS_ENGINE];
Florin Corasa332c462018-01-31 06:52:17 -0800566 props->segment_type = seg_type;
Dave Barach68b0fb02017-02-28 15:15:56 -0500567
Florin Coras15531972018-08-12 23:50:53 -0700568 /* Add app to lookup by api_client_index table */
Florin Corasc1f5a432018-11-20 11:31:26 -0800569 if (!application_is_builtin (app))
570 application_api_table_add (app->app_index, a->api_client_index);
571 else
572 application_name_table_add (app);
573
574 a->app_index = app->app_index;
Florin Corasa332c462018-01-31 06:52:17 -0800575
Florin Coras15531972018-08-12 23:50:53 -0700576 APP_DBG ("New app name: %v api index: %u index %u", app->name,
577 app->api_client_index, app->app_index);
578
579 return 0;
580}
581
Florin Corasc1a42652019-02-08 18:27:29 -0800582static void
Florin Coras15531972018-08-12 23:50:53 -0700583application_free (application_t * app)
584{
585 app_worker_map_t *wrk_map;
586 app_worker_t *app_wrk;
Florin Corasab2f6db2018-08-31 14:31:41 -0700587 u32 table_index;
588 local_session_t *ll;
589 session_endpoint_t sep;
Florin Coras15531972018-08-12 23:50:53 -0700590
591 /*
592 * The app event queue allocated in first segment is cleared with
593 * the segment manager. No need to explicitly free it.
594 */
595 APP_DBG ("Delete app name %v api index: %d index: %d", app->name,
596 app->api_client_index, app->app_index);
597
598 if (application_is_proxy (app))
599 application_remove_proxy (app);
600
Florin Corasab2f6db2018-08-31 14:31:41 -0700601 /*
602 * Free workers
603 */
604
Florin Coras15531972018-08-12 23:50:53 -0700605 /* *INDENT-OFF* */
606 pool_flush (wrk_map, app->worker_maps, ({
607 app_wrk = app_worker_get (wrk_map->wrk_index);
608 app_worker_free (app_wrk);
609 }));
610 /* *INDENT-ON* */
611 pool_free (app->worker_maps);
612
Florin Corasab2f6db2018-08-31 14:31:41 -0700613 /*
614 * Free local listeners. Global table unbinds stop local listeners
615 * as well, but if we have only local binds, these won't be cleaned up.
616 * Don't bother with local accepted sessions, we clean them when
617 * cleaning up the worker.
618 */
619 table_index = application_local_session_table (app);
620 /* *INDENT-OFF* */
621 pool_foreach (ll, app->local_listen_sessions, ({
622 application_local_listener_session_endpoint (ll, &sep);
623 session_lookup_del_session_endpoint (table_index, &sep);
624 }));
625 /* *INDENT-ON* */
626 pool_free (app->local_listen_sessions);
627
628 /*
629 * Cleanup remaining state
630 */
Florin Corasc1f5a432018-11-20 11:31:26 -0800631 if (application_is_builtin (app))
632 application_name_table_del (app);
Florin Coras15531972018-08-12 23:50:53 -0700633 vec_free (app->name);
634 vec_free (app->tls_cert);
635 vec_free (app->tls_key);
636 pool_put (app_main.app_pool, app);
637}
638
Florin Corasc1a42652019-02-08 18:27:29 -0800639static void
Florin Coras053a0e42018-11-13 15:52:38 -0800640application_detach_process (application_t * app, u32 api_client_index)
641{
642 vnet_app_worker_add_del_args_t _args = { 0 }, *args = &_args;
643 app_worker_map_t *wrk_map;
644 u32 *wrks = 0, *wrk_index;
645 app_worker_t *app_wrk;
646
647 if (api_client_index == ~0)
648 {
649 application_free (app);
650 return;
651 }
652
653 APP_DBG ("Detaching for app %v index %u api client index %u", app->name,
654 app->app_index, app->api_client_index);
655
656 /* *INDENT-OFF* */
657 pool_foreach (wrk_map, app->worker_maps, ({
658 app_wrk = app_worker_get (wrk_map->wrk_index);
Florin Corasc1f5a432018-11-20 11:31:26 -0800659 if (app_wrk->api_client_index == api_client_index)
Florin Coras053a0e42018-11-13 15:52:38 -0800660 vec_add1 (wrks, app_wrk->wrk_index);
661 }));
662 /* *INDENT-ON* */
663
664 if (!vec_len (wrks))
665 {
666 clib_warning ("no workers for app %u api_index %u", app->app_index,
667 api_client_index);
668 return;
669 }
670
671 args->app_index = app->app_index;
Florin Corasc1f5a432018-11-20 11:31:26 -0800672 args->api_client_index = api_client_index;
Florin Coras053a0e42018-11-13 15:52:38 -0800673 vec_foreach (wrk_index, wrks)
674 {
675 app_wrk = app_worker_get (wrk_index[0]);
Florin Coras349f8ca2018-11-20 16:52:49 -0800676 args->wrk_map_index = app_wrk->wrk_map_index;
Florin Coras053a0e42018-11-13 15:52:38 -0800677 args->is_add = 0;
678 vnet_app_worker_add_del (args);
679 }
680 vec_free (wrks);
681}
682
Florin Coras15531972018-08-12 23:50:53 -0700683app_worker_t *
684application_get_worker (application_t * app, u32 wrk_map_index)
685{
686 app_worker_map_t *map;
687 map = app_worker_map_get (app, wrk_map_index);
688 if (!map)
689 return 0;
690 return app_worker_get (map->wrk_index);
691}
692
693app_worker_t *
694application_get_default_worker (application_t * app)
695{
696 return application_get_worker (app, 0);
697}
698
Florin Coras053a0e42018-11-13 15:52:38 -0800699u32
700application_n_workers (application_t * app)
701{
702 return pool_elts (app->worker_maps);
703}
704
Florin Coras15531972018-08-12 23:50:53 -0700705app_worker_t *
Florin Corasc9940fc2019-02-05 20:55:11 -0800706application_listener_select_worker (session_t * ls)
Florin Corasab2f6db2018-08-31 14:31:41 -0700707{
Florin Corasc9940fc2019-02-05 20:55:11 -0800708 app_listener_t *al;
Florin Corasab2f6db2018-08-31 14:31:41 -0700709
Florin Corasc9940fc2019-02-05 20:55:11 -0800710 al = app_listener_get_w_session (ls);
711 return app_listener_select_worker (al);
Florin Corasab2f6db2018-08-31 14:31:41 -0700712}
713
Florin Coras15531972018-08-12 23:50:53 -0700714int
Florin Coras623eb562019-02-03 19:28:34 -0800715application_alloc_worker_and_init (application_t * app, app_worker_t ** wrk)
Florin Coras15531972018-08-12 23:50:53 -0700716{
717 app_worker_map_t *wrk_map;
718 app_worker_t *app_wrk;
719 segment_manager_t *sm;
720 int rv;
721
722 app_wrk = app_worker_alloc (app);
723 wrk_map = app_worker_map_alloc (app);
724 wrk_map->wrk_index = app_wrk->wrk_index;
725 app_wrk->wrk_map_index = app_worker_map_index (app, wrk_map);
726
727 /*
728 * Setup first segment manager
729 */
730 sm = segment_manager_new ();
731 sm->app_wrk_index = app_wrk->wrk_index;
732
733 if ((rv = segment_manager_init (sm, app->sm_properties.segment_size,
734 app->sm_properties.prealloc_fifos)))
735 {
736 app_worker_free (app_wrk);
737 return rv;
738 }
Florin Corasc87c91d2017-08-16 19:55:49 -0700739 sm->first_is_protected = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -0500740
Florin Corascea194d2017-10-02 00:18:51 -0700741 /*
Florin Coras15531972018-08-12 23:50:53 -0700742 * Setup app worker
Florin Corascea194d2017-10-02 00:18:51 -0700743 */
Florin Coras15531972018-08-12 23:50:53 -0700744 app_wrk->first_segment_manager = segment_manager_index (sm);
745 app_wrk->listeners_table = hash_create (0, sizeof (u64));
746 app_wrk->event_queue = segment_manager_event_queue (sm);
747 app_wrk->app_is_builtin = application_is_builtin (app);
Dave Barach68b0fb02017-02-28 15:15:56 -0500748
Florin Corasf8f516a2018-02-08 15:10:09 -0800749 /*
750 * Segment manager for local sessions
751 */
752 sm = segment_manager_new ();
Florin Coras15531972018-08-12 23:50:53 -0700753 sm->app_wrk_index = app_wrk->wrk_index;
754 app_wrk->local_segment_manager = segment_manager_index (sm);
755 app_wrk->local_connects = hash_create (0, sizeof (u64));
756
757 *wrk = app_wrk;
Florin Corasf8f516a2018-02-08 15:10:09 -0800758
Florin Coras6cf30ad2017-04-04 23:08:23 -0700759 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500760}
761
Florin Coras623eb562019-02-03 19:28:34 -0800762int
Florin Corasc1a42652019-02-08 18:27:29 -0800763vnet_app_worker_add_del (vnet_app_worker_add_del_args_t * a)
764{
765 svm_fifo_segment_private_t *fs;
766 app_worker_map_t *wrk_map;
767 app_worker_t *app_wrk;
768 segment_manager_t *sm;
769 application_t *app;
770 int rv;
771
772 app = application_get (a->app_index);
773 if (!app)
774 return VNET_API_ERROR_INVALID_VALUE;
775
776 if (a->is_add)
777 {
778 if ((rv = application_alloc_worker_and_init (app, &app_wrk)))
779 return rv;
780
781 /* Map worker api index to the app */
782 app_wrk->api_client_index = a->api_client_index;
783 application_api_table_add (app->app_index, a->api_client_index);
784
785 sm = segment_manager_get (app_wrk->first_segment_manager);
786 fs = segment_manager_get_segment_w_lock (sm, 0);
787 a->segment = &fs->ssvm;
788 a->segment_handle = segment_manager_segment_handle (sm, fs);
789 segment_manager_segment_reader_unlock (sm);
790 a->evt_q = app_wrk->event_queue;
791 a->wrk_map_index = app_wrk->wrk_map_index;
792 }
793 else
794 {
795 wrk_map = app_worker_map_get (app, a->wrk_map_index);
796 if (!wrk_map)
797 return VNET_API_ERROR_INVALID_VALUE;
798
799 app_wrk = app_worker_get (wrk_map->wrk_index);
800 if (!app_wrk)
801 return VNET_API_ERROR_INVALID_VALUE;
802
803 application_api_table_del (app_wrk->api_client_index);
804 app_worker_free (app_wrk);
805 app_worker_map_free (app, wrk_map);
806 if (application_n_workers (app) == 0)
807 application_free (app);
808 }
809 return 0;
810}
811
812static int
813app_validate_namespace (u8 * namespace_id, u64 secret, u32 * app_ns_index)
814{
815 app_namespace_t *app_ns;
816 if (vec_len (namespace_id) == 0)
817 {
818 /* Use default namespace */
819 *app_ns_index = 0;
820 return 0;
821 }
822
823 *app_ns_index = app_namespace_index_from_id (namespace_id);
824 if (*app_ns_index == APP_NAMESPACE_INVALID_INDEX)
825 return VNET_API_ERROR_APP_INVALID_NS;
826 app_ns = app_namespace_get (*app_ns_index);
827 if (!app_ns)
828 return VNET_API_ERROR_APP_INVALID_NS;
829 if (app_ns->ns_secret != secret)
830 return VNET_API_ERROR_APP_WRONG_NS_SECRET;
831 return 0;
832}
833
834static u8 *
835app_name_from_api_index (u32 api_client_index)
836{
837 vl_api_registration_t *regp;
838 regp = vl_api_client_index_to_registration (api_client_index);
839 if (regp)
840 return format (0, "%s%c", regp->name, 0);
841
842 clib_warning ("api client index %u does not have an api registration!",
843 api_client_index);
844 return format (0, "unknown%c", 0);
845}
846
847/**
848 * Attach application to vpp
849 *
850 * Allocates a vpp app, i.e., a structure that keeps back pointers
851 * to external app and a segment manager for shared memory fifo based
852 * communication with the external app.
853 */
854int
855vnet_application_attach (vnet_app_attach_args_t * a)
856{
857 svm_fifo_segment_private_t *fs;
858 application_t *app = 0;
859 app_worker_t *app_wrk;
860 segment_manager_t *sm;
861 u32 app_ns_index = 0;
862 u8 *app_name = 0;
863 u64 secret;
864 int rv;
865
866 if (a->api_client_index != APP_INVALID_INDEX)
867 app = application_lookup (a->api_client_index);
868 else if (a->name)
869 app = application_lookup_name (a->name);
870 else
871 return VNET_API_ERROR_INVALID_VALUE;
872
873 if (app)
874 return VNET_API_ERROR_APP_ALREADY_ATTACHED;
875
876 if (a->api_client_index != APP_INVALID_INDEX)
877 {
878 app_name = app_name_from_api_index (a->api_client_index);
879 a->name = app_name;
880 }
881
882 secret = a->options[APP_OPTIONS_NAMESPACE_SECRET];
883 if ((rv = app_validate_namespace (a->namespace_id, secret, &app_ns_index)))
884 return rv;
885 a->options[APP_OPTIONS_NAMESPACE] = app_ns_index;
886
887 if ((rv = application_alloc_and_init ((app_init_args_t *) a)))
888 return rv;
889
890 app = application_get (a->app_index);
891 if ((rv = application_alloc_worker_and_init (app, &app_wrk)))
892 return rv;
893
894 a->app_evt_q = app_wrk->event_queue;
895 app_wrk->api_client_index = a->api_client_index;
896 sm = segment_manager_get (app_wrk->first_segment_manager);
897 fs = segment_manager_get_segment_w_lock (sm, 0);
898
899 if (application_is_proxy (app))
900 application_setup_proxy (app);
901
902 ASSERT (vec_len (fs->ssvm.name) <= 128);
903 a->segment = &fs->ssvm;
904 a->segment_handle = segment_manager_segment_handle (sm, fs);
905
906 segment_manager_segment_reader_unlock (sm);
907 vec_free (app_name);
908 return 0;
909}
910
911/**
912 * Detach application from vpp
913 */
914int
915vnet_application_detach (vnet_app_detach_args_t * a)
916{
917 application_t *app;
918
919 app = application_get_if_valid (a->app_index);
920 if (!app)
921 {
922 clib_warning ("app not attached");
923 return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
924 }
925
926 app_interface_check_thread_and_barrier (vnet_application_detach, a);
927 application_detach_process (app, a->api_client_index);
928 return 0;
929}
930
931
932static u8
933session_endpoint_in_ns (session_endpoint_t * sep)
934{
935 u8 is_lep = session_endpoint_is_local (sep);
936 if (!is_lep && sep->sw_if_index != ENDPOINT_INVALID_INDEX
937 && !ip_interface_has_address (sep->sw_if_index, &sep->ip, sep->is_ip4))
938 {
939 clib_warning ("sw_if_index %u not configured with ip %U",
940 sep->sw_if_index, format_ip46_address, &sep->ip,
941 sep->is_ip4);
942 return 0;
943 }
944 return (is_lep || ip_is_local (sep->fib_index, &sep->ip, sep->is_ip4));
945}
946
947static void
948session_endpoint_update_for_app (session_endpoint_cfg_t * sep,
949 application_t * app, u8 is_connect)
950{
951 app_namespace_t *app_ns;
952 u32 ns_index, fib_index;
953
954 ns_index = app->ns_index;
955
956 /* App is a transport proto, so fetch the calling app's ns */
957 if (app->flags & APP_OPTIONS_FLAGS_IS_TRANSPORT_APP)
Florin Coras8a140612019-02-18 22:39:39 -0800958 ns_index = sep->ns_index;
Florin Corasc1a42652019-02-08 18:27:29 -0800959
Florin Corasc1a42652019-02-08 18:27:29 -0800960 app_ns = app_namespace_get (ns_index);
961 if (!app_ns)
962 return;
963
964 /* Ask transport and network to bind to/connect using local interface
965 * that "supports" app's namespace. This will fix our local connection
966 * endpoint.
967 */
968
969 /* If in default namespace and user requested a fib index use it */
970 if (ns_index == 0 && sep->fib_index != ENDPOINT_INVALID_INDEX)
971 fib_index = sep->fib_index;
972 else
973 fib_index = sep->is_ip4 ? app_ns->ip4_fib_index : app_ns->ip6_fib_index;
974 sep->peer.fib_index = fib_index;
975 sep->fib_index = fib_index;
976
977 if (!is_connect)
978 {
979 sep->sw_if_index = app_ns->sw_if_index;
980 }
981 else
982 {
983 if (app_ns->sw_if_index != APP_NAMESPACE_INVALID_INDEX
984 && sep->peer.sw_if_index != ENDPOINT_INVALID_INDEX
985 && sep->peer.sw_if_index != app_ns->sw_if_index)
986 clib_warning ("Local sw_if_index different from app ns sw_if_index");
987
988 sep->peer.sw_if_index = app_ns->sw_if_index;
989 }
990}
991
992int
993vnet_listen (vnet_listen_args_t * a)
994{
995 app_listener_t *app_listener;
996 app_worker_t *app_wrk;
997 application_t *app;
998 int rv;
999
1000 app = application_get_if_valid (a->app_index);
1001 if (!app)
1002 return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
1003
1004 app_wrk = application_get_worker (app, a->wrk_map_index);
1005 if (!app_wrk)
1006 return VNET_API_ERROR_INVALID_VALUE;
1007
1008 a->sep_ext.app_wrk_index = app_wrk->wrk_index;
1009
1010 session_endpoint_update_for_app (&a->sep_ext, app, 0 /* is_connect */ );
1011 if (!session_endpoint_in_ns (&a->sep))
1012 return VNET_API_ERROR_INVALID_VALUE_2;
1013
1014 /*
1015 * Check if we already have an app listener
1016 */
1017 app_listener = app_listener_lookup (app, &a->sep_ext);
1018 if (app_listener)
1019 {
1020 if (app_listener->app_index != app->app_index)
1021 return VNET_API_ERROR_ADDRESS_IN_USE;
1022 if (app_worker_start_listen (app_wrk, app_listener))
1023 return -1;
1024 a->handle = app_listener_handle (app_listener);
1025 return 0;
1026 }
1027
1028 /*
1029 * Create new app listener
1030 */
1031 if ((rv = app_listener_alloc_and_init (app, &a->sep_ext, &app_listener)))
1032 return rv;
1033
1034 if ((rv = app_worker_start_listen (app_wrk, app_listener)))
1035 {
1036 app_listener_cleanup (app_listener);
1037 return rv;
1038 }
1039
1040 a->handle = app_listener_handle (app_listener);
1041 return 0;
1042}
1043
1044int
1045vnet_connect (vnet_connect_args_t * a)
1046{
1047 app_worker_t *server_wrk, *client_wrk;
1048 application_t *client;
1049 local_session_t *ll;
1050 app_listener_t *al;
1051 u32 table_index;
1052 session_t *ls;
1053 u8 fib_proto;
1054 u64 lh;
1055
1056 if (session_endpoint_is_zero (&a->sep))
1057 return VNET_API_ERROR_INVALID_VALUE;
1058
1059 client = application_get (a->app_index);
1060 session_endpoint_update_for_app (&a->sep_ext, client, 1 /* is_connect */ );
1061 client_wrk = application_get_worker (client, a->wrk_map_index);
1062
1063 /*
1064 * First check the local scope for locally attached destinations.
1065 * If we have local scope, we pass *all* connects through it since we may
1066 * have special policy rules even for non-local destinations, think proxy.
1067 */
1068 if (application_has_local_scope (client))
1069 {
1070 table_index = application_local_session_table (client);
1071 lh = session_lookup_local_endpoint (table_index, &a->sep);
1072 if (lh == SESSION_DROP_HANDLE)
1073 return VNET_API_ERROR_APP_CONNECT_FILTERED;
1074
1075 if (lh == SESSION_INVALID_HANDLE)
1076 goto global_scope;
1077
1078 ll = application_get_local_listener_w_handle (lh);
1079 al = app_listener_get_w_session ((session_t *) ll);
1080
1081 /*
1082 * Break loop if rule in local table points to connecting app. This
1083 * can happen if client is a generic proxy. Route connect through
1084 * global table instead.
1085 */
1086 if (al->app_index == a->app_index)
1087 goto global_scope;
1088
1089 server_wrk = app_listener_select_worker (al);
1090 return app_worker_local_session_connect (client_wrk, server_wrk, ll,
1091 a->api_context);
1092 }
1093
1094 /*
1095 * If nothing found, check the global scope for locally attached
1096 * destinations. Make sure first that we're allowed to.
1097 */
1098
1099global_scope:
1100 if (session_endpoint_is_local (&a->sep))
1101 return VNET_API_ERROR_SESSION_CONNECT;
1102
1103 if (!application_has_global_scope (client))
1104 return VNET_API_ERROR_APP_CONNECT_SCOPE;
1105
1106 fib_proto = session_endpoint_fib_proto (&a->sep);
1107 table_index = application_session_table (client, fib_proto);
1108 ls = session_lookup_listener (table_index, &a->sep);
1109 if (ls)
1110 {
1111 al = app_listener_get_w_session (ls);
1112 server_wrk = app_listener_select_worker (al);
1113 ll = (local_session_t *) ls;
1114 return app_worker_local_session_connect (client_wrk, server_wrk, ll,
1115 a->api_context);
1116 }
1117
1118 /*
1119 * Not connecting to a local server, propagate to transport
1120 */
1121 if (app_worker_connect_session (client_wrk, &a->sep, a->api_context))
1122 return VNET_API_ERROR_SESSION_CONNECT;
1123 return 0;
1124}
1125
1126int
1127vnet_unlisten (vnet_unlisten_args_t * a)
1128{
1129 app_worker_t *app_wrk;
1130 app_listener_t *al;
1131 application_t *app;
1132
1133 if (!(app = application_get_if_valid (a->app_index)))
1134 return VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
1135
1136 al = app_listener_get_w_handle (a->handle);
1137 if (al->app_index != app->app_index)
1138 {
1139 clib_warning ("app doesn't own handle %llu!", a->handle);
1140 return -1;
1141 }
1142
1143 app_wrk = application_get_worker (app, a->wrk_map_index);
1144 if (!app_wrk)
1145 {
1146 clib_warning ("no app %u worker %u", app->app_index, a->wrk_map_index);
1147 return -1;
1148 }
1149
1150 return app_worker_stop_listen (app_wrk, al);
1151}
1152
1153int
1154vnet_disconnect_session (vnet_disconnect_args_t * a)
1155{
1156 if (session_handle_is_local (a->handle))
1157 {
Florin Coras51a423d2019-02-19 20:57:06 -08001158 app_worker_t *client_wrk, *server_wrk;
Florin Corasc1a42652019-02-08 18:27:29 -08001159 local_session_t *ls;
Florin Coras51a423d2019-02-19 20:57:06 -08001160 u32 wrk_index = ~0;
Florin Corasc1a42652019-02-08 18:27:29 -08001161
1162 /* Disconnect reply came to worker 1 not main thread */
1163 app_interface_check_thread_and_barrier (vnet_disconnect_session, a);
1164
1165 if (!(ls = app_worker_get_local_session_from_handle (a->handle)))
1166 return 0;
1167
Florin Coras51a423d2019-02-19 20:57:06 -08001168 client_wrk = app_worker_get_if_valid (ls->client_wrk_index);
1169 server_wrk = app_worker_get (ls->app_wrk_index);
1170
1171 if (server_wrk->app_index == a->app_index)
1172 wrk_index = server_wrk->wrk_index;
1173 else if (client_wrk && client_wrk->app_index == a->app_index)
1174 wrk_index = client_wrk->wrk_index;
1175
1176 if (wrk_index == ~0)
1177 {
1178 clib_warning ("app %u does not own session 0x%lx", a->app_index,
1179 application_local_session_handle (ls));
1180 return VNET_API_ERROR_INVALID_VALUE;
1181 }
1182
1183 return app_worker_local_session_disconnect (wrk_index, ls);
Florin Corasc1a42652019-02-08 18:27:29 -08001184 }
1185 else
1186 {
1187 app_worker_t *app_wrk;
1188 session_t *s;
1189
1190 s = session_get_from_handle_if_valid (a->handle);
1191 if (!s)
1192 return VNET_API_ERROR_INVALID_VALUE;
1193 app_wrk = app_worker_get (s->app_wrk_index);
1194 if (app_wrk->app_index != a->app_index)
1195 return VNET_API_ERROR_INVALID_VALUE;
1196
1197 /* We're peeking into another's thread pool. Make sure */
1198 ASSERT (s->session_index == session_index_from_handle (a->handle));
1199
1200 session_close (s);
1201 }
1202 return 0;
1203}
1204
1205int
Florin Coras623eb562019-02-03 19:28:34 -08001206application_change_listener_owner (session_t * s, app_worker_t * app_wrk)
1207{
1208 app_worker_t *old_wrk = app_worker_get (s->app_wrk_index);
1209 app_listener_t *app_listener;
1210 application_t *app;
1211
1212 if (!old_wrk)
1213 return -1;
1214
1215 hash_unset (old_wrk->listeners_table, listen_session_get_handle (s));
1216 if (session_transport_service_type (s) == TRANSPORT_SERVICE_CL
1217 && s->rx_fifo)
1218 segment_manager_dealloc_fifos (s->rx_fifo->segment_index, s->rx_fifo,
1219 s->tx_fifo);
1220
Florin Coras623eb562019-02-03 19:28:34 -08001221 app = application_get (old_wrk->app_index);
1222 if (!app)
1223 return -1;
1224
Florin Corasc9940fc2019-02-05 20:55:11 -08001225 app_listener = app_listener_get (app, s->al_index);
1226
1227 /* Only remove from lb for now */
Florin Coras623eb562019-02-03 19:28:34 -08001228 app_listener->workers = clib_bitmap_set (app_listener->workers,
1229 old_wrk->wrk_map_index, 0);
Florin Coras623eb562019-02-03 19:28:34 -08001230
Florin Corasc9940fc2019-02-05 20:55:11 -08001231 if (app_worker_start_listen (app_wrk, app_listener))
1232 return -1;
Florin Corasab2f6db2018-08-31 14:31:41 -07001233
Florin Corasc9940fc2019-02-05 20:55:11 -08001234 s->app_wrk_index = app_wrk->wrk_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001235
Dave Barach68b0fb02017-02-28 15:15:56 -05001236 return 0;
1237}
1238
Dave Barach52851e62017-08-07 09:35:25 -04001239int
1240application_is_proxy (application_t * app)
1241{
Florin Coras7999e832017-10-31 01:51:04 -07001242 return (app->flags & APP_OPTIONS_FLAGS_IS_PROXY);
1243}
1244
1245int
1246application_is_builtin (application_t * app)
1247{
1248 return (app->flags & APP_OPTIONS_FLAGS_IS_BUILTIN);
1249}
1250
1251int
1252application_is_builtin_proxy (application_t * app)
1253{
1254 return (application_is_proxy (app) && application_is_builtin (app));
Dave Barach52851e62017-08-07 09:35:25 -04001255}
1256
Florin Corascea194d2017-10-02 00:18:51 -07001257u8
1258application_has_local_scope (application_t * app)
1259{
1260 return app->flags & APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1261}
1262
1263u8
1264application_has_global_scope (application_t * app)
1265{
1266 return app->flags & APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
1267}
1268
Florin Coras60116992018-08-27 09:52:18 -07001269u8
1270application_use_mq_for_ctrl (application_t * app)
1271{
1272 return app->flags & APP_OPTIONS_FLAGS_USE_MQ_FOR_CTRL_MSGS;
1273}
1274
Florin Coras7999e832017-10-31 01:51:04 -07001275static clib_error_t *
1276application_start_stop_proxy_fib_proto (application_t * app, u8 fib_proto,
1277 u8 transport_proto, u8 is_start)
1278{
Florin Coras7999e832017-10-31 01:51:04 -07001279 app_namespace_t *app_ns = app_namespace_get (app->ns_index);
1280 u8 is_ip4 = (fib_proto == FIB_PROTOCOL_IP4);
Florin Coras5665ced2018-10-25 18:03:45 -07001281 session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
Florin Coras7999e832017-10-31 01:51:04 -07001282 transport_connection_t *tc;
Florin Coras15531972018-08-12 23:50:53 -07001283 app_worker_t *app_wrk;
Florin Corasc9940fc2019-02-05 20:55:11 -08001284 app_listener_t *al;
Florin Coras288eaab2019-02-03 15:26:14 -08001285 session_t *s;
Florin Corasc9940fc2019-02-05 20:55:11 -08001286 u32 flags;
Florin Coras7999e832017-10-31 01:51:04 -07001287
Florin Coras15531972018-08-12 23:50:53 -07001288 /* TODO decide if we want proxy to be enabled for all workers */
1289 app_wrk = application_get_default_worker (app);
Florin Coras7999e832017-10-31 01:51:04 -07001290 if (is_start)
1291 {
Florin Coras15531972018-08-12 23:50:53 -07001292 s = app_worker_first_listener (app_wrk, fib_proto, transport_proto);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001293 if (!s)
1294 {
1295 sep.is_ip4 = is_ip4;
1296 sep.fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1297 sep.sw_if_index = app_ns->sw_if_index;
1298 sep.transport_proto = transport_proto;
Florin Corasab2f6db2018-08-31 14:31:41 -07001299 sep.app_wrk_index = app_wrk->wrk_index; /* only default */
Florin Corasc9940fc2019-02-05 20:55:11 -08001300
1301 /* force global scope listener */
1302 flags = app->flags;
1303 app->flags &= ~APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
1304 app_listener_alloc_and_init (app, &sep, &al);
1305 app->flags = flags;
1306
1307 app_worker_start_listen (app_wrk, al);
1308 s = listen_session_get (al->session_index);
Florin Corasab2f6db2018-08-31 14:31:41 -07001309 s->enqueue_epoch = SESSION_PROXY_LISTENER_INDEX;
Florin Coras19b1f6a2017-12-11 03:37:03 -08001310 }
Florin Coras7999e832017-10-31 01:51:04 -07001311 }
1312 else
1313 {
Florin Coras623eb562019-02-03 19:28:34 -08001314 s = app_worker_proxy_listener (app_wrk, fib_proto, transport_proto);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001315 ASSERT (s);
Florin Coras7999e832017-10-31 01:51:04 -07001316 }
Florin Coras19b1f6a2017-12-11 03:37:03 -08001317
Florin Coras7999e832017-10-31 01:51:04 -07001318 tc = listen_session_get_transport (s);
1319
1320 if (!ip_is_zero (&tc->lcl_ip, 1))
1321 {
Florin Corasdbd44562017-11-09 19:30:17 -08001322 u32 sti;
1323 sep.is_ip4 = is_ip4;
1324 sep.fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
1325 sep.transport_proto = transport_proto;
1326 sep.port = 0;
1327 sti = session_lookup_get_index_for_fib (fib_proto, sep.fib_index);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001328 if (is_start)
Florin Corasab2f6db2018-08-31 14:31:41 -07001329 session_lookup_add_session_endpoint (sti,
1330 (session_endpoint_t *) & sep,
1331 s->session_index);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001332 else
Florin Corasab2f6db2018-08-31 14:31:41 -07001333 session_lookup_del_session_endpoint (sti,
1334 (session_endpoint_t *) & sep);
Florin Coras7999e832017-10-31 01:51:04 -07001335 }
Florin Coras19b1f6a2017-12-11 03:37:03 -08001336
Florin Coras7999e832017-10-31 01:51:04 -07001337 return 0;
1338}
1339
Florin Coras19b1f6a2017-12-11 03:37:03 -08001340static void
1341application_start_stop_proxy_local_scope (application_t * app,
1342 u8 transport_proto, u8 is_start)
1343{
1344 session_endpoint_t sep = SESSION_ENDPOINT_NULL;
1345 app_namespace_t *app_ns;
1346 app_ns = app_namespace_get (app->ns_index);
1347 sep.is_ip4 = 1;
1348 sep.transport_proto = transport_proto;
1349 sep.port = 0;
1350
1351 if (is_start)
1352 {
1353 session_lookup_add_session_endpoint (app_ns->local_table_index, &sep,
Florin Coras15531972018-08-12 23:50:53 -07001354 app->app_index);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001355 sep.is_ip4 = 0;
1356 session_lookup_add_session_endpoint (app_ns->local_table_index, &sep,
Florin Coras15531972018-08-12 23:50:53 -07001357 app->app_index);
Florin Coras19b1f6a2017-12-11 03:37:03 -08001358 }
1359 else
1360 {
1361 session_lookup_del_session_endpoint (app_ns->local_table_index, &sep);
1362 sep.is_ip4 = 0;
1363 session_lookup_del_session_endpoint (app_ns->local_table_index, &sep);
1364 }
1365}
1366
Florin Coras7999e832017-10-31 01:51:04 -07001367void
Florin Coras561af9b2017-12-09 10:19:43 -08001368application_start_stop_proxy (application_t * app,
1369 transport_proto_t transport_proto, u8 is_start)
Florin Coras7999e832017-10-31 01:51:04 -07001370{
Florin Coras7999e832017-10-31 01:51:04 -07001371 if (application_has_local_scope (app))
Florin Coras19b1f6a2017-12-11 03:37:03 -08001372 application_start_stop_proxy_local_scope (app, transport_proto, is_start);
Florin Coras7999e832017-10-31 01:51:04 -07001373
1374 if (application_has_global_scope (app))
1375 {
1376 application_start_stop_proxy_fib_proto (app, FIB_PROTOCOL_IP4,
1377 transport_proto, is_start);
1378 application_start_stop_proxy_fib_proto (app, FIB_PROTOCOL_IP6,
1379 transport_proto, is_start);
1380 }
1381}
1382
1383void
1384application_setup_proxy (application_t * app)
1385{
1386 u16 transports = app->proxied_transports;
Florin Coras561af9b2017-12-09 10:19:43 -08001387 transport_proto_t tp;
1388
Florin Coras7999e832017-10-31 01:51:04 -07001389 ASSERT (application_is_proxy (app));
Florin Coras561af9b2017-12-09 10:19:43 -08001390
1391 /* *INDENT-OFF* */
1392 transport_proto_foreach (tp, ({
1393 if (transports & (1 << tp))
1394 application_start_stop_proxy (app, tp, 1);
1395 }));
1396 /* *INDENT-ON* */
Florin Coras7999e832017-10-31 01:51:04 -07001397}
1398
1399void
1400application_remove_proxy (application_t * app)
1401{
1402 u16 transports = app->proxied_transports;
Florin Coras561af9b2017-12-09 10:19:43 -08001403 transport_proto_t tp;
1404
Florin Coras7999e832017-10-31 01:51:04 -07001405 ASSERT (application_is_proxy (app));
Florin Coras561af9b2017-12-09 10:19:43 -08001406
1407 /* *INDENT-OFF* */
1408 transport_proto_foreach (tp, ({
1409 if (transports & (1 << tp))
1410 application_start_stop_proxy (app, tp, 0);
1411 }));
1412 /* *INDENT-ON* */
Florin Coras7999e832017-10-31 01:51:04 -07001413}
1414
Florin Corasa332c462018-01-31 06:52:17 -08001415segment_manager_properties_t *
1416application_segment_manager_properties (application_t * app)
1417{
1418 return &app->sm_properties;
1419}
1420
1421segment_manager_properties_t *
1422application_get_segment_manager_properties (u32 app_index)
1423{
1424 application_t *app = application_get (app_index);
1425 return &app->sm_properties;
1426}
1427
Florin Coras371ca502018-02-21 12:07:41 -08001428clib_error_t *
1429vnet_app_add_tls_cert (vnet_app_add_tls_cert_args_t * a)
1430{
1431 application_t *app;
1432 app = application_get (a->app_index);
1433 if (!app)
1434 return clib_error_return_code (0, VNET_API_ERROR_APPLICATION_NOT_ATTACHED,
1435 0, "app %u doesn't exist", a->app_index);
1436 app->tls_cert = vec_dup (a->cert);
1437 return 0;
1438}
1439
1440clib_error_t *
1441vnet_app_add_tls_key (vnet_app_add_tls_key_args_t * a)
1442{
1443 application_t *app;
1444 app = application_get (a->app_index);
1445 if (!app)
1446 return clib_error_return_code (0, VNET_API_ERROR_APPLICATION_NOT_ATTACHED,
1447 0, "app %u doesn't exist", a->app_index);
1448 app->tls_key = vec_dup (a->key);
1449 return 0;
1450}
1451
Florin Coras15531972018-08-12 23:50:53 -07001452static void
1453application_format_listeners (application_t * app, int verbose)
1454{
1455 vlib_main_t *vm = vlib_get_main ();
1456 app_worker_map_t *wrk_map;
1457 app_worker_t *app_wrk;
1458 u32 sm_index;
1459 u64 handle;
1460
1461 if (!app)
1462 {
1463 vlib_cli_output (vm, "%U", format_app_worker_listener, 0 /* header */ ,
1464 0, 0, verbose);
1465 return;
1466 }
1467
1468 /* *INDENT-OFF* */
1469 pool_foreach (wrk_map, app->worker_maps, ({
1470 app_wrk = app_worker_get (wrk_map->wrk_index);
1471 if (hash_elts (app_wrk->listeners_table) == 0)
1472 continue;
1473 hash_foreach (handle, sm_index, app_wrk->listeners_table, ({
1474 vlib_cli_output (vm, "%U", format_app_worker_listener, app_wrk,
1475 handle, sm_index, verbose);
1476 }));
1477 }));
1478 /* *INDENT-ON* */
1479}
1480
1481static void
Florin Coras15531972018-08-12 23:50:53 -07001482application_format_connects (application_t * app, int verbose)
1483{
1484 app_worker_map_t *wrk_map;
1485 app_worker_t *app_wrk;
1486
1487 if (!app)
1488 {
1489 app_worker_format_connects (0, verbose);
1490 return;
1491 }
1492
1493 /* *INDENT-OFF* */
1494 pool_foreach (wrk_map, app->worker_maps, ({
1495 app_wrk = app_worker_get (wrk_map->wrk_index);
1496 app_worker_format_connects (app_wrk, verbose);
1497 }));
1498 /* *INDENT-ON* */
1499}
1500
1501static void
Florin Coras15531972018-08-12 23:50:53 -07001502application_format_local_sessions (application_t * app, int verbose)
1503{
Florin Corasab2f6db2018-08-31 14:31:41 -07001504 vlib_main_t *vm = vlib_get_main ();
Florin Coras15531972018-08-12 23:50:53 -07001505 app_worker_map_t *wrk_map;
1506 app_worker_t *app_wrk;
Florin Corasab2f6db2018-08-31 14:31:41 -07001507 transport_proto_t tp;
1508 local_session_t *ls;
1509 u8 *conn = 0;
Florin Coras15531972018-08-12 23:50:53 -07001510
1511 if (!app)
1512 {
1513 app_worker_format_local_sessions (0, verbose);
1514 return;
1515 }
1516
Florin Corasab2f6db2018-08-31 14:31:41 -07001517 /*
1518 * Format local listeners
1519 */
1520
1521 /* *INDENT-OFF* */
1522 pool_foreach (ls, app->local_listen_sessions, ({
1523 tp = session_type_transport_proto (ls->listener_session_type);
1524 conn = format (0, "[L][%U] *:%u", format_transport_proto_short, tp,
1525 ls->port);
1526 vlib_cli_output (vm, "%-40v%-15u%-20s", conn, ls->app_wrk_index, "*");
1527 vec_reset_length (conn);
1528 }));
1529 /* *INDENT-ON* */
1530
1531 /*
1532 * Format local accepted/connected sessions
1533 */
Florin Coras15531972018-08-12 23:50:53 -07001534 /* *INDENT-OFF* */
1535 pool_foreach (wrk_map, app->worker_maps, ({
1536 app_wrk = app_worker_get (wrk_map->wrk_index);
1537 app_worker_format_local_sessions (app_wrk, verbose);
1538 }));
1539 /* *INDENT-ON* */
1540}
1541
1542static void
Florin Coras15531972018-08-12 23:50:53 -07001543application_format_local_connects (application_t * app, int verbose)
1544{
1545 app_worker_map_t *wrk_map;
1546 app_worker_t *app_wrk;
1547
1548 if (!app)
1549 {
1550 app_worker_format_local_connects (0, verbose);
1551 return;
1552 }
1553
1554 /* *INDENT-OFF* */
1555 pool_foreach (wrk_map, app->worker_maps, ({
1556 app_wrk = app_worker_get (wrk_map->wrk_index);
1557 app_worker_format_local_connects (app_wrk, verbose);
Florin Corasf8f516a2018-02-08 15:10:09 -08001558 }));
1559 /* *INDENT-ON* */
1560}
1561
Florin Coras6cf30ad2017-04-04 23:08:23 -07001562u8 *
1563format_application (u8 * s, va_list * args)
1564{
1565 application_t *app = va_arg (*args, application_t *);
1566 CLIB_UNUSED (int verbose) = va_arg (*args, int);
Florin Corasad0c77f2017-11-09 18:00:15 -08001567 segment_manager_properties_t *props;
Florin Coras053a0e42018-11-13 15:52:38 -08001568 const u8 *app_ns_name, *app_name;
Florin Coras349f8ca2018-11-20 16:52:49 -08001569 app_worker_map_t *wrk_map;
1570 app_worker_t *app_wrk;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001571
1572 if (app == 0)
1573 {
Florin Coras349f8ca2018-11-20 16:52:49 -08001574 if (!verbose)
Florin Corasc1f5a432018-11-20 11:31:26 -08001575 s = format (s, "%-10s%-20s%-40s", "Index", "Name", "Namespace");
Florin Coras6cf30ad2017-04-04 23:08:23 -07001576 return s;
1577 }
1578
Florin Coras0bee9ce2018-03-22 21:24:31 -07001579 app_name = app_get_name (app);
Florin Corascea194d2017-10-02 00:18:51 -07001580 app_ns_name = app_namespace_id_from_index (app->ns_index);
Florin Corasa332c462018-01-31 06:52:17 -08001581 props = application_segment_manager_properties (app);
Florin Coras349f8ca2018-11-20 16:52:49 -08001582 if (!verbose)
1583 {
1584 s = format (s, "%-10u%-20s%-40s", app->app_index, app_name,
1585 app_ns_name);
1586 return s;
1587 }
1588
1589 s = format (s, "app-name %s app-index %u ns-index %u seg-size %U\n",
1590 app_name, app->app_index, app->ns_index,
1591 format_memory_size, props->add_segment_size);
1592 s = format (s, "rx-fifo-size %U tx-fifo-size %U workers:\n",
1593 format_memory_size, props->rx_fifo_size,
1594 format_memory_size, props->tx_fifo_size);
1595
1596 /* *INDENT-OFF* */
1597 pool_foreach (wrk_map, app->worker_maps, ({
1598 app_wrk = app_worker_get (wrk_map->wrk_index);
Florin Coras623eb562019-02-03 19:28:34 -08001599 s = format (s, "%U", format_app_worker, app_wrk);
Florin Coras349f8ca2018-11-20 16:52:49 -08001600 }));
1601 /* *INDENT-ON* */
1602
Dave Barach68b0fb02017-02-28 15:15:56 -05001603 return s;
1604}
1605
Florin Corasf8f516a2018-02-08 15:10:09 -08001606void
1607application_format_all_listeners (vlib_main_t * vm, int do_local, int verbose)
1608{
1609 application_t *app;
Florin Corasf8f516a2018-02-08 15:10:09 -08001610
Florin Coras15531972018-08-12 23:50:53 -07001611 if (!pool_elts (app_main.app_pool))
Florin Corasf8f516a2018-02-08 15:10:09 -08001612 {
1613 vlib_cli_output (vm, "No active server bindings");
1614 return;
1615 }
1616
1617 if (do_local)
1618 {
1619 application_format_local_sessions (0, verbose);
1620 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07001621 pool_foreach (app, app_main.app_pool, ({
Florin Corasf8f516a2018-02-08 15:10:09 -08001622 application_format_local_sessions (app, verbose);
1623 }));
1624 /* *INDENT-ON* */
1625 }
1626 else
1627 {
Florin Coras15531972018-08-12 23:50:53 -07001628 application_format_listeners (0, verbose);
Florin Corasf8f516a2018-02-08 15:10:09 -08001629
1630 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07001631 pool_foreach (app, app_main.app_pool, ({
1632 application_format_listeners (app, verbose);
Florin Corasf8f516a2018-02-08 15:10:09 -08001633 }));
1634 /* *INDENT-ON* */
1635 }
1636}
1637
1638void
1639application_format_all_clients (vlib_main_t * vm, int do_local, int verbose)
1640{
1641 application_t *app;
1642
Florin Coras15531972018-08-12 23:50:53 -07001643 if (!pool_elts (app_main.app_pool))
Florin Corasf8f516a2018-02-08 15:10:09 -08001644 {
1645 vlib_cli_output (vm, "No active apps");
1646 return;
1647 }
1648
1649 if (do_local)
1650 {
1651 application_format_local_connects (0, verbose);
1652
1653 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07001654 pool_foreach (app, app_main.app_pool, ({
1655 application_format_local_connects (app, verbose);
Florin Corasf8f516a2018-02-08 15:10:09 -08001656 }));
1657 /* *INDENT-ON* */
1658 }
1659 else
1660 {
1661 application_format_connects (0, verbose);
1662
1663 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07001664 pool_foreach (app, app_main.app_pool, ({
Florin Corasf8f516a2018-02-08 15:10:09 -08001665 application_format_connects (app, verbose);
1666 }));
1667 /* *INDENT-ON* */
1668 }
1669}
1670
Dave Barach68b0fb02017-02-28 15:15:56 -05001671static clib_error_t *
1672show_app_command_fn (vlib_main_t * vm, unformat_input_t * input,
1673 vlib_cli_command_t * cmd)
1674{
Florin Corasf8f516a2018-02-08 15:10:09 -08001675 int do_server = 0, do_client = 0, do_local = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001676 application_t *app;
Florin Coras349f8ca2018-11-20 16:52:49 -08001677 u32 app_index = ~0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001678 int verbose = 0;
1679
Florin Corascea194d2017-10-02 00:18:51 -07001680 session_cli_return_if_not_enabled ();
Florin Corase04c2992017-03-01 08:17:34 -08001681
Dave Barach68b0fb02017-02-28 15:15:56 -05001682 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1683 {
1684 if (unformat (input, "server"))
1685 do_server = 1;
1686 else if (unformat (input, "client"))
1687 do_client = 1;
Florin Corasf8f516a2018-02-08 15:10:09 -08001688 else if (unformat (input, "local"))
1689 do_local = 1;
Florin Coras349f8ca2018-11-20 16:52:49 -08001690 else if (unformat (input, "%u", &app_index))
1691 ;
Dave Barach68b0fb02017-02-28 15:15:56 -05001692 else if (unformat (input, "verbose"))
1693 verbose = 1;
1694 else
Florin Coras349f8ca2018-11-20 16:52:49 -08001695 return clib_error_return (0, "unknown input `%U'",
1696 format_unformat_error, input);
Dave Barach68b0fb02017-02-28 15:15:56 -05001697 }
1698
1699 if (do_server)
Florin Coras349f8ca2018-11-20 16:52:49 -08001700 {
1701 application_format_all_listeners (vm, do_local, verbose);
1702 return 0;
1703 }
Dave Barach68b0fb02017-02-28 15:15:56 -05001704
1705 if (do_client)
Florin Coras349f8ca2018-11-20 16:52:49 -08001706 {
1707 application_format_all_clients (vm, do_local, verbose);
1708 return 0;
1709 }
1710
1711 if (app_index != ~0)
1712 {
Florin Coras47c40e22018-11-26 17:01:36 -08001713 app = application_get_if_valid (app_index);
Florin Coras349f8ca2018-11-20 16:52:49 -08001714 if (!app)
1715 return clib_error_return (0, "No app with index %u", app_index);
1716
1717 vlib_cli_output (vm, "%U", format_application, app, /* verbose */ 1);
1718 return 0;
1719 }
Dave Barach68b0fb02017-02-28 15:15:56 -05001720
Florin Coras6cf30ad2017-04-04 23:08:23 -07001721 /* Print app related info */
1722 if (!do_server && !do_client)
1723 {
Florin Coras349f8ca2018-11-20 16:52:49 -08001724 vlib_cli_output (vm, "%U", format_application, 0, 0);
Florin Corascea194d2017-10-02 00:18:51 -07001725 /* *INDENT-OFF* */
Florin Coras15531972018-08-12 23:50:53 -07001726 pool_foreach (app, app_main.app_pool, ({
Florin Coras349f8ca2018-11-20 16:52:49 -08001727 vlib_cli_output (vm, "%U", format_application, app, 0);
Florin Corascea194d2017-10-02 00:18:51 -07001728 }));
1729 /* *INDENT-ON* */
Florin Coras6cf30ad2017-04-04 23:08:23 -07001730 }
1731
Dave Barach68b0fb02017-02-28 15:15:56 -05001732 return 0;
1733}
1734
Florin Corase04c2992017-03-01 08:17:34 -08001735/* *INDENT-OFF* */
Dave Barach68b0fb02017-02-28 15:15:56 -05001736VLIB_CLI_COMMAND (show_app_command, static) =
1737{
Florin Corase04c2992017-03-01 08:17:34 -08001738 .path = "show app",
1739 .short_help = "show app [server|client] [verbose]",
1740 .function = show_app_command_fn,
1741};
1742/* *INDENT-ON* */
Dave Barach68b0fb02017-02-28 15:15:56 -05001743
1744/*
1745 * fd.io coding-style-patch-verification: ON
1746 *
1747 * Local Variables:
1748 * eval: (c-set-style "gnu")
1749 * End:
1750 */