Line data Source code
1 : /*
2 : * Copyright (c) 2016-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 : #ifndef __included_uri_h__
16 : #define __included_uri_h__
17 :
18 : #include <vlibmemory/api.h>
19 : #include <svm/message_queue.h>
20 : #include <vnet/session/session_types.h>
21 : #include <vnet/tls/tls_test.h>
22 : #include <svm/fifo_segment.h>
23 :
24 : typedef struct certificate_
25 : {
26 : u32 *app_interests; /* vec of application index asking for deletion cb */
27 : u32 cert_key_index; /* index in cert & key pool */
28 : u8 *key;
29 : u8 *cert;
30 : } app_cert_key_pair_t;
31 :
32 : typedef struct session_cb_vft_
33 : {
34 : /** Notify server of new segment */
35 : int (*add_segment_callback) (u32 app_wrk_index, u64 segment_handle);
36 :
37 : /** Notify server of new segment */
38 : int (*del_segment_callback) (u32 app_wrk_index, u64 segment_handle);
39 :
40 : /** Notify server of newly accepted session */
41 : int (*session_accept_callback) (session_t * new_session);
42 :
43 : /** Connection request callback */
44 : int (*session_connected_callback) (u32 app_wrk_index, u32 opaque,
45 : session_t * s, session_error_t code);
46 :
47 : /** Notify app that session is closing */
48 : void (*session_disconnect_callback) (session_t * s);
49 :
50 : /** Notify app that transport is closed */
51 : void (*session_transport_closed_callback) (session_t * s);
52 :
53 : /** Notify app that session or transport are about to be removed */
54 : void (*session_cleanup_callback) (session_t * s, session_cleanup_ntf_t ntf);
55 :
56 : /** Notify app that half open state was cleaned up (optional) */
57 : void (*half_open_cleanup_callback) (session_t *s);
58 :
59 : /** Notify app that session was reset */
60 : void (*session_reset_callback) (session_t * s);
61 :
62 : /** Notify app that session pool migration happened */
63 : void (*session_migrate_callback) (session_t * s, session_handle_t new_sh);
64 :
65 : /** Direct RX callback for built-in application */
66 : int (*builtin_app_rx_callback) (session_t * session);
67 :
68 : /** Direct TX callback for built-in application */
69 : int (*builtin_app_tx_callback) (session_t * session);
70 :
71 : /** Cert and key pair delete notification */
72 : int (*app_cert_key_pair_delete_callback) (app_cert_key_pair_t * ckpair);
73 :
74 : /** Delegate fifo-tuning-logic to application */
75 : int (*fifo_tuning_callback) (session_t * s, svm_fifo_t * f,
76 : session_ft_action_t act, u32 bytes);
77 :
78 : } session_cb_vft_t;
79 :
80 : #define foreach_app_init_args \
81 : _(u32, api_client_index) \
82 : _(u8 *, name) \
83 : _(u64 *, options) \
84 : _(u8 *, namespace_id) \
85 : _(session_cb_vft_t *, session_cb_vft) \
86 : _(u32, app_index) \
87 : _(u8, use_sock_api) \
88 :
89 : typedef struct _vnet_app_attach_args_t
90 : {
91 : #define _(_type, _name) _type _name;
92 : foreach_app_init_args
93 : #undef _
94 : ssvm_private_t * segment;
95 : svm_msg_q_t *app_evt_q;
96 : u64 segment_handle;
97 : } vnet_app_attach_args_t;
98 :
99 : typedef struct _vnet_app_detach_args_t
100 : {
101 : u32 app_index;
102 : u32 api_client_index;
103 : } vnet_app_detach_args_t;
104 :
105 : typedef struct _vnet_bind_args_t
106 : {
107 : union
108 : {
109 : session_endpoint_cfg_t sep_ext;
110 : session_endpoint_t sep;
111 : char *uri;
112 : };
113 :
114 : u32 app_index;
115 : u32 wrk_map_index;
116 :
117 : /*
118 : * Results
119 : */
120 : u64 handle;
121 : } vnet_listen_args_t;
122 :
123 : typedef struct _vnet_unlisten_args_t
124 : {
125 : union
126 : {
127 : char *uri;
128 : u64 handle; /**< Session handle */
129 : };
130 : u32 app_index; /**< Owning application index */
131 : u32 wrk_map_index; /**< App's local pool worker index */
132 : } vnet_unlisten_args_t;
133 :
134 : typedef struct _vnet_connect_args
135 : {
136 : union
137 : {
138 : session_endpoint_cfg_t sep_ext;
139 : session_endpoint_t sep;
140 : char *uri;
141 : };
142 : u32 app_index;
143 : u32 wrk_map_index;
144 : u32 api_context;
145 :
146 : /* Resulting session, or half-open session, if connect successful */
147 : session_handle_t sh;
148 : } vnet_connect_args_t;
149 :
150 : typedef struct _vnet_shutdown_args_t
151 : {
152 : session_handle_t handle;
153 : u32 app_index;
154 : } vnet_shutdown_args_t;
155 :
156 : typedef struct _vnet_disconnect_args_t
157 : {
158 : session_handle_t handle;
159 : u32 app_index;
160 : } vnet_disconnect_args_t;
161 :
162 : typedef struct _vnet_application_add_tls_cert_args_t
163 : {
164 : u32 app_index;
165 : u8 *cert;
166 : } vnet_app_add_tls_cert_args_t;
167 :
168 : typedef struct _vnet_application_add_tls_key_args_t
169 : {
170 : u32 app_index;
171 : u8 *key;
172 : } vnet_app_add_tls_key_args_t;
173 :
174 : typedef enum crypto_engine_type_
175 : {
176 : CRYPTO_ENGINE_NONE,
177 : CRYPTO_ENGINE_OPENSSL,
178 : CRYPTO_ENGINE_MBEDTLS,
179 : CRYPTO_ENGINE_VPP,
180 : CRYPTO_ENGINE_PICOTLS,
181 : CRYPTO_ENGINE_LAST = CRYPTO_ENGINE_PICOTLS,
182 : } crypto_engine_type_t;
183 :
184 : typedef struct _vnet_app_add_cert_key_pair_args_
185 : {
186 : u8 *cert;
187 : u8 *key;
188 : u32 cert_len;
189 : u32 key_len;
190 : u32 index;
191 : } vnet_app_add_cert_key_pair_args_t;
192 :
193 : typedef struct crypto_ctx_
194 : {
195 : u32 ctx_index; /**< index in crypto context pool */
196 : u32 n_subscribers; /**< refcount of sessions using said context */
197 : u32 ckpair_index; /**< certificate & key */
198 : u8 crypto_engine;
199 : void *data; /**< protocol specific data */
200 : } crypto_context_t;
201 :
202 : /* Application attach options */
203 : typedef enum
204 : {
205 : APP_OPTIONS_FLAGS,
206 : APP_OPTIONS_EVT_QUEUE_SIZE,
207 : APP_OPTIONS_SEGMENT_SIZE,
208 : APP_OPTIONS_ADD_SEGMENT_SIZE,
209 : APP_OPTIONS_PRIVATE_SEGMENT_COUNT,
210 : APP_OPTIONS_RX_FIFO_SIZE,
211 : APP_OPTIONS_TX_FIFO_SIZE,
212 : APP_OPTIONS_PREALLOC_FIFO_PAIRS,
213 : APP_OPTIONS_PREALLOC_FIFO_HDRS,
214 : APP_OPTIONS_NAMESPACE,
215 : APP_OPTIONS_NAMESPACE_SECRET,
216 : APP_OPTIONS_PROXY_TRANSPORT,
217 : APP_OPTIONS_ACCEPT_COOKIE,
218 : APP_OPTIONS_TLS_ENGINE,
219 : APP_OPTIONS_MAX_FIFO_SIZE,
220 : APP_OPTIONS_HIGH_WATERMARK,
221 : APP_OPTIONS_LOW_WATERMARK,
222 : APP_OPTIONS_PCT_FIRST_ALLOC,
223 : APP_OPTIONS_N_OPTIONS
224 : } app_attach_options_index_t;
225 :
226 : #define foreach_app_options_flags \
227 : _ (ACCEPT_REDIRECT, "Use FIFO with redirects") \
228 : _ (ADD_SEGMENT, "Add segment and signal app if needed") \
229 : _ (IS_BUILTIN, "Application is builtin") \
230 : _ (IS_TRANSPORT_APP, "Application is a transport proto") \
231 : _ (IS_PROXY, "Application is proxying") \
232 : _ (USE_GLOBAL_SCOPE, "App can use global session scope") \
233 : _ (USE_LOCAL_SCOPE, "App can use local session scope") \
234 : _ (EVT_MQ_USE_EVENTFD, "Use eventfds for signaling") \
235 : _ (MEMFD_FOR_BUILTIN, "Use memfd for builtin app segs") \
236 : _ (USE_HUGE_PAGE, "Use huge page for FIFO")
237 :
238 : typedef enum _app_options
239 : {
240 : #define _(sym, str) APP_OPTIONS_##sym,
241 : foreach_app_options_flags
242 : #undef _
243 : } app_options_t;
244 :
245 : typedef enum _app_options_flags
246 : {
247 : #define _(sym, str) APP_OPTIONS_FLAGS_##sym = 1 << APP_OPTIONS_##sym,
248 : foreach_app_options_flags
249 : #undef _
250 : } app_options_flags_t;
251 :
252 : #define foreach_fd_type \
253 : _(VPP_MQ_SEGMENT, "Fd for vpp's event mq segment") \
254 : _(MEMFD_SEGMENT, "Fd for memfd segment") \
255 : _(MQ_EVENTFD, "Event fd used by message queue") \
256 : _(VPP_MQ_EVENTFD, "Event fd used by vpp's message queue") \
257 :
258 : typedef enum session_fd_type_
259 : {
260 : #define _(sym, str) SESSION_FD_##sym,
261 : foreach_fd_type
262 : #undef _
263 : SESSION_N_FD_TYPE
264 : } session_fd_type_t;
265 :
266 : typedef enum session_fd_flag_
267 : {
268 : #define _(sym, str) SESSION_FD_F_##sym = 1 << SESSION_FD_##sym,
269 : foreach_fd_type
270 : #undef _
271 : } session_fd_flag_t;
272 :
273 : int parse_uri (char *uri, session_endpoint_cfg_t * sep);
274 : int vnet_bind_uri (vnet_listen_args_t *);
275 : int vnet_unbind_uri (vnet_unlisten_args_t * a);
276 : int vnet_connect_uri (vnet_connect_args_t * a);
277 :
278 : int vnet_application_attach (vnet_app_attach_args_t * a);
279 : int vnet_application_detach (vnet_app_detach_args_t * a);
280 : int vnet_listen (vnet_listen_args_t * a);
281 : int vnet_connect (vnet_connect_args_t * a);
282 : int vnet_unlisten (vnet_unlisten_args_t * a);
283 : int vnet_shutdown_session (vnet_shutdown_args_t *a);
284 : int vnet_disconnect_session (vnet_disconnect_args_t * a);
285 :
286 : int vnet_app_add_cert_key_pair (vnet_app_add_cert_key_pair_args_t * a);
287 : int vnet_app_del_cert_key_pair (u32 index);
288 : /** Ask for app cb on pair deletion */
289 : int vnet_app_add_cert_key_interest (u32 index, u32 app_index);
290 :
291 : uword unformat_vnet_uri (unformat_input_t *input, va_list *args);
292 :
293 : typedef struct app_session_transport_
294 : {
295 : ip46_address_t rmt_ip; /**< remote ip */
296 : ip46_address_t lcl_ip; /**< local ip */
297 : u16 rmt_port; /**< remote port (network order) */
298 : u16 lcl_port; /**< local port (network order) */
299 : u8 is_ip4; /**< set if uses ip4 networking */
300 : } app_session_transport_t;
301 :
302 : #define foreach_app_session_field \
303 : _(svm_fifo_t, *rx_fifo) /**< rx fifo */ \
304 : _(svm_fifo_t, *tx_fifo) /**< tx fifo */ \
305 : _(session_type_t, session_type) /**< session type */ \
306 : _(volatile u8, session_state) /**< session state */ \
307 : _(u32, session_index) /**< index in owning pool */ \
308 : _(app_session_transport_t, transport) /**< transport info */ \
309 : _(svm_msg_q_t, *vpp_evt_q) /**< vpp event queue */ \
310 : _(u8, is_dgram) /**< flag for dgram mode */ \
311 :
312 : typedef struct
313 : {
314 : #define _(type, name) type name;
315 : foreach_app_session_field
316 : #undef _
317 : } app_session_t;
318 :
319 : typedef struct session_listen_msg_
320 : {
321 : u32 client_index;
322 : u32 context; /* Not needed but keeping it for compatibility with bapi */
323 : u32 wrk_index;
324 : u32 vrf;
325 : u16 port;
326 : u8 proto;
327 : u8 is_ip4;
328 : ip46_address_t ip;
329 : u8 flags;
330 : uword ext_config;
331 : } __clib_packed session_listen_msg_t;
332 :
333 : STATIC_ASSERT (sizeof (session_listen_msg_t) <= SESSION_CTRL_MSG_MAX_SIZE,
334 : "msg too large");
335 :
336 : typedef struct session_listen_uri_msg_
337 : {
338 : u32 client_index;
339 : u32 context;
340 : u8 uri[56];
341 : } __clib_packed session_listen_uri_msg_t;
342 :
343 : STATIC_ASSERT (sizeof (session_listen_uri_msg_t) <= SESSION_CTRL_MSG_MAX_SIZE,
344 : "msg too large");
345 :
346 : typedef struct session_bound_msg_
347 : {
348 : u32 context;
349 : u64 handle;
350 : i32 retval;
351 : u8 lcl_is_ip4;
352 : u8 lcl_ip[16];
353 : u16 lcl_port;
354 : uword rx_fifo;
355 : uword tx_fifo;
356 : uword vpp_evt_q;
357 : u64 segment_handle;
358 : u32 mq_index;
359 : } __clib_packed session_bound_msg_t;
360 :
361 : typedef struct session_unlisten_msg_
362 : {
363 : u32 client_index;
364 : u32 context;
365 : u32 wrk_index;
366 : session_handle_t handle;
367 : } __clib_packed session_unlisten_msg_t;
368 :
369 : typedef struct session_unlisten_reply_msg_
370 : {
371 : u32 context;
372 : u64 handle;
373 : i32 retval;
374 : } __clib_packed session_unlisten_reply_msg_t;
375 :
376 : typedef struct session_accepted_msg_
377 : {
378 : u32 context;
379 : u64 listener_handle;
380 : u64 handle;
381 : uword server_rx_fifo;
382 : uword server_tx_fifo;
383 : u64 segment_handle;
384 : uword vpp_event_queue_address;
385 : u32 mq_index;
386 : transport_endpoint_t lcl;
387 : transport_endpoint_t rmt;
388 : u8 flags;
389 : } __clib_packed session_accepted_msg_t;
390 :
391 : typedef struct session_accepted_reply_msg_
392 : {
393 : u32 context;
394 : i32 retval;
395 : u64 handle;
396 : } __clib_packed session_accepted_reply_msg_t;
397 :
398 : typedef struct session_connect_msg_
399 : {
400 : u32 client_index;
401 : u32 context;
402 : u32 wrk_index;
403 : u32 vrf;
404 : u16 port;
405 : u16 lcl_port;
406 : u8 proto;
407 : u8 is_ip4;
408 : ip46_address_t ip;
409 : ip46_address_t lcl_ip;
410 : u64 parent_handle;
411 : u32 ckpair_index;
412 : u8 crypto_engine;
413 : u8 flags;
414 : u8 dscp;
415 : uword ext_config;
416 : } __clib_packed session_connect_msg_t;
417 :
418 : STATIC_ASSERT (sizeof (session_connect_msg_t) <= SESSION_CTRL_MSG_MAX_SIZE,
419 : "msg too large");
420 :
421 : typedef struct session_connect_uri_msg_
422 : {
423 : u32 client_index;
424 : u32 context;
425 : u8 uri[56];
426 : } __clib_packed session_connect_uri_msg_t;
427 :
428 : STATIC_ASSERT (sizeof (session_connect_uri_msg_t) <=
429 : SESSION_CTRL_MSG_MAX_SIZE, "msg too large");
430 :
431 : typedef struct session_connected_msg_
432 : {
433 : u32 context;
434 : i32 retval;
435 : u64 handle;
436 : uword server_rx_fifo;
437 : uword server_tx_fifo;
438 : u64 segment_handle;
439 : uword ct_rx_fifo;
440 : uword ct_tx_fifo;
441 : u64 ct_segment_handle;
442 : uword vpp_event_queue_address;
443 : transport_endpoint_t lcl;
444 : u32 mq_index;
445 : } __clib_packed session_connected_msg_t;
446 :
447 : typedef struct session_shutdown_msg_
448 : {
449 : u32 client_index;
450 : u32 context;
451 : session_handle_t handle;
452 : } __clib_packed session_shutdown_msg_t;
453 :
454 : typedef struct session_disconnect_msg_
455 : {
456 : u32 client_index;
457 : u32 context;
458 : session_handle_t handle;
459 : } __clib_packed session_disconnect_msg_t;
460 :
461 : typedef struct session_disconnected_msg_
462 : {
463 : u32 client_index;
464 : u32 context;
465 : u64 handle;
466 : } __clib_packed session_disconnected_msg_t;
467 :
468 : typedef struct session_disconnected_reply_msg_
469 : {
470 : u32 context;
471 : i32 retval;
472 : u64 handle;
473 : } __clib_packed session_disconnected_reply_msg_t;
474 :
475 : typedef struct session_reset_msg_
476 : {
477 : u32 client_index;
478 : u32 context;
479 : u64 handle;
480 : } __clib_packed session_reset_msg_t;
481 :
482 : typedef struct session_reset_reply_msg_
483 : {
484 : u32 context;
485 : i32 retval;
486 : u64 handle;
487 : } __clib_packed session_reset_reply_msg_t;
488 :
489 : typedef struct session_req_worker_update_msg_
490 : {
491 : u64 session_handle;
492 : } __clib_packed session_req_worker_update_msg_t;
493 :
494 : /* NOTE: using u16 for wrk indices because message needs to fit in 18B */
495 : typedef struct session_worker_update_msg_
496 : {
497 : u32 client_index;
498 : u16 wrk_index;
499 : u16 req_wrk_index;
500 : u64 handle;
501 : } __clib_packed session_worker_update_msg_t;
502 :
503 : typedef struct session_worker_update_reply_msg_
504 : {
505 : u64 handle;
506 : uword rx_fifo;
507 : uword tx_fifo;
508 : u64 segment_handle;
509 : } __clib_packed session_worker_update_reply_msg_t;
510 :
511 : typedef struct session_app_detach_msg_
512 : {
513 : u32 client_index;
514 : u32 context;
515 : } session_app_detach_msg_t;
516 :
517 : typedef struct app_map_another_segment_msg_
518 : {
519 : u32 client_index;
520 : u32 context;
521 : u8 fd_flags;
522 : u32 segment_size;
523 : u8 segment_name[128];
524 : u64 segment_handle;
525 : } session_app_add_segment_msg_t;
526 :
527 : typedef struct app_unmap_segment_msg_
528 : {
529 : u32 client_index;
530 : u32 context;
531 : u64 segment_handle;
532 : } session_app_del_segment_msg_t;
533 :
534 : typedef struct session_migrate_msg_
535 : {
536 : uword vpp_evt_q;
537 : session_handle_t handle;
538 : session_handle_t new_handle;
539 : u64 segment_handle;
540 : u32 vpp_thread_index;
541 : } __clib_packed session_migrated_msg_t;
542 :
543 : typedef struct session_cleanup_msg_
544 : {
545 : session_handle_t handle;
546 : u8 type;
547 : } __clib_packed session_cleanup_msg_t;
548 :
549 : typedef struct session_app_wrk_rpc_msg_
550 : {
551 : u32 client_index; /**< app client index */
552 : u32 wrk_index; /**< dst worker index */
553 : u8 data[64]; /**< rpc data */
554 : } __clib_packed session_app_wrk_rpc_msg_t;
555 :
556 : typedef struct session_transport_attr_msg_
557 : {
558 : u32 client_index;
559 : session_handle_t handle;
560 : transport_endpt_attr_t attr;
561 : u8 is_get;
562 : } __clib_packed session_transport_attr_msg_t;
563 :
564 : typedef struct session_transport_attr_reply_msg_
565 : {
566 : i32 retval;
567 : session_handle_t handle;
568 : transport_endpt_attr_t attr;
569 : u8 is_get;
570 : } __clib_packed session_transport_attr_reply_msg_t;
571 :
572 : typedef struct app_session_event_
573 : {
574 : svm_msg_q_msg_t msg;
575 : session_event_t *evt;
576 : } __clib_packed app_session_evt_t;
577 :
578 : static inline void
579 260 : app_alloc_ctrl_evt_to_vpp (svm_msg_q_t * mq, app_session_evt_t * app_evt,
580 : u8 evt_type)
581 : {
582 260 : svm_msg_q_lock_and_alloc_msg_w_ring (mq,
583 : SESSION_MQ_CTRL_EVT_RING,
584 : SVM_Q_WAIT, &app_evt->msg);
585 260 : app_evt->evt = svm_msg_q_msg_data (mq, &app_evt->msg);
586 260 : clib_memset (app_evt->evt, 0, sizeof (*app_evt->evt));
587 260 : app_evt->evt->event_type = evt_type;
588 260 : }
589 :
590 : static inline void
591 260 : app_send_ctrl_evt_to_vpp (svm_msg_q_t * mq, app_session_evt_t * app_evt)
592 : {
593 260 : svm_msg_q_add_and_unlock (mq, &app_evt->msg);
594 260 : }
595 :
596 : /**
597 : * Send fifo io event to vpp worker thread
598 : *
599 : * Because there may be multiple writers to one of vpp's queues, this
600 : * protects message allocation and enqueueing.
601 : *
602 : * @param mq vpp message queue
603 : * @param f fifo for which the event is sent
604 : * @param evt_type type of event
605 : * @param noblock flag to indicate is request is blocking or not
606 : * @return 0 if success, negative integer otherwise
607 : */
608 : static inline int
609 135738 : app_send_io_evt_to_vpp (svm_msg_q_t * mq, u32 session_index, u8 evt_type,
610 : u8 noblock)
611 : {
612 : session_event_t *evt;
613 : svm_msg_q_msg_t msg;
614 :
615 135738 : if (noblock)
616 : {
617 0 : if (svm_msg_q_try_lock (mq))
618 0 : return -1;
619 0 : if (PREDICT_FALSE (
620 : svm_msg_q_or_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
621 : {
622 0 : svm_msg_q_unlock (mq);
623 0 : return -2;
624 : }
625 0 : msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
626 0 : evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
627 0 : evt->session_index = session_index;
628 0 : evt->event_type = evt_type;
629 0 : svm_msg_q_add_and_unlock (mq, &msg);
630 0 : return 0;
631 : }
632 : else
633 : {
634 135738 : svm_msg_q_lock (mq);
635 135738 : while (svm_msg_q_or_ring_is_full (mq, SESSION_MQ_IO_EVT_RING))
636 0 : svm_msg_q_or_ring_wait_prod (mq, SESSION_MQ_IO_EVT_RING);
637 135738 : msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
638 135738 : evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
639 135738 : evt->session_index = session_index;
640 135738 : evt->event_type = evt_type;
641 135738 : svm_msg_q_add_and_unlock (mq, &msg);
642 135738 : return 0;
643 : }
644 : }
645 :
646 : #define app_send_dgram_raw(f, at, vpp_evt_q, data, len, evt_type, do_evt, \
647 : noblock) \
648 : app_send_dgram_raw_gso (f, at, vpp_evt_q, data, len, 0, evt_type, do_evt, \
649 : noblock)
650 :
651 : always_inline int
652 9569 : app_send_dgram_raw_gso (svm_fifo_t *f, app_session_transport_t *at,
653 : svm_msg_q_t *vpp_evt_q, u8 *data, u32 len,
654 : u16 gso_size, u8 evt_type, u8 do_evt, u8 noblock)
655 : {
656 : session_dgram_hdr_t hdr;
657 : int rv;
658 9569 : if (svm_fifo_max_enqueue_prod (f) < (sizeof (session_dgram_hdr_t) + len))
659 0 : return 0;
660 :
661 9569 : hdr.data_length = len;
662 9569 : hdr.data_offset = 0;
663 9569 : clib_memcpy_fast (&hdr.rmt_ip, &at->rmt_ip, sizeof (ip46_address_t));
664 9569 : hdr.is_ip4 = at->is_ip4;
665 9569 : hdr.rmt_port = at->rmt_port;
666 9569 : clib_memcpy_fast (&hdr.lcl_ip, &at->lcl_ip, sizeof (ip46_address_t));
667 9569 : hdr.lcl_port = at->lcl_port;
668 9569 : hdr.gso_size = gso_size;
669 : /* *INDENT-OFF* */
670 9569 : svm_fifo_seg_t segs[2] = {{ (u8 *) &hdr, sizeof (hdr) }, { data, len }};
671 : /* *INDENT-ON* */
672 :
673 9569 : rv = svm_fifo_enqueue_segments (f, segs, 2, 0 /* allow partial */ );
674 9569 : if (PREDICT_FALSE (rv < 0))
675 0 : return 0;
676 :
677 9569 : if (do_evt)
678 : {
679 8189 : if (svm_fifo_set_event (f))
680 7194 : app_send_io_evt_to_vpp (vpp_evt_q, f->shr->master_session_index,
681 : evt_type, noblock);
682 : }
683 9569 : return len;
684 : }
685 :
686 : always_inline int
687 7183 : app_send_dgram (app_session_t * s, u8 * data, u32 len, u8 noblock)
688 : {
689 7183 : return app_send_dgram_raw (s->tx_fifo, &s->transport, s->vpp_evt_q, data,
690 : len, SESSION_IO_EVT_TX, 1 /* do_evt */ ,
691 : noblock);
692 : }
693 :
694 : always_inline int
695 3073758 : app_send_stream_raw (svm_fifo_t * f, svm_msg_q_t * vpp_evt_q, u8 * data,
696 : u32 len, u8 evt_type, u8 do_evt, u8 noblock)
697 : {
698 : int rv;
699 :
700 3073758 : rv = svm_fifo_enqueue (f, len, data);
701 3073758 : if (do_evt)
702 : {
703 2911489 : if (rv > 0 && svm_fifo_set_event (f))
704 2691 : app_send_io_evt_to_vpp (vpp_evt_q, f->shr->master_session_index,
705 : evt_type, noblock);
706 : }
707 3073758 : return rv;
708 : }
709 :
710 : always_inline int
711 2884632 : app_send_stream (app_session_t * s, u8 * data, u32 len, u8 noblock)
712 : {
713 2884632 : return app_send_stream_raw (s->tx_fifo, s->vpp_evt_q, data, len,
714 : SESSION_IO_EVT_TX, 1 /* do_evt */ , noblock);
715 : }
716 :
717 : always_inline int
718 2873560 : app_send (app_session_t * s, u8 * data, u32 len, u8 noblock)
719 : {
720 2873560 : if (s->is_dgram)
721 0 : return app_send_dgram (s, data, len, noblock);
722 2873560 : return app_send_stream (s, data, len, noblock);
723 : }
724 :
725 : always_inline int
726 2390 : app_recv_dgram_raw (svm_fifo_t * f, u8 * buf, u32 len,
727 : app_session_transport_t * at, u8 clear_evt, u8 peek)
728 : {
729 : session_dgram_pre_hdr_t ph;
730 : u32 max_deq;
731 : int rv;
732 :
733 2390 : max_deq = svm_fifo_max_dequeue_cons (f);
734 2390 : if (max_deq <= sizeof (session_dgram_hdr_t))
735 : {
736 5 : if (clear_evt)
737 0 : svm_fifo_unset_event (f);
738 5 : return 0;
739 : }
740 :
741 2385 : if (clear_evt)
742 0 : svm_fifo_unset_event (f);
743 :
744 2385 : svm_fifo_peek (f, 0, sizeof (ph), (u8 *) & ph);
745 2385 : ASSERT (ph.data_length >= ph.data_offset);
746 :
747 : /* Check if we have the full dgram */
748 2385 : if (max_deq < (ph.data_length + SESSION_CONN_HDR_LEN)
749 0 : && len >= ph.data_length)
750 0 : return 0;
751 :
752 2385 : svm_fifo_peek (f, sizeof (ph), sizeof (*at), (u8 *) at);
753 2385 : len = clib_min (len, ph.data_length - ph.data_offset);
754 2385 : rv = svm_fifo_peek (f, ph.data_offset + SESSION_CONN_HDR_LEN, len, buf);
755 2385 : if (peek)
756 0 : return rv;
757 :
758 : /* Discards data that did not fit in buffer */
759 2385 : svm_fifo_dequeue_drop (f, ph.data_length + SESSION_CONN_HDR_LEN);
760 :
761 2385 : return rv;
762 : }
763 :
764 : always_inline int
765 0 : app_recv_dgram (app_session_t * s, u8 * buf, u32 len)
766 : {
767 0 : return app_recv_dgram_raw (s->rx_fifo, buf, len, &s->transport, 1, 0);
768 : }
769 :
770 : always_inline int
771 8114479 : app_recv_stream_raw (svm_fifo_t * f, u8 * buf, u32 len, u8 clear_evt, u8 peek)
772 : {
773 8114479 : if (clear_evt)
774 7320830 : svm_fifo_unset_event (f);
775 :
776 8114479 : if (peek)
777 0 : return svm_fifo_peek (f, 0, len, buf);
778 :
779 8114479 : return svm_fifo_dequeue (f, len, buf);
780 : }
781 :
782 : always_inline int
783 7320830 : app_recv_stream (app_session_t * s, u8 * buf, u32 len)
784 : {
785 7320830 : return app_recv_stream_raw (s->rx_fifo, buf, len, 1, 0);
786 : }
787 :
788 : always_inline int
789 7294670 : app_recv (app_session_t * s, u8 * data, u32 len)
790 : {
791 7294670 : if (s->is_dgram)
792 0 : return app_recv_dgram (s, data, len);
793 7294670 : return app_recv_stream (s, data, len);
794 : }
795 :
796 : /* *INDENT-OFF* */
797 : static char *session_error_str[] = {
798 : #define _(sym, str) str,
799 : foreach_session_error
800 : #undef _
801 : };
802 : /* *INDENT-ON* */
803 :
804 : static inline u8 *
805 0 : format_session_error (u8 * s, va_list * args)
806 : {
807 0 : session_error_t error = va_arg (*args, session_error_t);
808 0 : if (-error >= 0 && -error < SESSION_N_ERRORS)
809 0 : s = format (s, "%s", session_error_str[-error]);
810 : else
811 0 : s = format (s, "invalid session err %u", -error);
812 0 : return s;
813 : }
814 :
815 : /*
816 : * Socket API messages
817 : */
818 :
819 : typedef enum app_sapi_msg_type
820 : {
821 : APP_SAPI_MSG_TYPE_NONE,
822 : APP_SAPI_MSG_TYPE_ATTACH,
823 : APP_SAPI_MSG_TYPE_ATTACH_REPLY,
824 : APP_SAPI_MSG_TYPE_ADD_DEL_WORKER,
825 : APP_SAPI_MSG_TYPE_ADD_DEL_WORKER_REPLY,
826 : APP_SAPI_MSG_TYPE_SEND_FDS,
827 : APP_SAPI_MSG_TYPE_ADD_DEL_CERT_KEY,
828 : APP_SAPI_MSG_TYPE_ADD_DEL_CERT_KEY_REPLY,
829 : } __clib_packed app_sapi_msg_type_e;
830 :
831 : typedef struct app_sapi_attach_msg_
832 : {
833 : u8 name[64];
834 : u64 options[18];
835 : } __clib_packed app_sapi_attach_msg_t;
836 :
837 : STATIC_ASSERT (sizeof (u64) * APP_OPTIONS_N_OPTIONS <=
838 : sizeof (((app_sapi_attach_msg_t *) 0)->options),
839 : "Out of options, fix message definition");
840 :
841 : typedef struct app_sapi_attach_reply_msg_
842 : {
843 : i32 retval;
844 : u32 app_index;
845 : u64 app_mq;
846 : u64 vpp_ctrl_mq;
847 : u64 segment_handle;
848 : u32 api_client_handle;
849 : u8 vpp_ctrl_mq_thread;
850 : u8 n_fds;
851 : u8 fd_flags;
852 : } __clib_packed app_sapi_attach_reply_msg_t;
853 :
854 : typedef struct app_sapi_worker_add_del_msg_
855 : {
856 : u32 app_index;
857 : u32 wrk_index;
858 : u8 is_add;
859 : } __clib_packed app_sapi_worker_add_del_msg_t;
860 :
861 : typedef struct app_sapi_worker_add_del_reply_msg_
862 : {
863 : i32 retval;
864 : u32 wrk_index;
865 : u64 app_event_queue_address;
866 : u64 segment_handle;
867 : u32 api_client_handle;
868 : u8 n_fds;
869 : u8 fd_flags;
870 : u8 is_add;
871 : } __clib_packed app_sapi_worker_add_del_reply_msg_t;
872 :
873 : typedef struct app_sapi_cert_key_add_del_msg_
874 : {
875 : u32 context;
876 : u32 index;
877 : u16 cert_len;
878 : u16 certkey_len;
879 : u8 is_add;
880 : } __clib_packed app_sapi_cert_key_add_del_msg_t;
881 :
882 : typedef struct app_sapi_cert_key_add_del_reply_msg_
883 : {
884 : u32 context;
885 : i32 retval;
886 : u32 index;
887 : } __clib_packed app_sapi_cert_key_add_del_reply_msg_t;
888 :
889 : typedef struct app_sapi_msg_
890 : {
891 : app_sapi_msg_type_e type;
892 : union
893 : {
894 : app_sapi_attach_msg_t attach;
895 : app_sapi_attach_reply_msg_t attach_reply;
896 : app_sapi_worker_add_del_msg_t worker_add_del;
897 : app_sapi_worker_add_del_reply_msg_t worker_add_del_reply;
898 : app_sapi_cert_key_add_del_msg_t cert_key_add_del;
899 : app_sapi_cert_key_add_del_reply_msg_t cert_key_add_del_reply;
900 : };
901 : } __clib_packed app_sapi_msg_t;
902 :
903 : static inline void
904 19 : session_endpoint_alloc_ext_cfg (session_endpoint_cfg_t *sep_ext,
905 : transport_endpt_ext_cfg_type_t type)
906 : {
907 : transport_endpt_ext_cfg_t *cfg;
908 : u32 cfg_size;
909 :
910 19 : cfg_size = sizeof (transport_endpt_ext_cfg_t);
911 19 : cfg = clib_mem_alloc (cfg_size);
912 19 : clib_memset (cfg, 0, cfg_size);
913 19 : cfg->type = type;
914 19 : sep_ext->ext_cfg = cfg;
915 19 : }
916 :
917 : #endif /* __included_uri_h__ */
918 :
919 : /*
920 : * fd.io coding-style-patch-verification: ON
921 : *
922 : * Local Variables:
923 : * eval: (c-set-style "gnu")
924 : * End:
925 : */
|