Cleanup URI code and TCP bugfixing
[vpp.git] / src / vnet / session / application.c
1 /*
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>
17 #include <vnet/session/session.h>
18
19 /*
20  * Pool from which we allocate all applications
21  */
22 static application_t *app_pool;
23
24 /*
25  * Hash table of apps by api client index
26  */
27 static uword *app_by_api_client_index;
28
29 int
30 application_api_queue_is_full (application_t * app)
31 {
32   unix_shared_memory_queue_t *q;
33
34   /* builtin servers are always OK */
35   if (app->api_client_index == ~0)
36     return 0;
37
38   q = vl_api_client_index_to_input_queue (app->api_client_index);
39   if (!q)
40     return 1;
41
42   if (q->cursize == q->maxsize)
43     return 1;
44   return 0;
45 }
46
47 static void
48 application_table_add (application_t * app)
49 {
50   hash_set (app_by_api_client_index, app->api_client_index, app->index);
51 }
52
53 static void
54 application_table_del (application_t * app)
55 {
56   hash_unset (app_by_api_client_index, app->api_client_index);
57 }
58
59 application_t *
60 application_lookup (u32 api_client_index)
61 {
62   uword *p;
63   p = hash_get (app_by_api_client_index, api_client_index);
64   if (p)
65     return application_get (p[0]);
66
67   return 0;
68 }
69
70 void
71 application_del (application_t * app)
72 {
73   session_manager_main_t *smm = vnet_get_session_manager_main ();
74   api_main_t *am = &api_main;
75   void *oldheap;
76   session_manager_t *sm;
77
78   if (app->mode == APP_SERVER)
79     {
80       sm = session_manager_get (app->session_manager_index);
81       session_manager_del (smm, sm);
82     }
83
84   /* Free the event fifo in the /vpe-api shared-memory segment */
85   oldheap = svm_push_data_heap (am->vlib_rp);
86   if (app->event_queue)
87     unix_shared_memory_queue_free (app->event_queue);
88   svm_pop_heap (oldheap);
89
90   application_table_del (app);
91
92   pool_put (app_pool, app);
93 }
94
95 application_t *
96 application_new (application_type_t type, session_type_t sst,
97                  u32 api_client_index, u32 flags, session_cb_vft_t * cb_fns)
98 {
99   session_manager_main_t *smm = vnet_get_session_manager_main ();
100   api_main_t *am = &api_main;
101   application_t *app;
102   void *oldheap;
103   session_manager_t *sm;
104
105   pool_get (app_pool, app);
106   memset (app, 0, sizeof (*app));
107
108   /* Allocate event fifo in the /vpe-api shared-memory segment */
109   oldheap = svm_push_data_heap (am->vlib_rp);
110
111   /* Allocate server event queue */
112   app->event_queue =
113     unix_shared_memory_queue_init (128 /* nels $$$$ config */ ,
114                                    sizeof (session_fifo_event_t),
115                                    0 /* consumer pid */ ,
116                                    0
117                                    /* (do not) signal when queue non-empty */
118     );
119
120   svm_pop_heap (oldheap);
121
122   /* If a server, allocate session manager */
123   if (type == APP_SERVER)
124     {
125       pool_get (smm->session_managers, sm);
126       memset (sm, 0, sizeof (*sm));
127
128       app->session_manager_index = sm - smm->session_managers;
129     }
130   else if (type == APP_CLIENT)
131     {
132       /* Allocate connect session manager if needed */
133       if (smm->connect_manager_index[sst] == INVALID_INDEX)
134         connects_session_manager_init (smm, sst);
135       app->session_manager_index = smm->connect_manager_index[sst];
136     }
137
138   app->mode = type;
139   app->index = application_get_index (app);
140   app->session_type = sst;
141   app->api_client_index = api_client_index;
142   app->flags = flags;
143   app->cb_fns = *cb_fns;
144
145   /* Add app to lookup by api_client_index table */
146   application_table_add (app);
147
148   return app;
149 }
150
151 application_t *
152 application_get (u32 index)
153 {
154   return pool_elt_at_index (app_pool, index);
155 }
156
157 application_t *
158 application_get_if_valid (u32 index)
159 {
160   if (pool_is_free_index (app_pool, index))
161     return 0;
162
163   return pool_elt_at_index (app_pool, index);
164 }
165
166 u32
167 application_get_index (application_t * app)
168 {
169   return app - app_pool;
170 }
171
172 int
173 application_server_init (application_t * server, u32 segment_size,
174                          u32 add_segment_size, u32 rx_fifo_size,
175                          u32 tx_fifo_size, u8 ** segment_name)
176 {
177   session_manager_main_t *smm = vnet_get_session_manager_main ();
178   session_manager_t *sm;
179   int rv;
180
181   sm = session_manager_get (server->session_manager_index);
182
183   /* Add first segment */
184   if ((rv = session_manager_add_first_segment (smm, sm, segment_size,
185                                                segment_name)))
186     {
187       return rv;
188     }
189
190   /* Setup session manager */
191   sm->add_segment_size = add_segment_size;
192   sm->rx_fifo_size = rx_fifo_size;
193   sm->tx_fifo_size = tx_fifo_size;
194   sm->add_segment = sm->add_segment_size != 0;
195   return 0;
196 }
197
198 u8 *
199 format_application_server (u8 * s, va_list * args)
200 {
201   application_t *srv = va_arg (*args, application_t *);
202   int verbose = va_arg (*args, int);
203   vl_api_registration_t *regp;
204   stream_session_t *listener;
205   u8 *server_name, *str, *seg_name;
206   u32 segment_size;
207
208   if (srv == 0)
209     {
210       if (verbose)
211         s = format (s, "%-40s%-20s%-15s%-15s%-10s", "Connection", "Server",
212                     "Segment", "API Client", "Cookie");
213       else
214         s = format (s, "%-40s%-20s", "Connection", "Server");
215
216       return s;
217     }
218
219   regp = vl_api_client_index_to_registration (srv->api_client_index);
220   if (!regp)
221     server_name = format (0, "builtin-%d%c", srv->index, 0);
222   else
223     server_name = regp->name;
224
225   listener = stream_session_listener_get (srv->session_type,
226                                           srv->session_index);
227   str = format (0, "%U", format_stream_session, listener, verbose);
228
229   session_manager_get_segment_info (listener->server_segment_index, &seg_name,
230                                     &segment_size);
231   if (verbose)
232     {
233       s = format (s, "%-40s%-20s%-20s%-10d%-10d", str, server_name,
234                   seg_name, srv->api_client_index, srv->accept_cookie);
235     }
236   else
237     s = format (s, "%-40s%-20s", str, server_name);
238   return s;
239 }
240
241 u8 *
242 format_application_client (u8 * s, va_list * args)
243 {
244   application_t *client = va_arg (*args, application_t *);
245   int verbose = va_arg (*args, int);
246   stream_session_t *session;
247   u8 *str, *seg_name;
248   u32 segment_size;
249
250   if (client == 0)
251     {
252       if (verbose)
253         s =
254           format (s, "%-40s%-20s%-10s", "Connection", "Segment",
255                   "API Client");
256       else
257         s = format (s, "%-40s", "Connection");
258
259       return s;
260     }
261
262   session = stream_session_get (client->session_index, client->thread_index);
263   str = format (0, "%U", format_stream_session, session, verbose);
264
265   session_manager_get_segment_info (session->server_segment_index, &seg_name,
266                                     &segment_size);
267   if (verbose)
268     {
269       s = format (s, "%-40s%-20s%-10d%", str, seg_name,
270                   client->api_client_index);
271     }
272   else
273     s = format (s, "%-40s", str);
274   return s;
275 }
276
277 static clib_error_t *
278 show_app_command_fn (vlib_main_t * vm, unformat_input_t * input,
279                      vlib_cli_command_t * cmd)
280 {
281   session_manager_main_t *smm = &session_manager_main;
282   application_t *app;
283   int do_server = 0;
284   int do_client = 0;
285   int verbose = 0;
286
287   if (!smm->is_enabled)
288     {
289       clib_error_return (0, "session layer is not enabled");
290     }
291
292   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
293     {
294       if (unformat (input, "server"))
295         do_server = 1;
296       else if (unformat (input, "client"))
297         do_client = 1;
298       else if (unformat (input, "verbose"))
299         verbose = 1;
300       else
301         break;
302     }
303
304   if (do_server)
305     {
306       if (pool_elts (app_pool))
307         {
308           vlib_cli_output (vm, "%U", format_application_server,
309                            0 /* header */ ,
310                            verbose);
311           /* *INDENT-OFF* */
312           pool_foreach (app, app_pool,
313           ({
314             if (app->mode == APP_SERVER)
315               vlib_cli_output (vm, "%U", format_application_server, app,
316                                verbose);
317           }));
318           /* *INDENT-ON* */
319         }
320       else
321         vlib_cli_output (vm, "No active server bindings");
322     }
323
324   if (do_client)
325     {
326       if (pool_elts (app_pool))
327         {
328           vlib_cli_output (vm, "%U", format_application_client,
329                            0 /* header */ ,
330                            verbose);
331           /* *INDENT-OFF* */
332           pool_foreach (app, app_pool,
333           ({
334             if (app->mode == APP_CLIENT)
335               vlib_cli_output (vm, "%U", format_application_client, app,
336                                verbose);
337           }));
338           /* *INDENT-ON* */
339         }
340       else
341         vlib_cli_output (vm, "No active client bindings");
342     }
343
344   return 0;
345 }
346
347 /* *INDENT-OFF* */
348 VLIB_CLI_COMMAND (show_app_command, static) =
349 {
350   .path = "show app",
351   .short_help = "show app [server|client] [verbose]",
352   .function = show_app_command_fn,
353 };
354 /* *INDENT-ON* */
355
356 /*
357  * fd.io coding-style-patch-verification: ON
358  *
359  * Local Variables:
360  * eval: (c-set-style "gnu")
361  * End:
362  */