Line data Source code
1 : /*
2 : * Copyright (c) 2017-2019 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 : #ifndef SRC_VNET_SESSION_APPLICATION_H_
17 : #define SRC_VNET_SESSION_APPLICATION_H_
18 :
19 : #include <vnet/session/application_interface.h>
20 : #include <vnet/session/application_namespace.h>
21 : #include <vnet/session/session_types.h>
22 : #include <vnet/session/segment_manager.h>
23 :
24 : #define APP_DEBUG 0
25 :
26 : #if APP_DEBUG > 0
27 : #define APP_DBG(_fmt, _args...) clib_warning (_fmt, ##_args)
28 : #else
29 : #define APP_DBG(_fmt, _args...)
30 : #endif
31 :
32 : typedef struct app_wrk_postponed_msg_
33 : {
34 : u32 len;
35 : u8 event_type;
36 : u8 ring;
37 : u8 is_sapi;
38 : int fd;
39 : u8 data[SESSION_CTRL_MSG_TX_MAX_SIZE];
40 : } app_wrk_postponed_msg_t;
41 :
42 : typedef struct app_worker_
43 : {
44 : CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
45 :
46 : /** Worker index in global worker pool*/
47 : u32 wrk_index;
48 :
49 : /** Worker index in app's map pool */
50 : u32 wrk_map_index;
51 :
52 : /** Index of owning app */
53 : u32 app_index;
54 :
55 : /** Application listens for events on this svm queue */
56 : svm_msg_q_t *event_queue;
57 :
58 : /**
59 : * Segment manager used for outgoing connects issued by the app. By
60 : * convention this is the first segment manager allocated by the worker
61 : * so it's also the one that holds the first segment with the app's
62 : * message queue in it.
63 : */
64 : u32 connects_seg_manager;
65 :
66 : /** Lookup tables for listeners. Value is segment manager index */
67 : uword *listeners_table;
68 :
69 : /** API index for the worker. Needed for multi-process apps */
70 : u32 api_client_index;
71 :
72 : /** Set if mq is congested */
73 : u8 mq_congested;
74 :
75 : u8 app_is_builtin;
76 :
77 : /** Pool of half-open session handles. Tracked in case worker detaches */
78 : session_handle_t *half_open_table;
79 :
80 : /* Per vpp worker fifos of events for app worker */
81 : session_event_t **wrk_evts;
82 :
83 : /* Vector of vpp workers mq congestion flags */
84 : u8 *wrk_mq_congested;
85 :
86 : /** Protects detached seg managers */
87 : clib_spinlock_t detached_seg_managers_lock;
88 :
89 : /** Vector of detached listener segment managers */
90 : u32 *detached_seg_managers;
91 : } app_worker_t;
92 :
93 : typedef struct app_worker_map_
94 : {
95 : u32 wrk_index;
96 : } app_worker_map_t;
97 :
98 : typedef struct app_listener_
99 : {
100 : clib_bitmap_t *workers; /**< workers accepting connections */
101 : u32 accept_rotor; /**< last worker to accept a connection */
102 : u32 al_index; /**< app listener index in app pool */
103 : u32 app_index; /**< owning app index */
104 : u32 local_index; /**< local listening session index */
105 : u32 session_index; /**< global listening session index */
106 : session_handle_t ls_handle; /**< session handle of the local or global
107 : listening session that also identifies
108 : the app listener */
109 : } app_listener_t;
110 :
111 : typedef enum app_rx_mq_flags_
112 : {
113 : APP_RX_MQ_F_PENDING = 1 << 0,
114 : APP_RX_MQ_F_POSTPONED = 1 << 1,
115 : } app_rx_mq_flags_t;
116 :
117 : typedef struct app_rx_mq_elt_
118 : {
119 : struct app_rx_mq_elt_ *next;
120 : struct app_rx_mq_elt_ *prev;
121 : svm_msg_q_t *mq;
122 : uword file_index;
123 : u32 app_index;
124 : u8 flags;
125 : } app_rx_mq_elt_t;
126 :
127 : typedef struct application_
128 : {
129 : /** App index in app pool */
130 : u32 app_index;
131 :
132 : /** Flags */
133 : u32 flags;
134 :
135 : /** Callbacks: shoulder-taps for the server/client */
136 : session_cb_vft_t cb_fns;
137 :
138 : /** Segment manager properties. Shared by all segment managers */
139 : segment_manager_props_t sm_properties;
140 :
141 : /** Pool of mappings that keep track of workers associated to this app */
142 : app_worker_map_t *worker_maps;
143 :
144 : /** Name registered by builtin apps */
145 : u8 *name;
146 :
147 : /** Namespace the application belongs to */
148 : u32 ns_index;
149 :
150 : u16 proxied_transports;
151 :
152 : /** Pool of listeners for the app */
153 : app_listener_t *listeners;
154 :
155 : /** Preferred tls engine */
156 : u8 tls_engine;
157 :
158 : /** quic initialization vector */
159 : char quic_iv[17];
160 : u8 quic_iv_set;
161 :
162 : /** Segment where rx mqs were allocated */
163 : fifo_segment_t rx_mqs_segment;
164 :
165 : /**
166 : * Fixed vector of rx mqs that can be a part of pending_rx_mqs
167 : * linked list maintained by the app sublayer for each worker
168 : */
169 : app_rx_mq_elt_t *rx_mqs;
170 : } application_t;
171 :
172 : typedef struct app_rx_mq_handle_
173 : {
174 : union
175 : {
176 : struct
177 : {
178 : u32 app_index;
179 : u32 thread_index;
180 : };
181 : u64 as_u64;
182 : };
183 : } __attribute__ ((aligned (sizeof (u64)))) app_rx_mq_handle_t;
184 :
185 : /**
186 : * App sublayer per vpp worker state
187 : */
188 : typedef struct asl_wrk_
189 : {
190 : /** Linked list of mqs with pending messages */
191 : app_rx_mq_elt_t *pending_rx_mqs;
192 : } appsl_wrk_t;
193 :
194 : typedef struct app_main_
195 : {
196 : /**
197 : * Pool from which we allocate all applications
198 : */
199 : application_t *app_pool;
200 :
201 : /**
202 : * Hash table of apps by api client index
203 : */
204 : uword *app_by_api_client_index;
205 :
206 : /**
207 : * Hash table of builtin apps by name
208 : */
209 : uword *app_by_name;
210 :
211 : /**
212 : * Pool from which we allocate certificates (key, cert)
213 : */
214 : app_cert_key_pair_t *cert_key_pair_store;
215 :
216 : /*
217 : * Last registered crypto engine type
218 : */
219 : crypto_engine_type_t last_crypto_engine;
220 :
221 : /**
222 : * App sublayer per-worker state
223 : */
224 : appsl_wrk_t *wrk;
225 : } app_main_t;
226 :
227 : typedef struct app_init_args_
228 : {
229 : #define _(_type, _name) _type _name;
230 : foreach_app_init_args
231 : #undef _
232 : } app_init_args_t;
233 :
234 : typedef struct _vnet_app_worker_add_del_args
235 : {
236 : u32 app_index; /**< App for which a new worker is requested */
237 : u32 wrk_map_index; /**< Index to delete or return value if add */
238 : u32 api_client_index; /**< Binary API client index */
239 : ssvm_private_t *segment; /**< First segment in segment manager */
240 : u64 segment_handle; /**< Handle for the segment */
241 : svm_msg_q_t *evt_q; /**< Worker message queue */
242 : u8 is_add; /**< Flag set if addition */
243 : } vnet_app_worker_add_del_args_t;
244 :
245 : #define APP_INVALID_INDEX ((u32)~0)
246 : #define APP_NS_INVALID_INDEX ((u32)~0)
247 : #define APP_INVALID_SEGMENT_MANAGER_INDEX ((u32) ~0)
248 :
249 : app_listener_t *app_listener_get (application_t * app, u32 al_index);
250 : int app_listener_alloc_and_init (application_t * app,
251 : session_endpoint_cfg_t * sep,
252 : app_listener_t ** listener);
253 : void app_listener_cleanup (app_listener_t * app_listener);
254 : session_handle_t app_listener_handle (app_listener_t * app_listener);
255 : app_listener_t *app_listener_lookup (application_t * app,
256 : session_endpoint_cfg_t * sep);
257 :
258 : /**
259 : * Get app listener handle for listening session
260 : *
261 : * For a given listening session, this can return either the session
262 : * handle of the app listener associated to the listening session or,
263 : * if no such app listener exists, the session's handle
264 : *
265 : * @param ls listening session
266 : * @return app listener or listening session handle
267 : */
268 : session_handle_t app_listen_session_handle (session_t * ls);
269 : /**
270 : * Get app listener for listener session handle
271 : *
272 : * Should only be called on handles that have an app listener, i.e.,
273 : * were obtained at the end of a @ref vnet_listen call.
274 : *
275 : * @param handle handle of the app listener. This is the handle of
276 : * either the global or local listener
277 : * @return pointer to app listener or 0
278 : */
279 : app_listener_t *app_listener_get_w_handle (session_handle_t handle);
280 : app_listener_t *app_listener_get_w_session (session_t * ls);
281 : session_t *app_listener_get_session (app_listener_t * al);
282 : session_t *app_listener_get_local_session (app_listener_t * al);
283 :
284 : application_t *application_get (u32 index);
285 : application_t *application_get_if_valid (u32 index);
286 : application_t *application_lookup (u32 api_client_index);
287 : application_t *application_lookup_name (const u8 * name);
288 : app_worker_t *application_get_worker (application_t * app, u32 wrk_index);
289 : app_worker_t *application_get_default_worker (application_t * app);
290 : app_worker_t *application_listener_select_worker (session_t * ls);
291 : int application_change_listener_owner (session_t * s, app_worker_t * app_wrk);
292 : int application_is_proxy (application_t * app);
293 : int application_is_builtin (application_t * app);
294 : int application_is_builtin_proxy (application_t * app);
295 : u32 application_session_table (application_t * app, u8 fib_proto);
296 : u32 application_local_session_table (application_t * app);
297 : const u8 *application_name_from_index (u32 app_or_wrk);
298 : u8 application_has_local_scope (application_t * app);
299 : u8 application_has_global_scope (application_t * app);
300 : void application_setup_proxy (application_t * app);
301 : void application_remove_proxy (application_t * app);
302 : void application_namespace_cleanup (app_namespace_t *app_ns);
303 : int application_original_dst_is_enabled (application_t *app);
304 :
305 : segment_manager_props_t *application_get_segment_manager_properties (u32
306 : app_index);
307 :
308 : segment_manager_props_t
309 : * application_segment_manager_properties (application_t * app);
310 :
311 : svm_msg_q_t *application_rx_mq_get (application_t *app, u32 mq_index);
312 : u8 application_use_private_rx_mqs (void);
313 : fifo_segment_t *application_get_rx_mqs_segment (application_t *app);
314 : void application_enable_rx_mqs_nodes (u8 is_en);
315 :
316 : /*
317 : * App worker
318 : */
319 :
320 : always_inline u8
321 187686 : app_worker_mq_is_congested (app_worker_t *app_wrk)
322 : {
323 187686 : return app_wrk->mq_congested > 0;
324 : }
325 :
326 : app_worker_t *app_worker_alloc (application_t * app);
327 : int application_alloc_worker_and_init (application_t * app,
328 : app_worker_t ** wrk);
329 : app_worker_t *app_worker_get (u32 wrk_index);
330 : app_worker_t *app_worker_get_if_valid (u32 wrk_index);
331 : application_t *app_worker_get_app (u32 wrk_index);
332 : int app_worker_own_session (app_worker_t * app_wrk, session_t * s);
333 : void app_worker_free (app_worker_t * app_wrk);
334 : int app_worker_connect_session (app_worker_t *app, session_endpoint_cfg_t *sep,
335 : session_handle_t *rsh);
336 : session_error_t app_worker_start_listen (app_worker_t *app_wrk,
337 : app_listener_t *lstnr);
338 : int app_worker_stop_listen (app_worker_t * app_wrk, app_listener_t * al);
339 : int app_worker_init_accepted (session_t * s);
340 : int app_worker_listened_notify (app_worker_t *app_wrk, session_handle_t alsh,
341 : u32 opaque, int err);
342 : int app_worker_unlisten_reply (app_worker_t *app_wrk, session_handle_t sh,
343 : u32 opaque, session_error_t err);
344 : int app_worker_accept_notify (app_worker_t * app_wrk, session_t * s);
345 : int app_worker_init_connected (app_worker_t * app_wrk, session_t * s);
346 : int app_worker_connect_notify (app_worker_t * app_wrk, session_t * s,
347 : session_error_t err, u32 opaque);
348 : int app_worker_add_half_open (app_worker_t *app_wrk, session_handle_t sh);
349 : int app_worker_del_half_open (app_worker_t *app_wrk, session_t *s);
350 : int app_worker_close_notify (app_worker_t * app_wrk, session_t * s);
351 : int app_worker_transport_closed_notify (app_worker_t * app_wrk,
352 : session_t * s);
353 : int app_worker_reset_notify (app_worker_t * app_wrk, session_t * s);
354 : int app_worker_cleanup_notify (app_worker_t * app_wrk, session_t * s,
355 : session_cleanup_ntf_t ntf);
356 : int app_worker_cleanup_notify_custom (app_worker_t *app_wrk, session_t *s,
357 : session_cleanup_ntf_t ntf,
358 : void (*cleanup_cb) (session_t *s));
359 : int app_worker_migrate_notify (app_worker_t * app_wrk, session_t * s,
360 : session_handle_t new_sh);
361 : int app_worker_rx_notify (app_worker_t *app_wrk, session_t *s);
362 : int app_worker_session_fifo_tuning (app_worker_t * app_wrk, session_t * s,
363 : svm_fifo_t * f,
364 : session_ft_action_t act, u32 len);
365 : void app_worker_add_event (app_worker_t *app_wrk, session_t *s,
366 : session_evt_type_t evt_type);
367 : void app_worker_add_event_custom (app_worker_t *app_wrk, u32 thread_index,
368 : session_event_t *evt);
369 : int app_wrk_flush_wrk_events (app_worker_t *app_wrk, u32 thread_index);
370 : void app_worker_del_all_events (app_worker_t *app_wrk);
371 : segment_manager_t *app_worker_get_listen_segment_manager (app_worker_t *,
372 : session_t *);
373 : segment_manager_t *app_worker_get_connect_segment_manager (app_worker_t *);
374 : int app_worker_add_segment_notify (app_worker_t * app_wrk,
375 : u64 segment_handle);
376 : int app_worker_del_segment_notify (app_worker_t * app_wrk,
377 : u64 segment_handle);
378 : u32 app_worker_n_listeners (app_worker_t * app);
379 : session_t *app_worker_first_listener (app_worker_t * app,
380 : u8 fib_proto, u8 transport_proto);
381 : void app_wrk_send_ctrl_evt_fd (app_worker_t *app_wrk, u8 evt_type, void *msg,
382 : u32 msg_len, int fd);
383 : void app_wrk_send_ctrl_evt (app_worker_t *app_wrk, u8 evt_type, void *msg,
384 : u32 msg_len);
385 : u8 app_worker_mq_wrk_is_congested (app_worker_t *app_wrk, u32 thread_index);
386 : void app_worker_set_mq_wrk_congested (app_worker_t *app_wrk, u32 thread_index);
387 : void app_worker_unset_wrk_mq_congested (app_worker_t *app_wrk,
388 : u32 thread_index);
389 : session_t *app_worker_proxy_listener (app_worker_t * app, u8 fib_proto,
390 : u8 transport_proto);
391 : void app_worker_del_detached_sm (app_worker_t * app_wrk, u32 sm_index);
392 : u8 *format_app_worker (u8 * s, va_list * args);
393 : u8 *format_app_worker_listener (u8 * s, va_list * args);
394 : u8 *format_crypto_engine (u8 * s, va_list * args);
395 : u8 *format_crypto_context (u8 * s, va_list * args);
396 : void app_worker_format_connects (app_worker_t * app_wrk, int verbose);
397 : session_error_t vnet_app_worker_add_del (vnet_app_worker_add_del_args_t *a);
398 :
399 : uword unformat_application_proto (unformat_input_t * input, va_list * args);
400 :
401 : app_cert_key_pair_t *app_cert_key_pair_get (u32 index);
402 : app_cert_key_pair_t *app_cert_key_pair_get_if_valid (u32 index);
403 : app_cert_key_pair_t *app_cert_key_pair_get_default ();
404 :
405 : /* Needed while we support both bapi and mq ctrl messages */
406 : int mq_send_session_bound_cb (u32 app_wrk_index, u32 api_context,
407 : session_handle_t handle, int rv);
408 : int mq_send_session_connected_cb (u32 app_wrk_index, u32 api_context,
409 : session_t * s, session_error_t err);
410 : void mq_send_unlisten_reply (app_worker_t * app_wrk, session_handle_t sh,
411 : u32 context, int rv);
412 : void sapi_socket_close_w_handle (u32 api_handle);
413 :
414 : crypto_engine_type_t app_crypto_engine_type_add (void);
415 : u8 app_crypto_engine_n_types (void);
416 :
417 : static inline u8
418 217353 : app_worker_application_is_builtin (app_worker_t *app_wrk)
419 : {
420 217353 : return app_wrk->app_is_builtin;
421 : }
422 :
423 : #endif /* SRC_VNET_SESSION_APPLICATION_H_ */
424 :
425 : /*
426 : * fd.io coding-style-patch-verification: ON
427 : *
428 : * Local Variables:
429 : * eval: (c-set-style "gnu")
430 : * End:
431 : */
|