FD.io VPP  v17.04.2-2-ga8f93f8
Vector Packet Processing
application.c
Go to the documentation of this file.
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 
17 #include <vnet/session/session.h>
18 
19 /*
20  * Pool from which we allocate all applications
21  */
23 
24 /*
25  * Hash table of apps by api client index
26  */
28 
29 int
31 {
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
49 {
50  hash_set (app_by_api_client_index, app->api_client_index, app->index);
51 }
52 
53 static void
55 {
56  hash_unset (app_by_api_client_index, app->api_client_index);
57 }
58 
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
72 {
74  api_main_t *am = &api_main;
75  void *oldheap;
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 
91 
92  pool_put (app_pool, app);
93 }
94 
95 static void
97 {
98  if (type == APP_SERVER && cb_fns->session_accept_callback == 0)
99  clib_warning ("No accept callback function provided");
100  if (type == APP_CLIENT && cb_fns->session_connected_callback == 0)
101  clib_warning ("No session connected callback function provided");
102  if (cb_fns->session_disconnect_callback == 0)
103  clib_warning ("No session disconnect callback function provided");
104  if (cb_fns->session_reset_callback == 0)
105  clib_warning ("No session reset callback function provided");
106 }
107 
110  u32 api_client_index, u32 flags, session_cb_vft_t * cb_fns)
111 {
113  api_main_t *am = &api_main;
114  application_t *app;
115  void *oldheap;
116  session_manager_t *sm;
117 
118  pool_get (app_pool, app);
119  memset (app, 0, sizeof (*app));
120 
121  /* Allocate event fifo in the /vpe-api shared-memory segment */
122  oldheap = svm_push_data_heap (am->vlib_rp);
123 
124  /* Allocate server event queue */
125  app->event_queue =
126  unix_shared_memory_queue_init (128 /* nels $$$$ config */ ,
127  sizeof (session_fifo_event_t),
128  0 /* consumer pid */ ,
129  0
130  /* (do not) signal when queue non-empty */
131  );
132 
133  svm_pop_heap (oldheap);
134 
135  /* If a server, allocate session manager */
136  if (type == APP_SERVER)
137  {
138  pool_get (smm->session_managers, sm);
139  memset (sm, 0, sizeof (*sm));
140 
141  app->session_manager_index = sm - smm->session_managers;
142  }
143  else if (type == APP_CLIENT)
144  {
145  /* Allocate connect session manager if needed */
146  if (smm->connect_manager_index[sst] == INVALID_INDEX)
148  app->session_manager_index = smm->connect_manager_index[sst];
149  }
150 
151  app->mode = type;
152  app->index = application_get_index (app);
153  app->session_type = sst;
154  app->api_client_index = api_client_index;
155  app->flags = flags;
156  app->cb_fns = *cb_fns;
157 
158  /* Check that the obvious things are properly set up */
159  application_verify_cb_fns (type, cb_fns);
160 
161  /* Add app to lookup by api_client_index table */
162  application_table_add (app);
163 
164  return app;
165 }
166 
169 {
170  return pool_elt_at_index (app_pool, index);
171 }
172 
175 {
176  if (pool_is_free_index (app_pool, index))
177  return 0;
178 
179  return pool_elt_at_index (app_pool, index);
180 }
181 
182 u32
184 {
185  return app - app_pool;
186 }
187 
188 int
189 application_server_init (application_t * server, u32 segment_size,
190  u32 add_segment_size, u32 rx_fifo_size,
191  u32 tx_fifo_size, u8 ** segment_name)
192 {
194  session_manager_t *sm;
195  int rv;
196 
197  sm = session_manager_get (server->session_manager_index);
198 
199  /* Add first segment */
200  if ((rv = session_manager_add_first_segment (smm, sm, segment_size,
201  segment_name)))
202  {
203  return rv;
204  }
205 
206  /* Setup session manager */
207  sm->add_segment_size = add_segment_size;
208  sm->rx_fifo_size = rx_fifo_size;
209  sm->tx_fifo_size = tx_fifo_size;
210  sm->add_segment = sm->add_segment_size != 0;
211  return 0;
212 }
213 
214 u8 *
215 format_application_server (u8 * s, va_list * args)
216 {
217  application_t *srv = va_arg (*args, application_t *);
218  int verbose = va_arg (*args, int);
219  vl_api_registration_t *regp;
220  stream_session_t *listener;
221  u8 *server_name, *str, *seg_name;
222  u32 segment_size;
223 
224  if (srv == 0)
225  {
226  if (verbose)
227  s = format (s, "%-40s%-20s%-15s%-15s%-10s", "Connection", "Server",
228  "Segment", "API Client", "Cookie");
229  else
230  s = format (s, "%-40s%-20s", "Connection", "Server");
231 
232  return s;
233  }
234 
235  regp = vl_api_client_index_to_registration (srv->api_client_index);
236  if (!regp)
237  server_name = format (0, "builtin-%d%c", srv->index, 0);
238  else
239  server_name = regp->name;
240 
241  listener = stream_session_listener_get (srv->session_type,
242  srv->session_index);
243  str = format (0, "%U", format_stream_session, listener, verbose);
244 
245  session_manager_get_segment_info (listener->server_segment_index, &seg_name,
246  &segment_size);
247  if (verbose)
248  {
249  s = format (s, "%-40s%-20s%-20s%-10d%-10d", str, server_name,
250  seg_name, srv->api_client_index, srv->accept_cookie);
251  }
252  else
253  s = format (s, "%-40s%-20s", str, server_name);
254  return s;
255 }
256 
257 u8 *
258 format_application_client (u8 * s, va_list * args)
259 {
260  application_t *client = va_arg (*args, application_t *);
261  int verbose = va_arg (*args, int);
262  stream_session_t *session;
263  u8 *str, *seg_name;
264  u32 segment_size;
265 
266  if (client == 0)
267  {
268  if (verbose)
269  s =
270  format (s, "%-40s%-20s%-10s", "Connection", "Segment",
271  "API Client");
272  else
273  s = format (s, "%-40s", "Connection");
274 
275  return s;
276  }
277 
278  session = stream_session_get (client->session_index, client->thread_index);
279  str = format (0, "%U", format_stream_session, session, verbose);
280 
281  session_manager_get_segment_info (session->server_segment_index, &seg_name,
282  &segment_size);
283  if (verbose)
284  {
285  s = format (s, "%-40s%-20s%-10d%", str, seg_name,
286  client->api_client_index);
287  }
288  else
289  s = format (s, "%-40s", str);
290  return s;
291 }
292 
293 static clib_error_t *
295  vlib_cli_command_t * cmd)
296 {
298  application_t *app;
299  int do_server = 0;
300  int do_client = 0;
301  int verbose = 0;
302 
303  if (!smm->is_enabled)
304  {
305  clib_error_return (0, "session layer is not enabled");
306  }
307 
309  {
310  if (unformat (input, "server"))
311  do_server = 1;
312  else if (unformat (input, "client"))
313  do_client = 1;
314  else if (unformat (input, "verbose"))
315  verbose = 1;
316  else
317  break;
318  }
319 
320  if (do_server)
321  {
322  if (pool_elts (app_pool))
323  {
325  0 /* header */ ,
326  verbose);
327  /* *INDENT-OFF* */
328  pool_foreach (app, app_pool,
329  ({
330  if (app->mode == APP_SERVER)
332  verbose);
333  }));
334  /* *INDENT-ON* */
335  }
336  else
337  vlib_cli_output (vm, "No active server bindings");
338  }
339 
340  if (do_client)
341  {
342  if (pool_elts (app_pool))
343  {
345  0 /* header */ ,
346  verbose);
347  /* *INDENT-OFF* */
348  pool_foreach (app, app_pool,
349  ({
350  if (app->mode == APP_CLIENT)
352  verbose);
353  }));
354  /* *INDENT-ON* */
355  }
356  else
357  vlib_cli_output (vm, "No active client bindings");
358  }
359 
360  return 0;
361 }
362 
363 /* *INDENT-OFF* */
364 VLIB_CLI_COMMAND (show_app_command, static) =
365 {
366  .path = "show app",
367  .short_help = "show app [server|client] [verbose]",
368  .function = show_app_command_fn,
369 };
370 /* *INDENT-ON* */
371 
372 /*
373  * fd.io coding-style-patch-verification: ON
374  *
375  * Local Variables:
376  * eval: (c-set-style "gnu")
377  * End:
378  */
static void application_table_add(application_t *app)
Definition: application.c:48
#define hash_set(h, key, value)
Definition: hash.h:254
static void svm_pop_heap(void *oldheap)
Definition: svm.h:190
#define hash_unset(h, key)
Definition: hash.h:260
static clib_error_t * show_app_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: application.c:294
void unix_shared_memory_queue_free(unix_shared_memory_queue_t *q)
session_manager_main_t session_manager_main
Definition: session.c:33
void session_manager_del(session_manager_main_t *smm, session_manager_t *sm)
Definition: session.c:477
application_t * application_lookup(u32 api_client_index)
Definition: application.c:60
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u8 * format_application_client(u8 *s, va_list *args)
Definition: application.c:258
int session_manager_add_first_segment(session_manager_main_t *smm, session_manager_t *sm, u32 segment_size, u8 **segment_name)
Definition: session.c:465
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
struct _stream_session_t stream_session_t
api_main_t api_main
Definition: api_shared.c:35
static stream_session_t * stream_session_get(u64 si, u32 thread_index)
Definition: session.h:303
void session_manager_get_segment_info(u32 index, u8 **name, u32 *size)
Definition: session.c:410
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
static void application_table_del(application_t *app)
Definition: application.c:54
static void * svm_push_data_heap(svm_region_t *rp)
Definition: svm.h:182
application_type_t
Definition: application.h:22
struct _stream_session_cb_vft session_cb_vft_t
static void application_verify_cb_fns(application_type_t type, session_cb_vft_t *cb_fns)
Definition: application.c:96
#define clib_error_return(e, args...)
Definition: error.h:111
svm_region_t * vlib_rp
Definition: api.h:142
static session_manager_t * session_manager_get(u32 index)
Definition: session.h:236
vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
#define hash_get(h, key)
Definition: hash.h:248
static session_manager_main_t * vnet_get_session_manager_main()
Definition: session.h:230
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
struct _unformat_input_t unformat_input_t
static application_t * app_pool
Definition: application.c:22
session_type_t
Definition: session.h:74
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
application_t * application_new(application_type_t type, session_type_t sst, u32 api_client_index, u32 flags, session_cb_vft_t *cb_fns)
Definition: application.c:109
struct _session_manager_main session_manager_main_t
Definition: session.h:157
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
void connects_session_manager_init(session_manager_main_t *smm, u8 session_type)
Definition: session.c:948
vlib_main_t * vm
Definition: buffer.c:276
#define INVALID_INDEX
Definition: session.h:25
u8 * format_stream_session(u8 *s, va_list *args)
Format stream session as per the following format.
Definition: session_cli.c:27
#define clib_warning(format, args...)
Definition: error.h:59
struct _session_manager session_manager_t
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:238
struct _application application_t
static uword * app_by_api_client_index
Definition: application.c:27
u8 * format_application_server(u8 *s, va_list *args)
Definition: application.c:215
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
unsigned int u32
Definition: types.h:88
static stream_session_t * stream_session_listener_get(u8 sst, u64 si)
Definition: session.h:321
unix_shared_memory_queue_t * unix_shared_memory_queue_init(int nels, int elsize, int consumer_pid, int signal_when_queue_non_empty)
void application_del(application_t *app)
Definition: application.c:71
u32 application_get_index(application_t *app)
Definition: application.c:183
u64 uword
Definition: types.h:112
unsigned char u8
Definition: types.h:56
application_t * application_get(u32 index)
Definition: application.c:168
int application_server_init(application_t *server, u32 segment_size, u32 add_segment_size, u32 rx_fifo_size, u32 tx_fifo_size, u8 **segment_name)
Definition: application.c:189
u32 flags
Definition: vhost-user.h:78
int application_api_queue_is_full(application_t *app)
Definition: application.c:30
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
application_t * application_get_if_valid(u32 index)
Definition: application.c:174
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:971
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109