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