FD.io VPP  v18.11-rc0-18-g2a3fb1a
Vector Packet Processing
application_interface.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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 <svm/svm_fifo_segment.h>
19 #include <vnet/session/session.h>
21 #include <vnet/session/transport.h>
22 #include <vnet/tls/tls.h>
23 
24 typedef struct _vnet_app_attach_args_t
25 {
26  /** Binary API client index */
27  u32 api_client_index;
28 
29  /** Application name. Used by builtin apps */
30  u8 *name;
31 
32  /** Application and segment manager options */
33  u64 *options;
34 
35  /** ID of the namespace the app has access to */
36  u8 *namespace_id;
37 
38  /** Session to application callback functions */
40 
41  /*
42  * Results
43  */
44  ssvm_private_t *segment;
45  u64 app_event_queue_address;
46  u32 app_index;
48 
49 typedef struct _vnet_app_detach_args_t
50 {
51  u32 app_index;
53 
54 typedef struct _vnet_bind_args_t
55 {
56  union
57  {
58  char *uri;
60  };
61 
62  u32 app_index;
63 
64  /*
65  * Results
66  */
67  char *segment_name;
68  u32 segment_name_length;
69  u64 server_event_queue_address;
70  u64 handle;
72 
73 typedef struct _vnet_unbind_args_t
74 {
75  union
76  {
77  char *uri;
78  u64 handle;
79  };
80  u32 app_index;
82 
83 typedef struct _vnet_connect_args
84 {
85  union
86  {
87  char *uri;
89  };
90  u32 app_index;
91  u32 api_context;
92 
95 
96 typedef struct _vnet_disconnect_args_t
97 {
98  session_handle_t handle;
99  u32 app_index;
101 
102 typedef struct _vnet_application_add_tls_cert_args_t
103 {
104  u32 app_index;
105  u8 *cert;
107 
108 typedef struct _vnet_application_add_tls_key_args_t
109 {
110  u32 app_index;
111  u8 *key;
113 
114 /* Application attach options */
115 typedef enum
116 {
132 
133 #define foreach_app_options_flags \
134  _(ACCEPT_REDIRECT, "Use FIFO with redirects") \
135  _(ADD_SEGMENT, "Add segment and signal app if needed") \
136  _(IS_BUILTIN, "Application is builtin") \
137  _(IS_PROXY, "Application is proxying") \
138  _(USE_GLOBAL_SCOPE, "App can use global session scope") \
139  _(USE_LOCAL_SCOPE, "App can use local session scope") \
140  _(USE_MQ_FOR_CTRL_MSGS, "Use message queue for ctr msgs") \
141 
142 typedef enum _app_options
143 {
144 #define _(sym, str) APP_OPTIONS_##sym,
146 #undef _
147 } app_options_t;
148 
149 typedef enum _app_options_flags
150 {
151 #define _(sym, str) APP_OPTIONS_FLAGS_##sym = 1 << APP_OPTIONS_##sym,
153 #undef _
155 
159 
166 
169 
170 extern const char test_srv_crt_rsa[];
171 extern const u32 test_srv_crt_rsa_len;
172 extern const char test_srv_key_rsa[];
173 extern const u32 test_srv_key_rsa_len;
174 
176 {
177  ip46_address_t rmt_ip; /**< remote ip */
178  ip46_address_t lcl_ip; /**< local ip */
179  u16 rmt_port; /**< remote port (network order) */
180  u16 lcl_port; /**< local port (network order) */
181  u8 is_ip4; /**< set if uses ip4 networking */
183 
184 #define foreach_app_session_field \
185  _(svm_fifo_t, *rx_fifo) /**< rx fifo */ \
186  _(svm_fifo_t, *tx_fifo) /**< tx fifo */ \
187  _(session_type_t, session_type) /**< session type */ \
188  _(volatile u8, session_state) /**< session state */ \
189  _(u32, session_index) /**< index in owning pool */ \
190  _(app_session_transport_t, transport) /**< transport info */ \
191  _(svm_msg_q_t, *vpp_evt_q) /**< vpp event queue */ \
192  _(u8, is_dgram) /**< flag for dgram mode */ \
193 
194 typedef struct
195 {
196 #define _(type, name) type name;
198 #undef _
199 } app_session_t;
200 
201 typedef struct session_accepted_msg_
202 {
203  u32 context;
204  u64 listener_handle;
205  u64 handle;
206  u64 server_rx_fifo;
207  u64 server_tx_fifo;
208  u64 vpp_event_queue_address;
209  u64 server_event_queue_address;
210  u16 port;
211  u8 is_ip4;
212  u8 ip[16];
214 
215 typedef struct session_accepted_reply_msg_
216 {
217  u32 context;
218  i32 retval;
219  u64 handle;
221 
222 /* Make sure this is not too large, otherwise it won't fit when dequeued in
223  * the session queue node */
224 STATIC_ASSERT (sizeof (session_accepted_reply_msg_t) <= 16, "accept reply");
225 
226 typedef struct session_connected_msg_
227 {
228  u32 context;
229  i32 retval;
230  u64 handle;
231  u64 server_rx_fifo;
232  u64 server_tx_fifo;
233  u64 vpp_event_queue_address;
234  u64 client_event_queue_address;
235  u32 segment_size;
236  u8 segment_name_length;
237  u8 segment_name[64];
238  u8 lcl_ip[16];
239  u8 is_ip4;
240  u16 lcl_port;
242 
243 typedef struct session_disconnected_msg_
244 {
245  u32 client_index;
246  u32 context;
247  u64 handle;
249 
250 typedef struct session_disconnected_reply_msg_
251 {
252  u32 context;
253  i32 retval;
254  u64 handle;
256 
257 typedef struct session_reset_msg_
258 {
259  u32 client_index;
260  u32 context;
261  u64 handle;
263 
264 typedef struct session_reset_reply_msg_
265 {
266  u32 client_index;
267  u32 context;
268  i32 retval;
269  u64 handle;
271 
272 typedef struct app_session_event_
273 {
274  svm_msg_q_msg_t msg;
275  session_event_t *evt;
277 
278 static inline void
280  u8 evt_type)
281 {
284  SVM_Q_WAIT, &app_evt->msg);
285  svm_msg_q_unlock (mq);
286  app_evt->evt = svm_msg_q_msg_data (mq, &app_evt->msg);
287  memset (app_evt->evt, 0, sizeof (*app_evt->evt));
288  app_evt->evt->event_type = evt_type;
289 }
290 
291 static inline void
293 {
294  svm_msg_q_add (mq, &app_evt->msg, SVM_Q_WAIT);
295 }
296 
297 /**
298  * Send fifo io event to vpp worker thread
299  *
300  * Because there may be multiple writers to one of vpp's queues, this
301  * protects message allocation and enqueueing.
302  *
303  * @param mq vpp message queue
304  * @param f fifo for which the event is sent
305  * @param evt_type type of event
306  * @param noblock flag to indicate is request is blocking or not
307  * @return 0 if success, negative integer otherwise
308  */
309 static inline int
310 app_send_io_evt_to_vpp (svm_msg_q_t * mq, svm_fifo_t * f, u8 evt_type,
311  u8 noblock)
312 {
313  session_event_t *evt;
314  svm_msg_q_msg_t msg;
315 
316  if (noblock)
317  {
318  if (svm_msg_q_try_lock (mq))
319  return -1;
321  {
322  svm_msg_q_unlock (mq);
323  return -2;
324  }
327  {
328  svm_msg_q_unlock (mq);
329  return -2;
330  }
331  evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
332  evt->fifo = f;
333  evt->event_type = evt_type;
334  svm_msg_q_add_and_unlock (mq, &msg);
335  return 0;
336  }
337  else
338  {
339  svm_msg_q_lock (mq);
341  while (svm_msg_q_msg_is_invalid (&msg))
342  {
343  svm_msg_q_wait (mq);
345  }
346  evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
347  evt->fifo = f;
348  evt->event_type = evt_type;
349  if (svm_msg_q_is_full (mq))
350  svm_msg_q_wait (mq);
351  svm_msg_q_add_and_unlock (mq, &msg);
352  return 0;
353  }
354 }
355 
356 always_inline int
358  svm_msg_q_t * vpp_evt_q, u8 * data, u32 len, u8 noblock)
359 {
360  u32 max_enqueue, actual_write;
361  session_dgram_hdr_t hdr;
362  int rv;
363 
364  max_enqueue = svm_fifo_max_enqueue (f);
365  if (max_enqueue <= sizeof (session_dgram_hdr_t))
366  return 0;
367 
368  max_enqueue -= sizeof (session_dgram_hdr_t);
369  actual_write = clib_min (len, max_enqueue);
370  hdr.data_length = actual_write;
371  hdr.data_offset = 0;
372  clib_memcpy (&hdr.rmt_ip, &at->rmt_ip, sizeof (ip46_address_t));
373  hdr.is_ip4 = at->is_ip4;
374  hdr.rmt_port = at->rmt_port;
375  clib_memcpy (&hdr.lcl_ip, &at->lcl_ip, sizeof (ip46_address_t));
376  hdr.lcl_port = at->lcl_port;
377  rv = svm_fifo_enqueue_nowait (f, sizeof (hdr), (u8 *) & hdr);
378  ASSERT (rv == sizeof (hdr));
379 
380  if ((rv = svm_fifo_enqueue_nowait (f, actual_write, data)) > 0)
381  {
382  if (svm_fifo_set_event (f))
383  app_send_io_evt_to_vpp (vpp_evt_q, f, FIFO_EVENT_APP_TX, noblock);
384  }
385  ASSERT (rv);
386  return rv;
387 }
388 
389 always_inline int
390 app_send_dgram (app_session_t * s, u8 * data, u32 len, u8 noblock)
391 {
392  return app_send_dgram_raw (s->tx_fifo, &s->transport, s->vpp_evt_q, data,
393  len, noblock);
394 }
395 
396 always_inline int
397 app_send_stream_raw (svm_fifo_t * f, svm_msg_q_t * vpp_evt_q, u8 * data,
398  u32 len, u8 noblock)
399 {
400  int rv;
401 
402  if ((rv = svm_fifo_enqueue_nowait (f, len, data)) > 0)
403  {
404  if (svm_fifo_set_event (f))
405  app_send_io_evt_to_vpp (vpp_evt_q, f, FIFO_EVENT_APP_TX, noblock);
406  }
407  return rv;
408 }
409 
410 always_inline int
411 app_send_stream (app_session_t * s, u8 * data, u32 len, u8 noblock)
412 {
413  return app_send_stream_raw (s->tx_fifo, s->vpp_evt_q, data, len, noblock);
414 }
415 
416 always_inline int
417 app_send (app_session_t * s, u8 * data, u32 len, u8 noblock)
418 {
419  if (s->is_dgram)
420  return app_send_dgram (s, data, len, noblock);
421  return app_send_stream (s, data, len, noblock);
422 }
423 
424 always_inline int
425 app_recv_dgram_raw (svm_fifo_t * f, u8 * buf, u32 len,
426  app_session_transport_t * at, u8 clear_evt)
427 {
429  u32 max_deq;
430  int rv;
431 
432  if (clear_evt)
434  max_deq = svm_fifo_max_dequeue (f);
435  if (max_deq < sizeof (session_dgram_hdr_t))
436  return 0;
437 
438  svm_fifo_peek (f, 0, sizeof (ph), (u8 *) & ph);
439  ASSERT (ph.data_length >= ph.data_offset);
440  if (!ph.data_offset)
441  svm_fifo_peek (f, sizeof (ph), sizeof (*at), (u8 *) at);
442  len = clib_min (len, ph.data_length - ph.data_offset);
443  rv = svm_fifo_peek (f, ph.data_offset + SESSION_CONN_HDR_LEN, len, buf);
444  ph.data_offset += rv;
445  if (ph.data_offset == ph.data_length)
447  else
448  svm_fifo_overwrite_head (f, (u8 *) & ph, sizeof (ph));
449  return rv;
450 }
451 
452 always_inline int
453 app_recv_dgram (app_session_t * s, u8 * buf, u32 len)
454 {
455  return app_recv_dgram_raw (s->rx_fifo, buf, len, &s->transport, 1);
456 }
457 
458 always_inline int
459 app_recv_stream_raw (svm_fifo_t * f, u8 * buf, u32 len, u8 clear_evt)
460 {
461  if (clear_evt)
463  return svm_fifo_dequeue_nowait (f, len, buf);
464 }
465 
466 always_inline int
467 app_recv_stream (app_session_t * s, u8 * buf, u32 len)
468 {
469  return app_recv_stream_raw (s->rx_fifo, buf, len, 1);
470 }
471 
472 always_inline int
473 app_recv (app_session_t * s, u8 * data, u32 len)
474 {
475  if (s->is_dgram)
476  return app_recv_dgram (s, data, len);
477  return app_recv_stream (s, data, len);
478 }
479 
480 #endif /* __included_uri_h__ */
481 
482 /*
483  * fd.io coding-style-patch-verification: ON
484  *
485  * Local Variables:
486  * eval: (c-set-style "gnu")
487  * End:
488  */
#define foreach_app_session_field
flag for dgram mode
clib_error_t * vnet_connect_uri(vnet_connect_args_t *a)
static u8 svm_msg_q_msg_is_invalid(svm_msg_q_msg_t *msg)
Check if message is invalid.
void * svm_msg_q_msg_data(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Get data for message in queue.
static u8 svm_msg_q_ring_is_full(svm_msg_q_t *mq, u32 ring_index)
#define clib_min(x, y)
Definition: clib.h:289
u8 is_ip4
set if uses ip4 networking
a
Definition: bitmap.h:538
#define SESSION_CONN_HDR_LEN
Definition: session.h:145
static int app_send_dgram_raw(svm_fifo_t *f, app_session_transport_t *at, svm_msg_q_t *vpp_evt_q, u8 *data, u32 len, u8 noblock)
struct _vnet_connect_args vnet_connect_args_t
static int app_recv_dgram_raw(svm_fifo_t *f, u8 *buf, u32 len, app_session_transport_t *at, u8 clear_evt)
unsigned long u64
Definition: types.h:89
const char test_srv_key_rsa[]
const u32 test_srv_crt_rsa_len
clib_error_t * vnet_unbind(vnet_unbind_args_t *a)
static int app_send_stream(app_session_t *s, u8 *data, u32 len, u8 noblock)
void svm_fifo_overwrite_head(svm_fifo_t *f, u8 *data, u32 len)
Definition: svm_fifo.c:623
static u32 svm_fifo_max_enqueue(svm_fifo_t *f)
Definition: svm_fifo.h:117
struct session_disconnected_reply_msg_ session_disconnected_reply_msg_t
static int app_send_io_evt_to_vpp(svm_msg_q_t *mq, svm_fifo_t *f, u8 evt_type, u8 noblock)
Send fifo io event to vpp worker thread.
u64 session_handle_t
Definition: session.h:103
struct _vnet_application_add_tls_cert_args_t vnet_app_add_tls_cert_args_t
unsigned char u8
Definition: types.h:56
struct _svm_fifo svm_fifo_t
clib_error_t * vnet_connect(vnet_connect_args_t *a)
int svm_msg_q_lock_and_alloc_msg_w_ring(svm_msg_q_t *mq, u32 ring_index, u8 noblock, svm_msg_q_msg_t *msg)
Lock message queue and allocate message buffer on ring.
Definition: message_queue.c:99
static void app_alloc_ctrl_evt_to_vpp(svm_msg_q_t *mq, app_session_evt_t *app_evt, u8 evt_type)
static int app_send(app_session_t *s, u8 *data, u32 len, u8 noblock)
struct session_accepted_msg_ session_accepted_msg_t
struct _vnet_disconnect_args_t vnet_disconnect_args_t
#define always_inline
Definition: clib.h:92
static u32 svm_fifo_max_dequeue(svm_fifo_t *f)
Definition: svm_fifo.h:105
struct _stream_session_cb_vft session_cb_vft_t
struct _vnet_unbind_args_t vnet_unbind_args_t
int svm_fifo_enqueue_nowait(svm_fifo_t *f, u32 max_bytes, const u8 *copy_from_here)
Definition: svm_fifo.c:538
unsigned int u32
Definition: types.h:88
STATIC_ASSERT(sizeof(session_accepted_reply_msg_t)<=16,"accept reply")
struct _vnet_app_attach_args_t vnet_app_attach_args_t
clib_error_t * vnet_app_add_tls_key(vnet_app_add_tls_key_args_t *a)
Definition: application.c:1380
static int app_recv(app_session_t *s, u8 *data, u32 len)
static session_cb_vft_t session_cb_vft
Definition: session_api.c:357
struct session_accepted_reply_msg_ session_accepted_reply_msg_t
static int app_send_stream_raw(svm_fifo_t *f, svm_msg_q_t *vpp_evt_q, u8 *data, u32 len, u8 noblock)
int vnet_unbind_uri(vnet_unbind_args_t *a)
struct _session_endpoint session_endpoint_t
clib_error_t * vnet_bind(vnet_bind_args_t *a)
unsigned short u16
Definition: types.h:57
static session_handle_t session_handle(stream_session_t *s)
Definition: session.h:329
#define PREDICT_FALSE(x)
Definition: clib.h:105
ip46_address_t rmt_ip
remote ip
static void svm_fifo_unset_event(svm_fifo_t *f)
Unsets fifo event flag.
Definition: svm_fifo.h:150
static void svm_msg_q_wait(svm_msg_q_t *mq)
int vnet_bind_uri(vnet_bind_args_t *)
const u32 test_srv_key_rsa_len
static void app_send_ctrl_evt_to_vpp(svm_msg_q_t *mq, app_session_evt_t *app_evt)
static u8 svm_fifo_set_event(svm_fifo_t *f)
Sets fifo event flag.
Definition: svm_fifo.h:140
static void svm_msg_q_unlock(svm_msg_q_t *mq)
Unlock message queue.
clib_error_t * vnet_application_attach(vnet_app_attach_args_t *a)
Attach application to vpp.
#define clib_memcpy(a, b, c)
Definition: string.h:75
struct app_session_transport_ app_session_transport_t
struct session_reset_reply_msg_ session_reset_reply_msg_t
int svm_msg_q_add(svm_msg_q_t *mq, svm_msg_q_msg_t *msg, int nowait)
Producer enqueue one message to queue.
blocking call
Definition: queue.h:44
static int app_recv_stream(app_session_t *s, u8 *buf, u32 len)
static int svm_msg_q_try_lock(svm_msg_q_t *mq)
Try locking message queue.
enum _app_options_flags app_options_flags_t
const char test_srv_crt_rsa[]
signed int i32
Definition: types.h:81
clib_error_t * vnet_app_add_tls_cert(vnet_app_add_tls_cert_args_t *a)
Definition: application.c:1368
int vnet_disconnect_session(vnet_disconnect_args_t *a)
struct session_disconnected_msg_ session_disconnected_msg_t
#define ASSERT(truth)
void svm_msg_q_add_and_unlock(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Producer enqueue one message to queue with mutex held.
enum _app_options app_options_t
app_attach_options_index_t
struct app_session_event_ app_session_evt_t
static int app_send_dgram(app_session_t *s, u8 *data, u32 len, u8 noblock)
struct _vnet_application_add_tls_key_args_t vnet_app_add_tls_key_args_t
int vnet_application_detach(vnet_app_detach_args_t *a)
Detach application from vpp.
u16 lcl_port
local port (network order)
struct _vnet_app_detach_args_t vnet_app_detach_args_t
struct session_connected_msg_ session_connected_msg_t
ip46_address_t lcl_ip
local ip
int svm_fifo_dequeue_drop(svm_fifo_t *f, u32 max_bytes)
Definition: svm_fifo.c:792
struct session_reset_msg_ session_reset_msg_t
static int app_recv_stream_raw(svm_fifo_t *f, u8 *buf, u32 len, u8 clear_evt)
#define foreach_app_options_flags
static int svm_msg_q_lock(svm_msg_q_t *mq)
Lock, or block trying, the message queue.
int svm_fifo_peek(svm_fifo_t *f, u32 relative_offset, u32 max_bytes, u8 *copy_here)
Definition: svm_fifo.c:776
static u8 svm_msg_q_is_full(svm_msg_q_t *mq)
Check if message queue is full.
int svm_fifo_dequeue_nowait(svm_fifo_t *f, u32 max_bytes, u8 *copy_here)
Definition: svm_fifo.c:710
struct _vnet_bind_args_t vnet_bind_args_t
svm_msg_q_msg_t svm_msg_q_alloc_msg_w_ring(svm_msg_q_t *mq, u32 ring_index)
Allocate message buffer on ring.
Definition: message_queue.c:85
struct _session_endpoint_extended session_endpoint_extended_t
static int app_recv_dgram(app_session_t *s, u8 *buf, u32 len)
u16 rmt_port
remote port (network order)