blob: 71d5af0446dda59494e9d8eb10028d81b8601bd9 [file] [log] [blame]
Dave Wallace543852a2017-08-03 02:11:34 -04001/*
Dave Wallace33e002b2017-09-06 01:20:02 -04002 * Copyright (c) 2017 Cisco and/or its affiliates.
Dave Wallace543852a2017-08-03 02:11:34 -04003 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this
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#include <stdio.h>
17#include <stdlib.h>
18#include <signal.h>
19#include <svm/svm_fifo_segment.h>
20#include <vlibmemory/api.h>
21#include <vpp/api/vpe_msg_enum.h>
22#include <vnet/session/application_interface.h>
Dave Wallace5c7cf1c2017-10-24 04:12:18 -040023#include <vcl/vppcom.h>
Dave Wallace543852a2017-08-03 02:11:34 -040024#include <vlib/unix/unix.h>
25#include <vppinfra/vec_bootstrap.h>
26
27#define vl_typedefs /* define message structures */
28#include <vpp/api/vpe_all_api_h.h>
29#undef vl_typedefs
30
31/* declare message handlers for each api */
32
33#define vl_endianfun /* define message structures */
34#include <vpp/api/vpe_all_api_h.h>
35#undef vl_endianfun
36
37/* instantiate all the print functions we know about */
38#define vl_print(handle, ...)
39#define vl_printfun
40#include <vpp/api/vpe_all_api_h.h>
41#undef vl_printfun
42
43#if (CLIB_DEBUG > 0)
Dave Wallace498b3a52017-11-09 13:00:34 -050044/* Set VPPCOM_DEBUG_INIT 2 for connection debug,
45 * 3 for read/write debug output
46 * or
47 * export VCL_DEBUG=<#> to set dynamically.
48 */
49#define VPPCOM_DEBUG_INIT 1
Dave Wallace543852a2017-08-03 02:11:34 -040050#else
Dave Wallace498b3a52017-11-09 13:00:34 -050051#define VPPCOM_DEBUG_INIT 0
Dave Wallace543852a2017-08-03 02:11:34 -040052#endif
53
Dave Wallace498b3a52017-11-09 13:00:34 -050054#define VPPCOM_DEBUG vcm->debug
55
Dave Wallace543852a2017-08-03 02:11:34 -040056/*
57 * VPPCOM Private definitions and functions.
58 */
59typedef enum
60{
61 STATE_APP_START,
62 STATE_APP_CONN_VPP,
63 STATE_APP_ENABLED,
64 STATE_APP_ATTACHED,
65} app_state_t;
66
67typedef enum
68{
69 STATE_START,
70 STATE_CONNECT,
71 STATE_LISTEN,
72 STATE_ACCEPT,
73 STATE_DISCONNECT,
74 STATE_FAILED
75} session_state_t;
76
Dave Wallacef7f809c2017-10-03 01:48:42 -040077typedef struct epoll_event vppcom_epoll_event_t;
78
79typedef struct
80{
81 u32 next_sid;
82 u32 prev_sid;
83 u32 vep_idx;
84 vppcom_epoll_event_t ev;
85#define VEP_DEFAULT_ET_MASK (EPOLLIN|EPOLLOUT)
86 u32 et_mask;
87} vppcom_epoll_t;
88
Dave Wallace543852a2017-08-03 02:11:34 -040089typedef struct
90{
Dave Wallace35830af2017-10-09 01:43:42 -040091 u8 is_ip4;
92 ip46_address_t ip46;
93} vppcom_ip46_t;
94
95typedef struct
96{
Dave Wallace543852a2017-08-03 02:11:34 -040097 volatile session_state_t state;
98
99 svm_fifo_t *server_rx_fifo;
100 svm_fifo_t *server_tx_fifo;
101 u32 sm_seg_index;
102 u64 vpp_session_handle;
Dave Wallace33e002b2017-09-06 01:20:02 -0400103 unix_shared_memory_queue_t *vpp_event_queue;
Dave Wallace543852a2017-08-03 02:11:34 -0400104
105 /* Socket configuration state */
Dave Wallacef7f809c2017-10-03 01:48:42 -0400106 /* TBD: covert 'is_*' vars to bit in u8 flags; */
Dave Wallace543852a2017-08-03 02:11:34 -0400107 u8 is_server;
108 u8 is_listen;
109 u8 is_cut_thru;
110 u8 is_nonblocking;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400111 u8 is_vep;
112 u8 is_vep_session;
113 u32 wait_cont_idx;
114 vppcom_epoll_t vep;
Dave Wallace543852a2017-08-03 02:11:34 -0400115 u32 vrf;
Dave Wallace35830af2017-10-09 01:43:42 -0400116 vppcom_ip46_t lcl_addr;
117 vppcom_ip46_t peer_addr;
Stevenac1f96d2017-10-24 16:03:58 -0700118 u16 lcl_port; // network order
119 u16 peer_port; // network order
Dave Wallace543852a2017-08-03 02:11:34 -0400120 u8 proto;
121 u64 client_queue_address;
122 u64 options[16];
123} session_t;
124
125typedef struct vppcom_cfg_t_
126{
127 u64 heapsize;
128 u64 segment_baseva;
129 u32 segment_size;
130 u32 add_segment_size;
131 u32 preallocated_fifo_pairs;
132 u32 rx_fifo_size;
133 u32 tx_fifo_size;
134 u32 event_queue_size;
135 u32 listen_queue_size;
Dave Wallace774169b2017-11-01 20:07:40 -0400136 u8 app_proxy_transport_tcp;
137 u8 app_proxy_transport_udp;
138 u8 app_scope_local;
139 u8 app_scope_global;
Dave Wallace8af20542017-10-26 03:29:30 -0400140 u8 *namespace_id;
141 u64 namespace_secret;
Dave Wallace543852a2017-08-03 02:11:34 -0400142 f64 app_timeout;
143 f64 session_timeout;
144 f64 accept_timeout;
145} vppcom_cfg_t;
146
147typedef struct vppcom_main_t_
148{
149 u8 init;
Dave Wallace498b3a52017-11-09 13:00:34 -0500150 u32 debug;
Dave Wallace543852a2017-08-03 02:11:34 -0400151 u32 *client_session_index_fifo;
152 volatile u32 bind_session_index;
Dave Wallace543852a2017-08-03 02:11:34 -0400153 int main_cpu;
154
155 /* vpe input queue */
156 unix_shared_memory_queue_t *vl_input_queue;
157
158 /* API client handle */
159 u32 my_client_index;
160
161 /* Session pool */
162 clib_spinlock_t sessions_lockp;
163 session_t *sessions;
164
165 /* Hash table for disconnect processing */
166 uword *session_index_by_vpp_handles;
167
168 /* Select bitmaps */
169 clib_bitmap_t *rd_bitmap;
170 clib_bitmap_t *wr_bitmap;
171 clib_bitmap_t *ex_bitmap;
172
173 /* Our event queue */
174 unix_shared_memory_queue_t *app_event_queue;
175
176 /* unique segment name counter */
177 u32 unique_segment_index;
178
Dave Wallace543852a2017-08-03 02:11:34 -0400179 /* For deadman timers */
180 clib_time_t clib_time;
181
182 /* State of the connection, shared between msg RX thread and main thread */
183 volatile app_state_t app_state;
184
185 vppcom_cfg_t cfg;
186
187 /* VNET_API_ERROR_FOO -> "Foo" hash table */
188 uword *error_string_by_error_number;
189} vppcom_main_t;
190
Dave Wallace2e005bb2017-11-07 01:21:39 -0500191/* NOTE: _vppcom_main is only used until the heap is allocated.
192 * Do not access it directly -- use vcm which will point to
193 * the heap allocated copy after init.
194 */
Dave Wallace498b3a52017-11-09 13:00:34 -0500195static vppcom_main_t _vppcom_main = {
196 .debug = VPPCOM_DEBUG_INIT,
197 .my_client_index = ~0
198};
Dave Wallace2e005bb2017-11-07 01:21:39 -0500199
200static vppcom_main_t *vcm = &_vppcom_main;
Dave Wallace543852a2017-08-03 02:11:34 -0400201
202static const char *
203vppcom_app_state_str (app_state_t state)
204{
205 char *st;
206
207 switch (state)
208 {
209 case STATE_APP_START:
210 st = "STATE_APP_START";
211 break;
212
213 case STATE_APP_CONN_VPP:
214 st = "STATE_APP_CONN_VPP";
215 break;
216
217 case STATE_APP_ENABLED:
218 st = "STATE_APP_ENABLED";
219 break;
220
221 case STATE_APP_ATTACHED:
222 st = "STATE_APP_ATTACHED";
223 break;
224
225 default:
226 st = "UNKNOWN_APP_STATE";
227 break;
228 }
229
230 return st;
231}
232
233static const char *
234vppcom_session_state_str (session_state_t state)
235{
236 char *st;
237
238 switch (state)
239 {
240 case STATE_START:
241 st = "STATE_START";
242 break;
243
244 case STATE_CONNECT:
245 st = "STATE_CONNECT";
246 break;
247
248 case STATE_LISTEN:
249 st = "STATE_LISTEN";
250 break;
251
252 case STATE_ACCEPT:
253 st = "STATE_ACCEPT";
254 break;
255
256 case STATE_DISCONNECT:
257 st = "STATE_DISCONNECT";
258 break;
259
260 case STATE_FAILED:
261 st = "STATE_FAILED";
262 break;
263
264 default:
265 st = "UNKNOWN_STATE";
266 break;
267 }
268
269 return st;
270}
271
272/*
273 * VPPCOM Utility Functions
274 */
275static inline int
276vppcom_session_at_index (u32 session_index, session_t * volatile *sess)
277{
Dave Wallace543852a2017-08-03 02:11:34 -0400278 /* Assumes that caller has acquired spinlock: vcm->sessions_lockp */
279 if (PREDICT_FALSE ((session_index == ~0) ||
280 pool_is_free_index (vcm->sessions, session_index)))
281 {
Dave Wallacef7f809c2017-10-03 01:48:42 -0400282 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500283 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400284 return VPPCOM_EBADFD;
285 }
286 *sess = pool_elt_at_index (vcm->sessions, session_index);
287 return VPPCOM_OK;
288}
289
290static int
291vppcom_connect_to_vpp (char *app_name)
292{
293 api_main_t *am = &api_main;
Dave Wallace543852a2017-08-03 02:11:34 -0400294
295 if (VPPCOM_DEBUG > 0)
296 printf ("\nConnecting to VPP api...");
297 if (vl_client_connect_to_vlib ("/vpe-api", app_name, 32) < 0)
298 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500299 clib_warning ("[%d] connect to vpp (%s) failed!", getpid (), app_name);
Dave Wallace543852a2017-08-03 02:11:34 -0400300 return VPPCOM_ECONNREFUSED;
301 }
302
303 vcm->vl_input_queue = am->shmem_hdr->vl_input_queue;
304 vcm->my_client_index = am->my_client_index;
305 if (VPPCOM_DEBUG > 0)
306 printf (" connected!\n");
307
308 vcm->app_state = STATE_APP_CONN_VPP;
309 return VPPCOM_OK;
310}
311
312static u8 *
313format_api_error (u8 * s, va_list * args)
314{
Dave Wallace543852a2017-08-03 02:11:34 -0400315 i32 error = va_arg (*args, u32);
316 uword *p;
317
318 p = hash_get (vcm->error_string_by_error_number, -error);
319
320 if (p)
321 s = format (s, "%s (%d)", p[0], error);
322 else
323 s = format (s, "%d", error);
324 return s;
325}
326
327static void
328vppcom_init_error_string_table (void)
329{
Dave Wallace543852a2017-08-03 02:11:34 -0400330 vcm->error_string_by_error_number = hash_create (0, sizeof (uword));
331
332#define _(n,v,s) hash_set (vcm->error_string_by_error_number, -v, s);
333 foreach_vnet_api_error;
334#undef _
335
336 hash_set (vcm->error_string_by_error_number, 99, "Misc");
337}
338
339static inline int
340vppcom_wait_for_app_state_change (app_state_t app_state)
341{
Dave Wallace543852a2017-08-03 02:11:34 -0400342 f64 timeout = clib_time_now (&vcm->clib_time) + vcm->cfg.app_timeout;
343
344 while (clib_time_now (&vcm->clib_time) < timeout)
345 {
346 if (vcm->app_state == app_state)
347 return VPPCOM_OK;
348 }
349 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500350 clib_warning ("[%d] timeout waiting for state %s (%d)", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400351 vppcom_app_state_str (app_state), app_state);
352 return VPPCOM_ETIMEDOUT;
353}
354
355static inline int
356vppcom_wait_for_session_state_change (u32 session_index,
357 session_state_t state,
358 f64 wait_for_time)
359{
Dave Wallace543852a2017-08-03 02:11:34 -0400360 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
361 session_t *volatile session;
362 int rv;
363
364 do
365 {
366 clib_spinlock_lock (&vcm->sessions_lockp);
367 rv = vppcom_session_at_index (session_index, &session);
368 if (PREDICT_FALSE (rv))
369 {
370 clib_spinlock_unlock (&vcm->sessions_lockp);
371 return rv;
372 }
373 if (session->state == state)
374 {
375 clib_spinlock_unlock (&vcm->sessions_lockp);
376 return VPPCOM_OK;
377 }
378 clib_spinlock_unlock (&vcm->sessions_lockp);
379 }
380 while (clib_time_now (&vcm->clib_time) < timeout);
381
382 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500383 clib_warning ("[%d] timeout waiting for state %s (%d)", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400384 vppcom_session_state_str (state), state);
385 return VPPCOM_ETIMEDOUT;
386}
387
388static inline int
389vppcom_wait_for_client_session_index (f64 wait_for_time)
390{
Dave Wallace543852a2017-08-03 02:11:34 -0400391 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
392
393 do
394 {
395 if (clib_fifo_elts (vcm->client_session_index_fifo))
396 return VPPCOM_OK;
397 }
398 while (clib_time_now (&vcm->clib_time) < timeout);
399
400 if (wait_for_time == 0)
401 return VPPCOM_EAGAIN;
402
403 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500404 clib_warning ("[%d] timeout waiting for client_session_index", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -0400405 return VPPCOM_ETIMEDOUT;
406}
407
408/*
409 * VPP-API message functions
410 */
411static void
412vppcom_send_session_enable_disable (u8 is_enable)
413{
Dave Wallace543852a2017-08-03 02:11:34 -0400414 vl_api_session_enable_disable_t *bmp;
415 bmp = vl_msg_api_alloc (sizeof (*bmp));
416 memset (bmp, 0, sizeof (*bmp));
417
418 bmp->_vl_msg_id = ntohs (VL_API_SESSION_ENABLE_DISABLE);
419 bmp->client_index = vcm->my_client_index;
420 bmp->context = htonl (0xfeedface);
421 bmp->is_enable = is_enable;
422 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
423}
424
425static int
426vppcom_app_session_enable (void)
427{
Dave Wallace543852a2017-08-03 02:11:34 -0400428 int rv;
429
430 if (vcm->app_state != STATE_APP_ENABLED)
431 {
432 vppcom_send_session_enable_disable (1 /* is_enabled == TRUE */ );
433 rv = vppcom_wait_for_app_state_change (STATE_APP_ENABLED);
434 if (PREDICT_FALSE (rv))
435 {
436 if (VPPCOM_DEBUG > 0)
437 clib_warning ("[%d] Session enable timed out, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500438 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -0400439 return rv;
440 }
441 }
442 return VPPCOM_OK;
443}
444
445static void
446 vl_api_session_enable_disable_reply_t_handler
447 (vl_api_session_enable_disable_reply_t * mp)
448{
Dave Wallace543852a2017-08-03 02:11:34 -0400449 if (mp->retval)
450 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500451 clib_warning ("[%d] session_enable_disable failed: %U", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400452 format_api_error, ntohl (mp->retval));
453 }
454 else
455 vcm->app_state = STATE_APP_ENABLED;
456}
457
458static void
459vppcom_app_send_attach (void)
460{
Dave Wallace543852a2017-08-03 02:11:34 -0400461 vl_api_application_attach_t *bmp;
Dave Wallace8af20542017-10-26 03:29:30 -0400462 u8 nsid_len = vec_len (vcm->cfg.namespace_id);
Dave Wallace774169b2017-11-01 20:07:40 -0400463 u8 app_is_proxy = (vcm->cfg.app_proxy_transport_tcp ||
464 vcm->cfg.app_proxy_transport_udp);
Dave Wallace8af20542017-10-26 03:29:30 -0400465
Dave Wallace543852a2017-08-03 02:11:34 -0400466 bmp = vl_msg_api_alloc (sizeof (*bmp));
467 memset (bmp, 0, sizeof (*bmp));
468
469 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
470 bmp->client_index = vcm->my_client_index;
471 bmp->context = htonl (0xfeedface);
472 bmp->options[APP_OPTIONS_FLAGS] =
Florin Corascea194d2017-10-02 00:18:51 -0700473 APP_OPTIONS_FLAGS_ACCEPT_REDIRECT | APP_OPTIONS_FLAGS_ADD_SEGMENT |
Dave Wallace774169b2017-11-01 20:07:40 -0400474 (vcm->cfg.app_scope_local ? APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE : 0) |
475 (vcm->cfg.app_scope_global ? APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE : 0) |
476 (app_is_proxy ? APP_OPTIONS_FLAGS_IS_PROXY : 0);
477 bmp->options[APP_OPTIONS_PROXY_TRANSPORT] =
478 (vcm->cfg.app_proxy_transport_tcp ? 1 << TRANSPORT_PROTO_TCP : 0) |
479 (vcm->cfg.app_proxy_transport_udp ? 1 << TRANSPORT_PROTO_UDP : 0);
Dave Wallace543852a2017-08-03 02:11:34 -0400480 bmp->options[SESSION_OPTIONS_SEGMENT_SIZE] = vcm->cfg.segment_size;
481 bmp->options[SESSION_OPTIONS_ADD_SEGMENT_SIZE] = vcm->cfg.add_segment_size;
482 bmp->options[SESSION_OPTIONS_RX_FIFO_SIZE] = vcm->cfg.rx_fifo_size;
483 bmp->options[SESSION_OPTIONS_TX_FIFO_SIZE] = vcm->cfg.tx_fifo_size;
Dave Wallace8af20542017-10-26 03:29:30 -0400484 if (nsid_len)
485 {
486 bmp->namespace_id_len = nsid_len;
487 clib_memcpy (bmp->namespace_id, vcm->cfg.namespace_id, nsid_len);
488 bmp->options[APP_OPTIONS_NAMESPACE_SECRET] = vcm->cfg.namespace_secret;
489 }
Dave Wallace543852a2017-08-03 02:11:34 -0400490 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
491}
492
493static int
494vppcom_app_attach (void)
495{
Dave Wallace543852a2017-08-03 02:11:34 -0400496 int rv;
497
498 vppcom_app_send_attach ();
499 rv = vppcom_wait_for_app_state_change (STATE_APP_ATTACHED);
500 if (PREDICT_FALSE (rv))
501 {
502 if (VPPCOM_DEBUG > 0)
503 clib_warning ("[%d] application attach timed out, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500504 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -0400505 return rv;
506 }
507 return VPPCOM_OK;
508}
509
510static void
511vppcom_app_detach (void)
512{
Dave Wallace543852a2017-08-03 02:11:34 -0400513 vl_api_application_detach_t *bmp;
514 bmp = vl_msg_api_alloc (sizeof (*bmp));
515 memset (bmp, 0, sizeof (*bmp));
516
517 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
518 bmp->client_index = vcm->my_client_index;
519 bmp->context = htonl (0xfeedface);
520 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
521}
522
523static void
524vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t *
525 mp)
526{
Dave Wallace543852a2017-08-03 02:11:34 -0400527 static svm_fifo_segment_create_args_t _a;
528 svm_fifo_segment_create_args_t *a = &_a;
529 int rv;
530
531 memset (a, 0, sizeof (*a));
532 if (mp->retval)
533 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500534 clib_warning ("[%d] attach failed: %U", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400535 format_api_error, ntohl (mp->retval));
536 return;
537 }
538
539 if (mp->segment_name_length == 0)
540 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500541 clib_warning ("[%d] segment_name_length zero", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -0400542 return;
543 }
544
545 a->segment_name = (char *) mp->segment_name;
546 a->segment_size = mp->segment_size;
547
548 ASSERT (mp->app_event_queue_address);
549
550 /* Attach to the segment vpp created */
551 rv = svm_fifo_segment_attach (a);
552 vec_reset_length (a->new_segment_indices);
553 if (PREDICT_FALSE (rv))
554 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500555 clib_warning ("[%d] svm_fifo_segment_attach ('%s') failed", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400556 mp->segment_name);
557 return;
558 }
559
560 vcm->app_event_queue =
561 uword_to_pointer (mp->app_event_queue_address,
562 unix_shared_memory_queue_t *);
563
564 vcm->app_state = STATE_APP_ATTACHED;
565}
566
567static void
568vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t *
569 mp)
570{
Dave Wallace543852a2017-08-03 02:11:34 -0400571 if (mp->retval)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500572 clib_warning ("[%d] detach failed: %U", getpid (), format_api_error,
Dave Wallace543852a2017-08-03 02:11:34 -0400573 ntohl (mp->retval));
574
575 vcm->app_state = STATE_APP_ENABLED;
576}
577
578static void
579vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t *
580 mp)
581{
Dave Wallace543852a2017-08-03 02:11:34 -0400582 uword *p;
583
584 p = hash_get (vcm->session_index_by_vpp_handles, mp->handle);
585 if (p)
586 {
587 session_t *session = 0;
588 int rv;
589 clib_spinlock_lock (&vcm->sessions_lockp);
590 rv = vppcom_session_at_index (p[0], &session);
591 if (PREDICT_FALSE (rv))
592 {
593 if (VPPCOM_DEBUG > 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -0400594 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500595 getpid (), p[0]);
Dave Wallace543852a2017-08-03 02:11:34 -0400596 }
597 hash_unset (vcm->session_index_by_vpp_handles, mp->handle);
598 session->state = STATE_DISCONNECT;
599 clib_spinlock_unlock (&vcm->sessions_lockp);
600 }
601 else
602 {
603 if (VPPCOM_DEBUG > 1)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500604 clib_warning ("[%d] couldn't find session key %llx", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400605 mp->handle);
606 }
607
608 if (mp->retval)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500609 clib_warning ("[%d] disconnect_session failed: %U", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400610 format_api_error, ntohl (mp->retval));
611}
612
613static void
614vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
615{
Dave Wallace543852a2017-08-03 02:11:34 -0400616 static svm_fifo_segment_create_args_t _a;
617 svm_fifo_segment_create_args_t *a = &_a;
618 int rv;
619
620 memset (a, 0, sizeof (*a));
621 a->segment_name = (char *) mp->segment_name;
622 a->segment_size = mp->segment_size;
623 /* Attach to the segment vpp created */
624 rv = svm_fifo_segment_attach (a);
625 vec_reset_length (a->new_segment_indices);
626 if (PREDICT_FALSE (rv))
627 {
628 clib_warning ("[%d] svm_fifo_segment_attach ('%s') failed",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500629 getpid (), mp->segment_name);
Dave Wallace543852a2017-08-03 02:11:34 -0400630 return;
631 }
632 if (VPPCOM_DEBUG > 1)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500633 clib_warning ("[%d] mapped new segment '%s' size %d", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400634 mp->segment_name, mp->segment_size);
635}
636
637static void
638vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp)
639{
Dave Wallace543852a2017-08-03 02:11:34 -0400640 session_t *session = 0;
641 vl_api_disconnect_session_reply_t *rmp;
642 uword *p;
643 int rv = 0;
644
645 p = hash_get (vcm->session_index_by_vpp_handles, mp->handle);
646 if (p)
647 {
648 int rval;
649 clib_spinlock_lock (&vcm->sessions_lockp);
650 rval = vppcom_session_at_index (p[0], &session);
651 if (PREDICT_FALSE (rval))
652 {
653 if (VPPCOM_DEBUG > 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -0400654 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500655 getpid (), p[0]);
Dave Wallace543852a2017-08-03 02:11:34 -0400656 }
657 else
658 pool_put (vcm->sessions, session);
659 clib_spinlock_unlock (&vcm->sessions_lockp);
660 hash_unset (vcm->session_index_by_vpp_handles, mp->handle);
661 }
662 else
663 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500664 clib_warning ("[%d] couldn't find session key %llx", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400665 mp->handle);
666 rv = -11;
667 }
668
669 rmp = vl_msg_api_alloc (sizeof (*rmp));
670 memset (rmp, 0, sizeof (*rmp));
671
672 rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY);
673 rmp->retval = htonl (rv);
674 rmp->handle = mp->handle;
675 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
676}
677
678static void
679vl_api_reset_session_t_handler (vl_api_reset_session_t * mp)
680{
Dave Wallace543852a2017-08-03 02:11:34 -0400681 session_t *session = 0;
682 vl_api_reset_session_reply_t *rmp;
683 uword *p;
684 int rv = 0;
685
686 p = hash_get (vcm->session_index_by_vpp_handles, mp->handle);
687 if (p)
688 {
689 int rval;
690 clib_spinlock_lock (&vcm->sessions_lockp);
691 rval = vppcom_session_at_index (p[0], &session);
692 if (PREDICT_FALSE (rval))
693 {
694 if (VPPCOM_DEBUG > 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -0400695 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500696 getpid (), p[0]);
Dave Wallace543852a2017-08-03 02:11:34 -0400697 }
698 else
699 pool_put (vcm->sessions, session);
700 clib_spinlock_unlock (&vcm->sessions_lockp);
701 hash_unset (vcm->session_index_by_vpp_handles, mp->handle);
702 }
703 else
704 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500705 clib_warning ("[%d] couldn't find session key %llx", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400706 mp->handle);
707 rv = -11;
708 }
709
710 rmp = vl_msg_api_alloc (sizeof (*rmp));
711 memset (rmp, 0, sizeof (*rmp));
712 rmp->_vl_msg_id = ntohs (VL_API_RESET_SESSION_REPLY);
713 rmp->retval = htonl (rv);
714 rmp->handle = mp->handle;
715 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
716}
717
718static void
Dave Wallace33e002b2017-09-06 01:20:02 -0400719vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp)
Dave Wallace543852a2017-08-03 02:11:34 -0400720{
Dave Wallace543852a2017-08-03 02:11:34 -0400721 session_t *session;
722 u32 session_index;
723 svm_fifo_t *rx_fifo, *tx_fifo;
724 u8 is_cut_thru = 0;
725 int rv;
726
727 if (mp->retval)
728 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500729 clib_warning ("[%d] connect failed: %U", getpid (), format_api_error,
Dave Wallace543852a2017-08-03 02:11:34 -0400730 ntohl (mp->retval));
731 return;
732 }
733
Dave Wallace33e002b2017-09-06 01:20:02 -0400734 session_index = mp->context;
Dave Wallace543852a2017-08-03 02:11:34 -0400735 if (VPPCOM_DEBUG > 1)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500736 clib_warning ("[%d] session_index = %d 0x%08x", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400737 session_index, session_index);
738
739 clib_spinlock_lock (&vcm->sessions_lockp);
740 if (pool_is_free_index (vcm->sessions, session_index))
741 {
742 clib_spinlock_unlock (&vcm->sessions_lockp);
743 if (VPPCOM_DEBUG > 1)
744 clib_warning ("[%d] invalid session, sid %d is closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500745 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400746 return;
747 }
748
749 /* We've been redirected */
750 if (mp->segment_name_length > 0)
751 {
752 static svm_fifo_segment_create_args_t _a;
753 svm_fifo_segment_create_args_t *a = &_a;
754
755 is_cut_thru = 1;
756 memset (a, 0, sizeof (*a));
757 a->segment_name = (char *) mp->segment_name;
758 if (VPPCOM_DEBUG > 1)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500759 clib_warning ("[%d] cut-thru segment: %s", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400760 a->segment_name);
761 rv = svm_fifo_segment_attach (a);
762 vec_reset_length (a->new_segment_indices);
763 if (PREDICT_FALSE (rv))
764 {
Dave Wallacef7f809c2017-10-03 01:48:42 -0400765 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -0400766 clib_warning ("[%d] sm_fifo_segment_attach ('%s') failed",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500767 getpid (), a->segment_name);
Dave Wallace543852a2017-08-03 02:11:34 -0400768 return;
769 }
770 }
771
772 /*
773 * Setup session
774 */
775 if (VPPCOM_DEBUG > 1)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500776 clib_warning ("[%d] client sid %d", getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400777
778 session = pool_elt_at_index (vcm->sessions, session_index);
779 session->is_cut_thru = is_cut_thru;
Dave Wallace33e002b2017-09-06 01:20:02 -0400780 session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address,
781 unix_shared_memory_queue_t *);
Dave Wallace543852a2017-08-03 02:11:34 -0400782
783 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
784 rx_fifo->client_session_index = session_index;
785 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
786 tx_fifo->client_session_index = session_index;
787
788 session->server_rx_fifo = rx_fifo;
789 session->server_tx_fifo = tx_fifo;
790 session->vpp_session_handle = mp->handle;
791 session->state = STATE_CONNECT;
792
793 /* Add it to lookup table */
794 hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
795 clib_spinlock_unlock (&vcm->sessions_lockp);
796}
797
798static void
799vppcom_send_connect_sock (session_t * session, u32 session_index)
800{
Dave Wallace543852a2017-08-03 02:11:34 -0400801 vl_api_connect_sock_t *cmp;
802
803 /* Assumes caller as acquired the spinlock: vcm->sessions_lockp */
804 session->is_server = 0;
805 cmp = vl_msg_api_alloc (sizeof (*cmp));
806 memset (cmp, 0, sizeof (*cmp));
807 cmp->_vl_msg_id = ntohs (VL_API_CONNECT_SOCK);
808 cmp->client_index = vcm->my_client_index;
Dave Wallace33e002b2017-09-06 01:20:02 -0400809 cmp->context = session_index;
Dave Wallace543852a2017-08-03 02:11:34 -0400810
811 if (VPPCOM_DEBUG > 1)
Dave Wallace33e002b2017-09-06 01:20:02 -0400812 clib_warning ("[%d] session_index = %d 0x%08x",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500813 getpid (), session_index, session_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400814
815 cmp->vrf = session->vrf;
Dave Wallace35830af2017-10-09 01:43:42 -0400816 cmp->is_ip4 = session->peer_addr.is_ip4;
817 clib_memcpy (cmp->ip, &session->peer_addr.ip46, sizeof (cmp->ip));
Stevenac1f96d2017-10-24 16:03:58 -0700818 cmp->port = session->peer_port;
Dave Wallace543852a2017-08-03 02:11:34 -0400819 cmp->proto = session->proto;
820 clib_memcpy (cmp->options, session->options, sizeof (cmp->options));
821 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & cmp);
822}
823
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400824static inline void
825vppcom_send_disconnect (session_t * session)
Dave Wallace543852a2017-08-03 02:11:34 -0400826{
Dave Wallace543852a2017-08-03 02:11:34 -0400827 vl_api_disconnect_session_t *dmp;
Dave Wallace543852a2017-08-03 02:11:34 -0400828
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400829 /* Assumes caller as acquired the spinlock: vcm->sessions_lockp */
Dave Wallace543852a2017-08-03 02:11:34 -0400830 dmp = vl_msg_api_alloc (sizeof (*dmp));
831 memset (dmp, 0, sizeof (*dmp));
832 dmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION);
833 dmp->client_index = vcm->my_client_index;
834 dmp->handle = session->vpp_session_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400835 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & dmp);
Dave Wallace543852a2017-08-03 02:11:34 -0400836}
837
838static void
839vl_api_bind_sock_reply_t_handler (vl_api_bind_sock_reply_t * mp)
840{
Dave Wallace543852a2017-08-03 02:11:34 -0400841 session_t *session = 0;
842 int rv;
843
844 if (mp->retval)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500845 clib_warning ("[%d] bind failed: %U", getpid (), format_api_error,
Dave Wallace543852a2017-08-03 02:11:34 -0400846 ntohl (mp->retval));
847
848 ASSERT (vcm->bind_session_index != ~0);
849
850 clib_spinlock_lock (&vcm->sessions_lockp);
851 rv = vppcom_session_at_index (vcm->bind_session_index, &session);
852 if (rv == VPPCOM_OK)
853 {
854 session->vpp_session_handle = mp->handle;
855 hash_set (vcm->session_index_by_vpp_handles, mp->handle,
856 vcm->bind_session_index);
857 session->state = mp->retval ? STATE_FAILED : STATE_LISTEN;
858 vcm->bind_session_index = ~0;
859 }
860 clib_spinlock_unlock (&vcm->sessions_lockp);
861}
862
863static void
864vl_api_unbind_sock_reply_t_handler (vl_api_unbind_sock_reply_t * mp)
865{
Dave Wallace543852a2017-08-03 02:11:34 -0400866 session_t *session = 0;
867 int rv;
868
869 clib_spinlock_lock (&vcm->sessions_lockp);
870 rv = vppcom_session_at_index (vcm->bind_session_index, &session);
Dave Wallace19481612017-09-15 18:47:44 -0400871 if (rv == VPPCOM_OK)
Dave Wallace543852a2017-08-03 02:11:34 -0400872 {
Dave Wallace19481612017-09-15 18:47:44 -0400873 if ((VPPCOM_DEBUG > 1) && (mp->retval))
Dave Wallace2e005bb2017-11-07 01:21:39 -0500874 clib_warning ("[%d] unbind failed: %U", getpid (), format_api_error,
Dave Wallace19481612017-09-15 18:47:44 -0400875 ntohl (mp->retval));
876
877 vcm->bind_session_index = ~0;
878 session->state = STATE_START;
Dave Wallace543852a2017-08-03 02:11:34 -0400879 }
Dave Wallace543852a2017-08-03 02:11:34 -0400880 clib_spinlock_unlock (&vcm->sessions_lockp);
881}
882
883u8 *
884format_ip4_address (u8 * s, va_list * args)
885{
886 u8 *a = va_arg (*args, u8 *);
887 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
888}
889
890u8 *
891format_ip6_address (u8 * s, va_list * args)
892{
893 ip6_address_t *a = va_arg (*args, ip6_address_t *);
894 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
895
896 i_max_n_zero = ARRAY_LEN (a->as_u16);
897 max_n_zeros = 0;
898 i_first_zero = i_max_n_zero;
899 n_zeros = 0;
900 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
901 {
902 u32 is_zero = a->as_u16[i] == 0;
903 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
904 {
905 i_first_zero = i;
906 n_zeros = 0;
907 }
908 n_zeros += is_zero;
909 if ((!is_zero && n_zeros > max_n_zeros)
910 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
911 {
912 i_max_n_zero = i_first_zero;
913 max_n_zeros = n_zeros;
914 i_first_zero = ARRAY_LEN (a->as_u16);
915 n_zeros = 0;
916 }
917 }
918
919 last_double_colon = 0;
920 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
921 {
922 if (i == i_max_n_zero && max_n_zeros > 1)
923 {
924 s = format (s, "::");
925 i += max_n_zeros - 1;
926 last_double_colon = 1;
927 }
928 else
929 {
930 s = format (s, "%s%x",
931 (last_double_colon || i == 0) ? "" : ":",
932 clib_net_to_host_u16 (a->as_u16[i]));
933 last_double_colon = 0;
934 }
935 }
936
937 return s;
938}
939
940/* Format an IP46 address. */
941u8 *
942format_ip46_address (u8 * s, va_list * args)
943{
944 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
945 ip46_type_t type = va_arg (*args, ip46_type_t);
946 int is_ip4 = 1;
947
948 switch (type)
949 {
950 case IP46_TYPE_ANY:
951 is_ip4 = ip46_address_is_ip4 (ip46);
952 break;
953 case IP46_TYPE_IP4:
954 is_ip4 = 1;
955 break;
956 case IP46_TYPE_IP6:
957 is_ip4 = 0;
958 break;
959 }
960
961 return is_ip4 ?
962 format (s, "%U", format_ip4_address, &ip46->ip4) :
963 format (s, "%U", format_ip6_address, &ip46->ip6);
964}
965
966static void
967vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
968{
Dave Wallace543852a2017-08-03 02:11:34 -0400969 vl_api_accept_session_reply_t *rmp;
970 svm_fifo_t *rx_fifo, *tx_fifo;
971 session_t *session;
972 u32 session_index;
973 int rv = 0;
974
975 if (!clib_fifo_free_elts (vcm->client_session_index_fifo))
976 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500977 clib_warning ("[%d] client session queue is full!", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -0400978 rv = VNET_API_ERROR_QUEUE_FULL;
979 goto send_reply;
980 }
981
982 if (VPPCOM_DEBUG > 1)
983 {
984 u8 *ip_str = format (0, "%U", format_ip46_address, &mp->ip, mp->is_ip4);
Dave Wallace2e005bb2017-11-07 01:21:39 -0500985 clib_warning ("[%d] accepted session from: %s:%d", getpid (), ip_str,
Dave Wallace543852a2017-08-03 02:11:34 -0400986 clib_net_to_host_u16 (mp->port));
987 vec_free (ip_str);
988 }
989
990 clib_spinlock_lock (&vcm->sessions_lockp);
991 /* Allocate local session and set it up */
992 pool_get (vcm->sessions, session);
993 memset (session, 0, sizeof (*session));
994 session_index = session - vcm->sessions;
995
996 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
997 rx_fifo->client_session_index = session_index;
998 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
999 tx_fifo->client_session_index = session_index;
1000
1001 session->server_rx_fifo = rx_fifo;
1002 session->server_tx_fifo = tx_fifo;
Dave Wallace33e002b2017-09-06 01:20:02 -04001003 session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address,
1004 unix_shared_memory_queue_t *);
Dave Wallace543852a2017-08-03 02:11:34 -04001005 session->state = STATE_ACCEPT;
1006 session->is_cut_thru = 0;
Dave Wallace19481612017-09-15 18:47:44 -04001007 session->is_server = 1;
Stevenac1f96d2017-10-24 16:03:58 -07001008 session->peer_port = mp->port;
Dave Wallace35830af2017-10-09 01:43:42 -04001009 session->peer_addr.is_ip4 = mp->is_ip4;
1010 clib_memcpy (&session->peer_addr.ip46, mp->ip,
1011 sizeof (session->peer_addr.ip46));
Dave Wallace543852a2017-08-03 02:11:34 -04001012
1013 /* Add it to lookup table */
1014 hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
1015
1016 clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04001017 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04001018
1019 /*
1020 * Send accept reply to vpp
1021 */
1022send_reply:
1023 rmp = vl_msg_api_alloc (sizeof (*rmp));
1024 memset (rmp, 0, sizeof (*rmp));
1025 rmp->_vl_msg_id = ntohs (VL_API_ACCEPT_SESSION_REPLY);
1026 rmp->retval = htonl (rv);
1027 rmp->handle = mp->handle;
1028 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
1029}
1030
1031/*
1032 * Acting as server for redirected connect requests
1033 */
1034static void
1035vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp)
1036{
1037 static svm_fifo_segment_create_args_t _a;
1038 svm_fifo_segment_create_args_t *a = &_a;
Dave Wallace543852a2017-08-03 02:11:34 -04001039 u32 session_index;
1040 svm_fifo_segment_private_t *seg;
1041 unix_shared_memory_queue_t *client_q;
Dave Wallace33e002b2017-09-06 01:20:02 -04001042 vl_api_connect_session_reply_t *rmp;
Dave Wallace543852a2017-08-03 02:11:34 -04001043 session_t *session = 0;
1044 int rv = 0;
1045 svm_fifo_t *rx_fifo;
1046 svm_fifo_t *tx_fifo;
1047 unix_shared_memory_queue_t *event_q = 0;
1048
Dave Wallacef7f809c2017-10-03 01:48:42 -04001049 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04001050 if (!clib_fifo_free_elts (vcm->client_session_index_fifo))
1051 {
1052 if (VPPCOM_DEBUG > 1)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001053 clib_warning ("[%d] client session queue is full!", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04001054 rv = VNET_API_ERROR_QUEUE_FULL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001055 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04001056 goto send_reply;
1057 }
1058
1059 /* Create the segment */
1060 memset (a, 0, sizeof (*a));
1061 a->segment_name = (char *) format ((u8 *) a->segment_name, "%d:segment%d%c",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001062 getpid (), vcm->unique_segment_index++,
Dave Wallace543852a2017-08-03 02:11:34 -04001063 0);
1064 a->segment_size = vcm->cfg.segment_size;
1065 a->preallocated_fifo_pairs = vcm->cfg.preallocated_fifo_pairs;
1066 a->rx_fifo_size = vcm->cfg.rx_fifo_size;
1067 a->tx_fifo_size = vcm->cfg.tx_fifo_size;
1068
1069 rv = svm_fifo_segment_create (a);
1070 if (PREDICT_FALSE (rv))
1071 {
1072 if (VPPCOM_DEBUG > 1)
1073 clib_warning ("[%d] svm_fifo_segment_create ('%s') failed",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001074 getpid (), a->segment_name);
Dave Wallace543852a2017-08-03 02:11:34 -04001075 vec_reset_length (a->new_segment_indices);
1076 rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
1077 goto send_reply;
1078 }
1079
1080 if (VPPCOM_DEBUG > 1)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001081 clib_warning ("[%d] created segment '%s'", getpid (), a->segment_name);
Dave Wallace543852a2017-08-03 02:11:34 -04001082
Dave Wallace543852a2017-08-03 02:11:34 -04001083 pool_get (vcm->sessions, session);
1084 memset (session, 0, sizeof (*session));
1085 session_index = session - vcm->sessions;
1086
1087 session->sm_seg_index = a->new_segment_indices[0];
1088 vec_reset_length (a->new_segment_indices);
1089
Florin Corasc87c91d2017-08-16 19:55:49 -07001090 seg = svm_fifo_segment_get_segment (session->sm_seg_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001091 rx_fifo = session->server_rx_fifo =
1092 svm_fifo_segment_alloc_fifo (seg, vcm->cfg.rx_fifo_size,
1093 FIFO_SEGMENT_RX_FREELIST);
1094 if (PREDICT_FALSE (!session->server_rx_fifo))
1095 {
1096 svm_fifo_segment_delete (seg);
1097 clib_warning ("[%d] rx fifo alloc failed, size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001098 getpid (), vcm->cfg.rx_fifo_size, vcm->cfg.rx_fifo_size);
Dave Wallace543852a2017-08-03 02:11:34 -04001099 rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
1100 clib_spinlock_unlock (&vcm->sessions_lockp);
1101 goto send_reply;
1102 }
1103
1104 tx_fifo = session->server_tx_fifo =
1105 svm_fifo_segment_alloc_fifo (seg, vcm->cfg.tx_fifo_size,
1106 FIFO_SEGMENT_TX_FREELIST);
1107 if (PREDICT_FALSE (!session->server_tx_fifo))
1108 {
1109 svm_fifo_segment_delete (seg);
1110 if (VPPCOM_DEBUG > 1)
1111 clib_warning ("[%d] tx fifo alloc failed, size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001112 getpid (), vcm->cfg.tx_fifo_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001113 vcm->cfg.tx_fifo_size);
1114 rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
1115 clib_spinlock_unlock (&vcm->sessions_lockp);
1116 goto send_reply;
1117 }
1118
1119 session->server_rx_fifo->master_session_index = session_index;
1120 session->server_tx_fifo->master_session_index = session_index;
1121 session->client_queue_address = mp->client_queue_address;
1122 session->is_cut_thru = 1;
1123 session->is_server = 1;
Stevenac1f96d2017-10-24 16:03:58 -07001124 session->peer_port = mp->port;
Dave Wallace35830af2017-10-09 01:43:42 -04001125 session->peer_addr.is_ip4 = mp->is_ip4;
1126 clib_memcpy (&session->peer_addr.ip46, mp->ip,
1127 sizeof (session->peer_addr.ip46));
Dave Wallace543852a2017-08-03 02:11:34 -04001128 {
1129 void *oldheap;
1130 ssvm_shared_header_t *sh = seg->ssvm.sh;
1131
1132 ssvm_lock_non_recursive (sh, 1);
1133 oldheap = ssvm_push_heap (sh);
Dave Wallace33e002b2017-09-06 01:20:02 -04001134 event_q = session->vpp_event_queue =
Dave Wallace543852a2017-08-03 02:11:34 -04001135 unix_shared_memory_queue_init (vcm->cfg.event_queue_size,
1136 sizeof (session_fifo_event_t),
Dave Wallace2e005bb2017-11-07 01:21:39 -05001137 getpid (), 0 /* signal not sent */ );
Dave Wallace543852a2017-08-03 02:11:34 -04001138 ssvm_pop_heap (oldheap);
1139 ssvm_unlock_non_recursive (sh);
1140 }
Dave Wallace6d5c4cd2017-08-15 16:56:29 -04001141
Dave Wallace543852a2017-08-03 02:11:34 -04001142 session->state = STATE_ACCEPT;
Dave Wallace543852a2017-08-03 02:11:34 -04001143 clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
Dave Wallace2e005bb2017-11-07 01:21:39 -05001144 if (VPPCOM_DEBUG > 1)
1145 clib_warning
1146 ("[%d] Connected cut-thru to client: sid %d, clib_fifo_elts %u!",
1147 getpid (), session_index,
1148 clib_fifo_elts (vcm->client_session_index_fifo));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001149 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04001150
1151send_reply:
1152 rmp = vl_msg_api_alloc (sizeof (*rmp));
1153 memset (rmp, 0, sizeof (*rmp));
1154
Dave Wallace33e002b2017-09-06 01:20:02 -04001155 rmp->_vl_msg_id = ntohs (VL_API_CONNECT_SESSION_REPLY);
Dave Wallace543852a2017-08-03 02:11:34 -04001156 rmp->context = mp->context;
Dave Wallace543852a2017-08-03 02:11:34 -04001157 rmp->retval = htonl (rv);
1158 rmp->segment_name_length = vec_len (a->segment_name);
1159 clib_memcpy (rmp->segment_name, a->segment_name, vec_len (a->segment_name));
1160 vec_reset_length (a->segment_name);
1161
1162 if (event_q)
1163 {
1164 rmp->vpp_event_queue_address = pointer_to_uword (event_q);
1165 rmp->server_rx_fifo = pointer_to_uword (rx_fifo);
1166 rmp->server_tx_fifo = pointer_to_uword (tx_fifo);
1167 }
1168 client_q =
1169 uword_to_pointer (mp->client_queue_address, unix_shared_memory_queue_t *);
1170
1171 ASSERT (client_q);
1172 vl_msg_api_send_shmem (client_q, (u8 *) & rmp);
1173}
1174
1175static void
1176vppcom_send_bind_sock (session_t * session)
1177{
Dave Wallace543852a2017-08-03 02:11:34 -04001178 vl_api_bind_sock_t *bmp;
1179
1180 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
1181 session->is_server = 1;
1182 bmp = vl_msg_api_alloc (sizeof (*bmp));
1183 memset (bmp, 0, sizeof (*bmp));
1184
1185 bmp->_vl_msg_id = ntohs (VL_API_BIND_SOCK);
1186 bmp->client_index = vcm->my_client_index;
1187 bmp->context = htonl (0xfeedface);
1188 bmp->vrf = session->vrf;
Dave Wallace35830af2017-10-09 01:43:42 -04001189 bmp->is_ip4 = session->lcl_addr.is_ip4;
1190 clib_memcpy (bmp->ip, &session->lcl_addr.ip46, sizeof (bmp->ip));
Stevenac1f96d2017-10-24 16:03:58 -07001191 bmp->port = session->lcl_port;
Dave Wallace543852a2017-08-03 02:11:34 -04001192 bmp->proto = session->proto;
1193 clib_memcpy (bmp->options, session->options, sizeof (bmp->options));
1194 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
1195}
1196
1197static void
1198vppcom_send_unbind_sock (u32 session_index)
1199{
Dave Wallace543852a2017-08-03 02:11:34 -04001200 vl_api_unbind_sock_t *ump;
1201 session_t *session = 0;
1202 int rv;
1203
1204 clib_spinlock_lock (&vcm->sessions_lockp);
1205 rv = vppcom_session_at_index (session_index, &session);
1206 if (PREDICT_FALSE (rv))
1207 {
1208 clib_spinlock_unlock (&vcm->sessions_lockp);
1209 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001210 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001211 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001212 return;
1213 }
1214
1215 ump = vl_msg_api_alloc (sizeof (*ump));
1216 memset (ump, 0, sizeof (*ump));
1217
1218 ump->_vl_msg_id = ntohs (VL_API_UNBIND_SOCK);
1219 ump->client_index = vcm->my_client_index;
1220 ump->handle = session->vpp_session_handle;
1221 clib_spinlock_unlock (&vcm->sessions_lockp);
1222 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & ump);
1223}
1224
1225static int
1226vppcom_session_unbind_cut_thru (session_t * session)
1227{
1228 svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
1229 svm_fifo_segment_private_t *seg;
1230 int rv = VPPCOM_OK;
1231
1232 seg = vec_elt_at_index (sm->segments, session->sm_seg_index);
1233 svm_fifo_segment_free_fifo (seg, session->server_rx_fifo,
1234 FIFO_SEGMENT_RX_FREELIST);
1235 svm_fifo_segment_free_fifo (seg, session->server_tx_fifo,
1236 FIFO_SEGMENT_TX_FREELIST);
1237 svm_fifo_segment_delete (seg);
1238
1239 return rv;
1240}
1241
1242static int
1243vppcom_session_unbind (u32 session_index)
1244{
Dave Wallace543852a2017-08-03 02:11:34 -04001245 int rv;
1246
1247 clib_spinlock_lock (&vcm->sessions_lockp);
1248 if (PREDICT_FALSE (pool_is_free_index (vcm->sessions, session_index)))
1249 {
1250 clib_spinlock_unlock (&vcm->sessions_lockp);
1251 if (VPPCOM_DEBUG > 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001252 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001253 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001254 return VPPCOM_EBADFD;
1255 }
1256 clib_spinlock_unlock (&vcm->sessions_lockp);
1257
1258 vcm->bind_session_index = session_index;
1259 vppcom_send_unbind_sock (session_index);
1260 rv = vppcom_wait_for_session_state_change (session_index, STATE_START,
1261 vcm->cfg.session_timeout);
1262 if (PREDICT_FALSE (rv))
1263 {
1264 vcm->bind_session_index = ~0;
1265 if (VPPCOM_DEBUG > 0)
1266 clib_warning ("[%d] server unbind timed out, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001267 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -04001268 return rv;
1269 }
1270 return VPPCOM_OK;
1271}
1272
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001273static inline int
Dave Wallace543852a2017-08-03 02:11:34 -04001274vppcom_session_disconnect (u32 session_index)
1275{
Dave Wallace543852a2017-08-03 02:11:34 -04001276 int rv;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001277 session_t *session;
Dave Wallace543852a2017-08-03 02:11:34 -04001278
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001279 clib_spinlock_lock (&vcm->sessions_lockp);
1280 rv = vppcom_session_at_index (session_index, &session);
Dave Wallace543852a2017-08-03 02:11:34 -04001281 if (PREDICT_FALSE (rv))
1282 {
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001283 clib_spinlock_unlock (&vcm->sessions_lockp);
1284 if (VPPCOM_DEBUG > 1)
1285 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001286 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001287 return rv;
1288 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001289
1290 if (!session->is_cut_thru)
1291 {
1292 vppcom_send_disconnect (session);
1293 clib_spinlock_unlock (&vcm->sessions_lockp);
1294
1295 rv = vppcom_wait_for_session_state_change (session_index,
1296 STATE_DISCONNECT, 1.0);
1297 if ((VPPCOM_DEBUG > 0) && (rv < 0))
1298 clib_warning ("[%d] disconnect (session %d) failed, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001299 getpid (), session_index, vppcom_retval_str (rv), rv);
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001300 }
1301 else
1302 clib_spinlock_unlock (&vcm->sessions_lockp);
1303
Dave Wallace543852a2017-08-03 02:11:34 -04001304 return VPPCOM_OK;
1305}
1306
1307#define foreach_sock_msg \
1308_(SESSION_ENABLE_DISABLE_REPLY, session_enable_disable_reply) \
1309_(BIND_SOCK_REPLY, bind_sock_reply) \
1310_(UNBIND_SOCK_REPLY, unbind_sock_reply) \
1311_(ACCEPT_SESSION, accept_session) \
1312_(CONNECT_SOCK, connect_sock) \
Dave Wallace33e002b2017-09-06 01:20:02 -04001313_(CONNECT_SESSION_REPLY, connect_session_reply) \
Dave Wallace543852a2017-08-03 02:11:34 -04001314_(DISCONNECT_SESSION, disconnect_session) \
1315_(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \
1316_(RESET_SESSION, reset_session) \
1317_(APPLICATION_ATTACH_REPLY, application_attach_reply) \
1318_(APPLICATION_DETACH_REPLY, application_detach_reply) \
1319_(MAP_ANOTHER_SEGMENT, map_another_segment)
1320
1321static void
1322vppcom_api_hookup (void)
1323{
1324#define _(N,n) \
1325 vl_msg_api_set_handlers(VL_API_##N, #n, \
1326 vl_api_##n##_t_handler, \
1327 vl_noop_handler, \
1328 vl_api_##n##_t_endian, \
1329 vl_api_##n##_t_print, \
1330 sizeof(vl_api_##n##_t), 1);
1331 foreach_sock_msg;
1332#undef _
1333}
1334
1335static void
1336vppcom_cfg_init (vppcom_cfg_t * vcl_cfg)
1337{
1338 ASSERT (vcl_cfg);
1339
1340 vcl_cfg->heapsize = (256ULL << 20);
1341 vcl_cfg->segment_baseva = 0x200000000ULL;
1342 vcl_cfg->segment_size = (256 << 20);
1343 vcl_cfg->add_segment_size = (128 << 20);
1344 vcl_cfg->preallocated_fifo_pairs = 8;
1345 vcl_cfg->rx_fifo_size = (1 << 20);
1346 vcl_cfg->tx_fifo_size = (1 << 20);
1347 vcl_cfg->event_queue_size = 2048;
1348 vcl_cfg->listen_queue_size = CLIB_CACHE_LINE_BYTES / sizeof (u32);
1349 vcl_cfg->app_timeout = 10 * 60.0;
1350 vcl_cfg->session_timeout = 10 * 60.0;
1351 vcl_cfg->accept_timeout = 60.0;
1352}
1353
1354static void
1355vppcom_cfg_heapsize (char *conf_fname)
1356{
Dave Wallace543852a2017-08-03 02:11:34 -04001357 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
1358 FILE *fp;
1359 char inbuf[4096];
1360 int argc = 1;
1361 char **argv = NULL;
1362 char *arg = NULL;
1363 char *p;
1364 int i;
1365 u8 *sizep;
1366 u32 size;
Dave Wallace2e005bb2017-11-07 01:21:39 -05001367 void *vcl_mem;
1368 void *heap;
Dave Wallace543852a2017-08-03 02:11:34 -04001369
1370 fp = fopen (conf_fname, "r");
1371 if (fp == NULL)
1372 {
1373 if (VPPCOM_DEBUG > 0)
1374 fprintf (stderr, "open configuration file '%s' failed\n", conf_fname);
1375 goto defaulted;
1376 }
1377 argv = calloc (1, sizeof (char *));
1378 if (argv == NULL)
1379 goto defaulted;
1380
1381 while (1)
1382 {
1383 if (fgets (inbuf, 4096, fp) == 0)
1384 break;
1385 p = strtok (inbuf, " \t\n");
1386 while (p != NULL)
1387 {
1388 if (*p == '#')
1389 break;
1390 argc++;
1391 char **tmp = realloc (argv, argc * sizeof (char *));
1392 if (tmp == NULL)
Chris Lukeab7b8d92017-09-07 07:40:13 -04001393 goto defaulted;
Dave Wallace543852a2017-08-03 02:11:34 -04001394 argv = tmp;
1395 arg = strndup (p, 1024);
1396 if (arg == NULL)
Chris Lukeab7b8d92017-09-07 07:40:13 -04001397 goto defaulted;
Dave Wallace543852a2017-08-03 02:11:34 -04001398 argv[argc - 1] = arg;
1399 p = strtok (NULL, " \t\n");
1400 }
1401 }
1402
1403 fclose (fp);
Chris Lukeab7b8d92017-09-07 07:40:13 -04001404 fp = NULL;
Dave Wallace543852a2017-08-03 02:11:34 -04001405
1406 char **tmp = realloc (argv, (argc + 1) * sizeof (char *));
1407 if (tmp == NULL)
1408 goto defaulted;
1409 argv = tmp;
1410 argv[argc] = NULL;
1411
1412 /*
1413 * Look for and parse the "heapsize" config parameter.
1414 * Manual since none of the clib infra has been bootstrapped yet.
1415 *
1416 * Format: heapsize <nn>[mM][gG]
1417 */
1418
1419 for (i = 1; i < (argc - 1); i++)
1420 {
1421 if (!strncmp (argv[i], "heapsize", 8))
1422 {
1423 sizep = (u8 *) argv[i + 1];
1424 size = 0;
1425 while (*sizep >= '0' && *sizep <= '9')
1426 {
1427 size *= 10;
1428 size += *sizep++ - '0';
1429 }
1430 if (size == 0)
1431 {
1432 if (VPPCOM_DEBUG > 0)
1433 clib_warning ("[%d] parse error '%s %s', "
1434 "using default heapsize %lld (0x%llx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001435 getpid (), argv[i], argv[i + 1],
Dave Wallace543852a2017-08-03 02:11:34 -04001436 vcl_cfg->heapsize, vcl_cfg->heapsize);
1437 goto defaulted;
1438 }
1439
1440 if (*sizep == 'g' || *sizep == 'G')
1441 vcl_cfg->heapsize = size << 30;
1442 else if (*sizep == 'm' || *sizep == 'M')
1443 vcl_cfg->heapsize = size << 20;
1444 else
1445 {
1446 if (VPPCOM_DEBUG > 0)
1447 clib_warning ("[%d] parse error '%s %s', "
1448 "using default heapsize %lld (0x%llx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001449 getpid (), argv[i], argv[i + 1],
Dave Wallace543852a2017-08-03 02:11:34 -04001450 vcl_cfg->heapsize, vcl_cfg->heapsize);
1451 goto defaulted;
1452 }
1453 }
1454 }
1455
1456defaulted:
Chris Lukeab7b8d92017-09-07 07:40:13 -04001457 if (fp != NULL)
1458 fclose (fp);
1459 if (argv != NULL)
1460 free (argv);
Dave Wallacee7fa24e2017-11-07 13:07:44 -05001461
Dave Wallace2e005bb2017-11-07 01:21:39 -05001462 vcl_mem = mmap (0, vcl_cfg->heapsize, PROT_READ | PROT_WRITE,
1463 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
Dave Wallacee7fa24e2017-11-07 13:07:44 -05001464 if (vcl_mem <= 0)
1465 {
1466 clib_unix_error ("[%d] ERROR: mmap(0, %lld == 0x%llx, "
1467 "PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, "
1468 "-1, 0) failed!",
1469 getpid (), vcl_cfg->heapsize, vcl_cfg->heapsize);
1470 return;
1471 }
Dave Wallace2e005bb2017-11-07 01:21:39 -05001472 heap = clib_mem_init (vcl_mem, vcl_cfg->heapsize);
1473 if (!heap)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001474 {
Dave Wallacee7fa24e2017-11-07 13:07:44 -05001475 clib_warning ("[%d] ERROR: clib_mem_init() failed!", getpid ());
1476 return;
Dave Wallace2e005bb2017-11-07 01:21:39 -05001477 }
Dave Wallacee7fa24e2017-11-07 13:07:44 -05001478 vcl_mem = clib_mem_alloc (sizeof (_vppcom_main));
1479 if (!vcl_mem)
1480 {
1481 clib_warning ("[%d] ERROR: clib_mem_alloc() failed!", getpid ());
1482 return;
1483 }
1484
1485 clib_memcpy (vcl_mem, &_vppcom_main, sizeof (_vppcom_main));
1486 vcm = vcl_mem;
1487
1488 if (VPPCOM_DEBUG > 0)
1489 clib_warning ("[%d] allocated VCL heap = %p, size %lld (0x%llx)",
1490 getpid (), heap, vcl_cfg->heapsize, vcl_cfg->heapsize);
Dave Wallace543852a2017-08-03 02:11:34 -04001491}
1492
1493static void
1494vppcom_cfg_read (char *conf_fname)
1495{
Dave Wallace543852a2017-08-03 02:11:34 -04001496 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
1497 int fd;
1498 unformat_input_t _input, *input = &_input;
1499 unformat_input_t _line_input, *line_input = &_line_input;
1500 u8 vc_cfg_input = 0;
1501 u8 *chroot_path;
1502 struct stat s;
1503 u32 uid, gid;
1504
1505 fd = open (conf_fname, O_RDONLY);
1506 if (fd < 0)
1507 {
1508 if (VPPCOM_DEBUG > 0)
1509 clib_warning ("[%d] open configuration file '%s' failed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001510 getpid (), conf_fname);
Dave Wallace543852a2017-08-03 02:11:34 -04001511 goto file_done;
1512 }
1513
1514 if (fstat (fd, &s) < 0)
1515 {
1516 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001517 clib_warning ("[%d] failed to stat `%s'", getpid (), conf_fname);
Dave Wallace543852a2017-08-03 02:11:34 -04001518 goto file_done;
1519 }
1520
1521 if (!(S_ISREG (s.st_mode) || S_ISLNK (s.st_mode)))
1522 {
1523 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001524 clib_warning ("[%d] not a regular file `%s'", getpid (), conf_fname);
Dave Wallace543852a2017-08-03 02:11:34 -04001525 goto file_done;
1526 }
1527
Dave Barach59b25652017-09-10 15:04:27 -04001528 unformat_init_clib_file (input, fd);
Dave Wallace543852a2017-08-03 02:11:34 -04001529
1530 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1531 {
Chris Lukeb2bcad62017-09-18 08:51:22 -04001532 (void) unformat_user (input, unformat_line_input, line_input);
Dave Wallace543852a2017-08-03 02:11:34 -04001533 unformat_skip_white_space (line_input);
1534
Dave Wallace8af20542017-10-26 03:29:30 -04001535 if (unformat (line_input, "vcl {"))
Dave Wallace543852a2017-08-03 02:11:34 -04001536 {
1537 vc_cfg_input = 1;
1538 continue;
1539 }
1540
1541 if (vc_cfg_input)
1542 {
1543 if (unformat (line_input, "heapsize %s", &chroot_path))
1544 {
1545 vec_terminate_c_string (chroot_path);
1546 if (VPPCOM_DEBUG > 0)
1547 clib_warning ("[%d] configured heapsize %s, "
1548 "actual heapsize %lld (0x%llx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001549 getpid (), chroot_path, vcl_cfg->heapsize,
Dave Wallace543852a2017-08-03 02:11:34 -04001550 vcl_cfg->heapsize);
1551 vec_free (chroot_path);
1552 }
1553 else if (unformat (line_input, "api-prefix %s", &chroot_path))
1554 {
1555 vec_terminate_c_string (chroot_path);
1556 vl_set_memory_root_path ((char *) chroot_path);
1557 if (VPPCOM_DEBUG > 0)
1558 clib_warning ("[%d] configured api-prefix %s",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001559 getpid (), chroot_path);
Dave Wallace543852a2017-08-03 02:11:34 -04001560 chroot_path = 0; /* Don't vec_free() it! */
1561 }
1562 else if (unformat (line_input, "uid %d", &uid))
1563 {
1564 vl_set_memory_uid (uid);
1565 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001566 clib_warning ("[%d] configured uid %d", getpid (), uid);
Dave Wallace543852a2017-08-03 02:11:34 -04001567 }
1568 else if (unformat (line_input, "gid %d", &gid))
1569 {
1570 vl_set_memory_gid (gid);
1571 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001572 clib_warning ("[%d] configured gid %d", getpid (), gid);
Dave Wallace543852a2017-08-03 02:11:34 -04001573 }
Dave Wallace8af20542017-10-26 03:29:30 -04001574 else if (unformat (line_input, "segment-baseva 0x%lx",
Dave Wallace543852a2017-08-03 02:11:34 -04001575 &vcl_cfg->segment_baseva))
1576 {
1577 if (VPPCOM_DEBUG > 0)
Dave Wallace8af20542017-10-26 03:29:30 -04001578 clib_warning ("[%d] configured segment_baseva 0x%lx",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001579 getpid (), vcl_cfg->segment_baseva);
Dave Wallace543852a2017-08-03 02:11:34 -04001580 }
1581 else if (unformat (line_input, "segment-size 0x%lx",
1582 &vcl_cfg->segment_size))
1583 {
1584 if (VPPCOM_DEBUG > 0)
1585 clib_warning ("[%d] configured segment_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001586 getpid (), vcl_cfg->segment_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001587 vcl_cfg->segment_size);
1588 }
1589 else if (unformat (line_input, "segment-size %ld",
1590 &vcl_cfg->segment_size))
1591 {
1592 if (VPPCOM_DEBUG > 0)
1593 clib_warning ("[%d] configured segment_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001594 getpid (), vcl_cfg->segment_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001595 vcl_cfg->segment_size);
1596 }
1597 else if (unformat (line_input, "add-segment-size 0x%lx",
1598 &vcl_cfg->add_segment_size))
1599 {
1600 if (VPPCOM_DEBUG > 0)
1601 clib_warning
1602 ("[%d] configured add_segment_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001603 getpid (), vcl_cfg->add_segment_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001604 vcl_cfg->add_segment_size);
1605 }
1606 else if (unformat (line_input, "add-segment-size %ld",
1607 &vcl_cfg->add_segment_size))
1608 {
1609 if (VPPCOM_DEBUG > 0)
1610 clib_warning
1611 ("[%d] configured add_segment_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001612 getpid (), vcl_cfg->add_segment_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001613 vcl_cfg->add_segment_size);
1614 }
1615 else if (unformat (line_input, "preallocated-fifo-pairs %d",
1616 &vcl_cfg->preallocated_fifo_pairs))
1617 {
1618 if (VPPCOM_DEBUG > 0)
1619 clib_warning ("[%d] configured preallocated_fifo_pairs "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001620 "%d (0x%x)", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -04001621 vcl_cfg->preallocated_fifo_pairs,
1622 vcl_cfg->preallocated_fifo_pairs);
1623 }
1624 else if (unformat (line_input, "rx-fifo-size 0x%lx",
1625 &vcl_cfg->rx_fifo_size))
1626 {
1627 if (VPPCOM_DEBUG > 0)
1628 clib_warning ("[%d] configured rx_fifo_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001629 getpid (), vcl_cfg->rx_fifo_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001630 vcl_cfg->rx_fifo_size);
1631 }
1632 else if (unformat (line_input, "rx-fifo-size %ld",
1633 &vcl_cfg->rx_fifo_size))
1634 {
1635 if (VPPCOM_DEBUG > 0)
1636 clib_warning ("[%d] configured rx_fifo_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001637 getpid (), vcl_cfg->rx_fifo_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001638 vcl_cfg->rx_fifo_size);
1639 }
1640 else if (unformat (line_input, "tx-fifo-size 0x%lx",
1641 &vcl_cfg->tx_fifo_size))
1642 {
1643 if (VPPCOM_DEBUG > 0)
1644 clib_warning ("[%d] configured tx_fifo_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001645 getpid (), vcl_cfg->tx_fifo_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001646 vcl_cfg->tx_fifo_size);
1647 }
1648 else if (unformat (line_input, "tx-fifo-size %ld",
1649 &vcl_cfg->tx_fifo_size))
1650 {
1651 if (VPPCOM_DEBUG > 0)
1652 clib_warning ("[%d] configured tx_fifo_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001653 getpid (), vcl_cfg->tx_fifo_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001654 vcl_cfg->tx_fifo_size);
1655 }
1656 else if (unformat (line_input, "event-queue-size 0x%lx",
1657 &vcl_cfg->event_queue_size))
1658 {
1659 if (VPPCOM_DEBUG > 0)
1660 clib_warning ("[%d] configured event_queue_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001661 getpid (), vcl_cfg->event_queue_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001662 vcl_cfg->event_queue_size);
1663 }
1664 else if (unformat (line_input, "event-queue-size %ld",
1665 &vcl_cfg->event_queue_size))
1666 {
1667 if (VPPCOM_DEBUG > 0)
1668 clib_warning ("[%d] configured event_queue_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001669 getpid (), vcl_cfg->event_queue_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001670 vcl_cfg->event_queue_size);
1671 }
1672 else if (unformat (line_input, "listen-queue-size 0x%lx",
1673 &vcl_cfg->listen_queue_size))
1674 {
1675 if (VPPCOM_DEBUG > 0)
1676 clib_warning ("[%d] configured listen_queue_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001677 getpid (), vcl_cfg->listen_queue_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001678 vcl_cfg->listen_queue_size);
1679 }
1680 else if (unformat (line_input, "listen-queue-size %ld",
1681 &vcl_cfg->listen_queue_size))
1682 {
1683 if (VPPCOM_DEBUG > 0)
1684 clib_warning ("[%d] configured listen_queue_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001685 getpid (), vcl_cfg->listen_queue_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001686 vcl_cfg->listen_queue_size);
1687 }
1688 else if (unformat (line_input, "app-timeout %f",
1689 &vcl_cfg->app_timeout))
1690 {
1691 if (VPPCOM_DEBUG > 0)
1692 clib_warning ("[%d] configured app_timeout %f",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001693 getpid (), vcl_cfg->app_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001694 }
1695 else if (unformat (line_input, "session-timeout %f",
1696 &vcl_cfg->session_timeout))
1697 {
1698 if (VPPCOM_DEBUG > 0)
1699 clib_warning ("[%d] configured session_timeout %f",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001700 getpid (), vcl_cfg->session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001701 }
1702 else if (unformat (line_input, "accept-timeout %f",
1703 &vcl_cfg->accept_timeout))
1704 {
1705 if (VPPCOM_DEBUG > 0)
1706 clib_warning ("[%d] configured accept_timeout %f",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001707 getpid (), vcl_cfg->accept_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001708 }
Dave Wallace774169b2017-11-01 20:07:40 -04001709 else if (unformat (line_input, "app-proxy-transport-tcp"))
Dave Wallace8af20542017-10-26 03:29:30 -04001710 {
Dave Wallace774169b2017-11-01 20:07:40 -04001711 vcl_cfg->app_proxy_transport_tcp = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001712 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001713 clib_warning ("[%d] configured app_proxy_transport_tcp (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001714 getpid (), vcl_cfg->app_proxy_transport_tcp);
Dave Wallace8af20542017-10-26 03:29:30 -04001715 }
Dave Wallace774169b2017-11-01 20:07:40 -04001716 else if (unformat (line_input, "app-proxy-transport-udp"))
Dave Wallace8af20542017-10-26 03:29:30 -04001717 {
Dave Wallace774169b2017-11-01 20:07:40 -04001718 vcl_cfg->app_proxy_transport_udp = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001719 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001720 clib_warning ("[%d] configured app_proxy_transport_udp (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001721 getpid (), vcl_cfg->app_proxy_transport_udp);
Dave Wallace8af20542017-10-26 03:29:30 -04001722 }
Dave Wallace774169b2017-11-01 20:07:40 -04001723 else if (unformat (line_input, "app-scope-local"))
Dave Wallace8af20542017-10-26 03:29:30 -04001724 {
Dave Wallace774169b2017-11-01 20:07:40 -04001725 vcl_cfg->app_scope_local = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001726 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001727 clib_warning ("[%d] configured app_scope_local (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001728 getpid (), vcl_cfg->app_scope_local);
Dave Wallace774169b2017-11-01 20:07:40 -04001729 }
1730 else if (unformat (line_input, "app-scope-global"))
1731 {
1732 vcl_cfg->app_scope_global = 1;
1733 if (VPPCOM_DEBUG > 0)
1734 clib_warning ("[%d] configured app_scope_global (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001735 getpid (), vcl_cfg->app_scope_global);
Dave Wallace8af20542017-10-26 03:29:30 -04001736 }
1737 else if (unformat (line_input, "namespace-secret %lu",
1738 &vcl_cfg->namespace_secret))
1739 {
1740 if (VPPCOM_DEBUG > 0)
1741 clib_warning
1742 ("[%d] configured namespace_secret %lu (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001743 getpid (), vcl_cfg->namespace_secret,
Dave Wallace8af20542017-10-26 03:29:30 -04001744 vcl_cfg->namespace_secret);
1745 }
1746 else if (unformat (line_input, "namespace-id %v",
1747 &vcl_cfg->namespace_id))
1748 {
1749 vl_api_application_attach_t *mp;
1750 u32 max_nsid_vec_len = sizeof (mp->namespace_id) - 1;
1751 u32 nsid_vec_len = vec_len (vcl_cfg->namespace_id);
1752 if (nsid_vec_len > max_nsid_vec_len)
1753 {
1754 _vec_len (vcl_cfg->namespace_id) = max_nsid_vec_len;
1755 if (VPPCOM_DEBUG > 0)
1756 clib_warning ("[%d] configured namespace_id is too long,"
Dave Wallace2e005bb2017-11-07 01:21:39 -05001757 " truncated to %d characters!", getpid (),
Dave Wallace8af20542017-10-26 03:29:30 -04001758 max_nsid_vec_len);
1759 }
1760
1761 if (VPPCOM_DEBUG > 0)
1762 clib_warning ("[%d] configured namespace_id %v",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001763 getpid (), vcl_cfg->namespace_id);
Dave Wallace8af20542017-10-26 03:29:30 -04001764 }
Dave Wallace543852a2017-08-03 02:11:34 -04001765 else if (unformat (line_input, "}"))
1766 {
1767 vc_cfg_input = 0;
1768 if (VPPCOM_DEBUG > 0)
1769 clib_warning ("[%d] completed parsing vppcom config!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001770 getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04001771 goto input_done;
1772 }
1773 else
1774 {
1775 if (line_input->buffer[line_input->index] != '#')
1776 {
1777 clib_warning ("[%d] Unknown vppcom config option: '%s'",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001778 getpid (), (char *)
Dave Wallace543852a2017-08-03 02:11:34 -04001779 &line_input->buffer[line_input->index]);
1780 }
1781 }
1782 }
1783 }
1784
1785input_done:
1786 unformat_free (input);
1787
1788file_done:
Chris Lukeab7b8d92017-09-07 07:40:13 -04001789 if (fd >= 0)
Dave Wallace543852a2017-08-03 02:11:34 -04001790 close (fd);
1791}
1792
1793/*
1794 * VPPCOM Public API functions
1795 */
1796int
1797vppcom_app_create (char *app_name)
1798{
Dave Wallace543852a2017-08-03 02:11:34 -04001799 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
1800 u8 *heap;
1801 mheap_t *h;
1802 int rv;
1803
1804 if (!vcm->init)
1805 {
1806 char *conf_fname;
Dave Wallace8af20542017-10-26 03:29:30 -04001807 char *env_var_str;
Dave Wallace543852a2017-08-03 02:11:34 -04001808
1809 vcm->init = 1;
Dave Wallace543852a2017-08-03 02:11:34 -04001810 vppcom_cfg_init (vcl_cfg);
Dave Wallace498b3a52017-11-09 13:00:34 -05001811 env_var_str = getenv (VPPCOM_ENV_DEBUG);
1812 if (env_var_str)
1813 {
1814 u32 tmp;
1815 if (sscanf (env_var_str, "%u", &tmp) != 1)
1816 clib_warning ("[%d] Invalid debug level specified in "
1817 "the environment variable "
1818 VPPCOM_ENV_DEBUG
1819 " (%s)!\n", getpid (), env_var_str);
1820 else
1821 {
1822 vcm->debug = tmp;
1823 clib_warning ("[%d] configured debug level (%u) from "
1824 VPPCOM_ENV_DEBUG "!", getpid (), vcm->debug);
1825 }
1826 }
Dave Wallace8af20542017-10-26 03:29:30 -04001827 conf_fname = getenv (VPPCOM_ENV_CONF);
Dave Wallace543852a2017-08-03 02:11:34 -04001828 if (!conf_fname)
1829 {
1830 conf_fname = VPPCOM_CONF_DEFAULT;
1831 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001832 clib_warning ("[%d] getenv '%s' failed!", getpid (),
Dave Wallace8af20542017-10-26 03:29:30 -04001833 VPPCOM_ENV_CONF);
Dave Wallace543852a2017-08-03 02:11:34 -04001834 }
1835 vppcom_cfg_heapsize (conf_fname);
Dave Wallace2e005bb2017-11-07 01:21:39 -05001836 clib_fifo_validate (vcm->client_session_index_fifo,
1837 vcm->cfg.listen_queue_size);
Dave Wallace543852a2017-08-03 02:11:34 -04001838 vppcom_cfg_read (conf_fname);
Dave Wallace8af20542017-10-26 03:29:30 -04001839 env_var_str = getenv (VPPCOM_ENV_APP_NAMESPACE_ID);
1840 if (env_var_str)
1841 {
1842 u32 ns_id_vec_len = strlen (env_var_str);
1843
1844 vec_reset_length (vcm->cfg.namespace_id);
1845 vec_validate (vcm->cfg.namespace_id, ns_id_vec_len - 1);
1846 clib_memcpy (vcm->cfg.namespace_id, env_var_str, ns_id_vec_len);
1847
1848 if (VPPCOM_DEBUG > 0)
1849 clib_warning ("[%d] configured namespace_id (%v) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001850 VPPCOM_ENV_APP_NAMESPACE_ID "!", getpid (),
Dave Wallace8af20542017-10-26 03:29:30 -04001851 vcm->cfg.namespace_id);
1852 }
1853 env_var_str = getenv (VPPCOM_ENV_APP_NAMESPACE_SECRET);
1854 if (env_var_str)
1855 {
1856 u64 tmp;
1857 if (sscanf (env_var_str, "%lu", &tmp) != 1)
1858 clib_warning ("[%d] Invalid namespace secret specified in "
1859 "the environment variable "
1860 VPPCOM_ENV_APP_NAMESPACE_SECRET
Dave Wallace2e005bb2017-11-07 01:21:39 -05001861 " (%s)!\n", getpid (), env_var_str);
Dave Wallace8af20542017-10-26 03:29:30 -04001862 else
1863 {
1864 vcm->cfg.namespace_secret = tmp;
1865 if (VPPCOM_DEBUG > 0)
1866 clib_warning ("[%d] configured namespace secret (%lu) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001867 VPPCOM_ENV_APP_NAMESPACE_ID "!", getpid (),
Dave Wallace8af20542017-10-26 03:29:30 -04001868 vcm->cfg.namespace_secret);
1869 }
1870 }
Dave Wallace774169b2017-11-01 20:07:40 -04001871 if (getenv (VPPCOM_ENV_APP_PROXY_TRANSPORT_TCP))
Dave Wallace8af20542017-10-26 03:29:30 -04001872 {
Dave Wallace774169b2017-11-01 20:07:40 -04001873 vcm->cfg.app_proxy_transport_tcp = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001874 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001875 clib_warning ("[%d] configured app_proxy_transport_tcp (%u) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001876 VPPCOM_ENV_APP_PROXY_TRANSPORT_TCP "!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04001877 vcm->cfg.app_proxy_transport_tcp);
Dave Wallace8af20542017-10-26 03:29:30 -04001878 }
Dave Wallace774169b2017-11-01 20:07:40 -04001879 if (getenv (VPPCOM_ENV_APP_PROXY_TRANSPORT_UDP))
Dave Wallace8af20542017-10-26 03:29:30 -04001880 {
Dave Wallace774169b2017-11-01 20:07:40 -04001881 vcm->cfg.app_proxy_transport_udp = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001882 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001883 clib_warning ("[%d] configured app_proxy_transport_udp (%u) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001884 VPPCOM_ENV_APP_PROXY_TRANSPORT_UDP "!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04001885 vcm->cfg.app_proxy_transport_udp);
1886 }
1887 if (getenv (VPPCOM_ENV_APP_SCOPE_LOCAL))
1888 {
1889 vcm->cfg.app_scope_local = 1;
1890 if (VPPCOM_DEBUG > 0)
1891 clib_warning ("[%d] configured app_scope_local (%u) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001892 VPPCOM_ENV_APP_SCOPE_LOCAL "!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04001893 vcm->cfg.app_scope_local);
1894 }
1895 if (getenv (VPPCOM_ENV_APP_SCOPE_GLOBAL))
1896 {
1897 vcm->cfg.app_scope_global = 1;
1898 if (VPPCOM_DEBUG > 0)
1899 clib_warning ("[%d] configured app_scope_global (%u) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001900 VPPCOM_ENV_APP_SCOPE_GLOBAL "!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04001901 vcm->cfg.app_scope_global);
Dave Wallace8af20542017-10-26 03:29:30 -04001902 }
1903
Dave Wallace543852a2017-08-03 02:11:34 -04001904 vcm->bind_session_index = ~0;
1905 vcm->main_cpu = os_get_thread_index ();
1906 heap = clib_mem_get_per_cpu_heap ();
1907 h = mheap_header (heap);
1908
1909 /* make the main heap thread-safe */
1910 h->flags |= MHEAP_FLAG_THREAD_SAFE;
1911
1912 vcm->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
1913
1914 clib_time_init (&vcm->clib_time);
1915 vppcom_init_error_string_table ();
1916 svm_fifo_segment_init (vcl_cfg->segment_baseva,
1917 20 /* timeout in secs */ );
1918 clib_spinlock_init (&vcm->sessions_lockp);
1919 vppcom_api_hookup ();
1920 }
1921
1922 if (vcm->my_client_index == ~0)
1923 {
1924 vcm->app_state = STATE_APP_START;
1925 rv = vppcom_connect_to_vpp (app_name);
1926 if (rv)
1927 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05001928 clib_warning ("[%d] couldn't connect to VPP.", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04001929 return rv;
1930 }
1931
1932 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001933 clib_warning ("[%d] sending session enable", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04001934
1935 rv = vppcom_app_session_enable ();
1936 if (rv)
1937 {
1938 clib_warning ("[%d] vppcom_app_session_enable() failed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001939 getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04001940 return rv;
1941 }
1942
1943 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001944 clib_warning ("[%d] sending app attach", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04001945
1946 rv = vppcom_app_attach ();
1947 if (rv)
1948 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05001949 clib_warning ("[%d] vppcom_app_attach() failed!", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04001950 return rv;
1951 }
Dave Wallace543852a2017-08-03 02:11:34 -04001952
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001953 if (VPPCOM_DEBUG > 0)
1954 clib_warning ("[%d] app_name '%s', my_client_index %d (0x%x)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001955 getpid (), app_name, vcm->my_client_index,
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001956 vcm->my_client_index);
1957 }
Dave Wallace543852a2017-08-03 02:11:34 -04001958
1959 return VPPCOM_OK;
1960}
1961
1962void
1963vppcom_app_destroy (void)
1964{
Dave Wallace543852a2017-08-03 02:11:34 -04001965 int rv;
1966
1967 if (vcm->my_client_index == ~0)
1968 return;
1969
1970 if (VPPCOM_DEBUG > 0)
1971 clib_warning ("[%d] detaching from VPP, my_client_index %d (0x%x)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001972 getpid (), vcm->my_client_index, vcm->my_client_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001973
1974 vppcom_app_detach ();
1975 rv = vppcom_wait_for_app_state_change (STATE_APP_ENABLED);
1976 if (PREDICT_FALSE (rv))
1977 {
1978 if (VPPCOM_DEBUG > 0)
1979 clib_warning ("[%d] application detach timed out, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001980 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -04001981 }
1982 vl_client_disconnect_from_vlib ();
1983 vcm->my_client_index = ~0;
1984 vcm->app_state = STATE_APP_START;
1985}
1986
1987int
1988vppcom_session_create (u32 vrf, u8 proto, u8 is_nonblocking)
1989{
Dave Wallace543852a2017-08-03 02:11:34 -04001990 session_t *session;
1991 u32 session_index;
1992
1993 clib_spinlock_lock (&vcm->sessions_lockp);
1994 pool_get (vcm->sessions, session);
Dave Wallacef7f809c2017-10-03 01:48:42 -04001995 memset (session, 0, sizeof (*session));
Dave Wallace543852a2017-08-03 02:11:34 -04001996 session_index = session - vcm->sessions;
1997
1998 session->vrf = vrf;
1999 session->proto = proto;
2000 session->state = STATE_START;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002001 session->is_nonblocking = is_nonblocking ? 1 : 0;
Dave Wallace543852a2017-08-03 02:11:34 -04002002 clib_spinlock_unlock (&vcm->sessions_lockp);
2003
2004 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002005 clib_warning ("[%d] sid %d", getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002006
2007 return (int) session_index;
2008}
2009
2010int
2011vppcom_session_close (uint32_t session_index)
2012{
Dave Wallace543852a2017-08-03 02:11:34 -04002013 session_t *session = 0;
2014 int rv;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002015 u8 is_server;
2016 u8 is_listen;
2017 u8 is_cut_thru;
2018 u8 is_vep;
2019 u8 is_vep_session;
2020 u32 next_sid;
2021 u32 vep_idx;
2022 session_state_t state;
Dave Wallace543852a2017-08-03 02:11:34 -04002023
2024 clib_spinlock_lock (&vcm->sessions_lockp);
2025 rv = vppcom_session_at_index (session_index, &session);
2026 if (PREDICT_FALSE (rv))
2027 {
Dave Wallace543852a2017-08-03 02:11:34 -04002028 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002029 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002030 getpid (), session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002031 clib_spinlock_unlock (&vcm->sessions_lockp);
2032 goto done;
Dave Wallace543852a2017-08-03 02:11:34 -04002033 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002034 is_server = session->is_server;
2035 is_listen = session->is_listen;
2036 is_cut_thru = session->is_cut_thru;
2037 is_vep = session->is_vep;
2038 is_vep_session = session->is_vep_session;
2039 next_sid = session->vep.next_sid;
2040 vep_idx = session->vep.vep_idx;
2041 state = session->state;
Dave Wallace543852a2017-08-03 02:11:34 -04002042 clib_spinlock_unlock (&vcm->sessions_lockp);
2043
2044 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002045 clib_warning ("[%d] sid %d", getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002046
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002047 if (is_vep)
Dave Wallace543852a2017-08-03 02:11:34 -04002048 {
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002049 while (next_sid != ~0)
Dave Wallace19481612017-09-15 18:47:44 -04002050 {
Dave Wallacef7f809c2017-10-03 01:48:42 -04002051 rv = vppcom_epoll_ctl (session_index, EPOLL_CTL_DEL, next_sid, 0);
Dave Wallace19481612017-09-15 18:47:44 -04002052 if ((VPPCOM_DEBUG > 0) && (rv < 0))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002053 clib_warning ("[%d] EPOLL_CTL_DEL vep_idx %u, sid %u failed, "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002054 "rv = %s (%d)", getpid (), vep_idx, next_sid,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002055 vppcom_retval_str (rv), rv);
2056
2057 clib_spinlock_lock (&vcm->sessions_lockp);
2058 rv = vppcom_session_at_index (session_index, &session);
2059 if (PREDICT_FALSE (rv))
2060 {
2061 if (VPPCOM_DEBUG > 0)
2062 clib_warning
2063 ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002064 getpid (), session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002065 clib_spinlock_unlock (&vcm->sessions_lockp);
2066 goto done;
2067 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002068 next_sid = session->vep.next_sid;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002069 clib_spinlock_unlock (&vcm->sessions_lockp);
2070 }
2071 }
2072 else
2073 {
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002074 if (is_vep_session)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002075 {
Dave Wallacef7f809c2017-10-03 01:48:42 -04002076 rv = vppcom_epoll_ctl (vep_idx, EPOLL_CTL_DEL, session_index, 0);
2077 if ((VPPCOM_DEBUG > 0) && (rv < 0))
2078 clib_warning ("[%d] EPOLL_CTL_DEL vep_idx %u, sid %u failed, "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002079 "rv = %s (%d)", getpid (), vep_idx, session_index,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002080 vppcom_retval_str (rv), rv);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002081 }
2082
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002083 if (is_cut_thru && is_server && (state == STATE_ACCEPT))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002084 {
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002085 rv = vppcom_session_unbind_cut_thru (session);
2086 if ((VPPCOM_DEBUG > 0) && (rv < 0))
2087 clib_warning ("[%d] unbind cut-thru (session %d) failed, "
2088 "rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002089 getpid (), session_index,
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002090 vppcom_retval_str (rv), rv);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002091 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002092 else if (is_server && is_listen)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002093 {
2094 rv = vppcom_session_unbind (session_index);
2095 if ((VPPCOM_DEBUG > 0) && (rv < 0))
2096 clib_warning ("[%d] unbind (session %d) failed, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002097 getpid (), session_index,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002098 vppcom_retval_str (rv), rv);
2099 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002100 else if (state == STATE_CONNECT)
2101 if (vppcom_session_disconnect (session_index))
2102 goto done;
Dave Wallace19481612017-09-15 18:47:44 -04002103 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002104 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04002105 pool_put_index (vcm->sessions, session_index);
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002106 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002107done:
Dave Wallace543852a2017-08-03 02:11:34 -04002108 return rv;
2109}
2110
2111int
2112vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep)
2113{
Dave Wallace543852a2017-08-03 02:11:34 -04002114 session_t *session = 0;
2115 int rv;
2116
2117 if (!ep || !ep->ip)
2118 return VPPCOM_EINVAL;
2119
2120 clib_spinlock_lock (&vcm->sessions_lockp);
2121 rv = vppcom_session_at_index (session_index, &session);
2122 if (PREDICT_FALSE (rv))
2123 {
2124 clib_spinlock_unlock (&vcm->sessions_lockp);
2125 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002126 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002127 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002128 return rv;
2129 }
2130
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002131 if (session->is_vep)
2132 {
2133 clib_spinlock_unlock (&vcm->sessions_lockp);
2134 if (VPPCOM_DEBUG > 0)
2135 clib_warning ("[%d] invalid session, sid (%u) is an epoll session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002136 getpid (), session_index);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002137 return VPPCOM_EBADFD;
2138 }
2139
Dave Wallace543852a2017-08-03 02:11:34 -04002140 session->vrf = ep->vrf;
Dave Wallace35830af2017-10-09 01:43:42 -04002141 session->lcl_addr.is_ip4 = ep->is_ip4;
2142 session->lcl_addr.ip46 = to_ip46 (!ep->is_ip4, ep->ip);
Stevenac1f96d2017-10-24 16:03:58 -07002143 session->lcl_port = ep->port;
2144
2145 if (VPPCOM_DEBUG > 0)
2146 clib_warning ("[%d] sid %d, bound to lcl address %U lcl port %u",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002147 getpid (), session_index, format_ip46_address,
Stevenac1f96d2017-10-24 16:03:58 -07002148 &session->lcl_addr.ip46, session->lcl_addr.is_ip4,
2149 clib_net_to_host_u16 (session->lcl_port));
Dave Wallace543852a2017-08-03 02:11:34 -04002150
2151 clib_spinlock_unlock (&vcm->sessions_lockp);
2152 return VPPCOM_OK;
2153}
2154
2155int
Dave Wallace33e002b2017-09-06 01:20:02 -04002156vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len)
Dave Wallace543852a2017-08-03 02:11:34 -04002157{
Dave Wallace33e002b2017-09-06 01:20:02 -04002158 session_t *listen_session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04002159 int rv;
2160
2161 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallace33e002b2017-09-06 01:20:02 -04002162 rv = vppcom_session_at_index (listen_session_index, &listen_session);
Dave Wallace543852a2017-08-03 02:11:34 -04002163 if (PREDICT_FALSE (rv))
2164 {
2165 clib_spinlock_unlock (&vcm->sessions_lockp);
2166 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002167 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002168 getpid (), listen_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002169 return rv;
2170 }
2171
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002172 if (listen_session->is_vep)
2173 {
2174 clib_spinlock_unlock (&vcm->sessions_lockp);
2175 if (VPPCOM_DEBUG > 0)
2176 clib_warning ("[%d] invalid session, sid (%u) is an epoll session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002177 getpid (), listen_session_index);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002178 return VPPCOM_EBADFD;
2179 }
2180
Dave Wallacee695cb42017-11-02 22:04:42 -04002181 if (listen_session->is_listen)
2182 {
2183 clib_spinlock_unlock (&vcm->sessions_lockp);
2184 if (VPPCOM_DEBUG > 0)
2185 clib_warning ("[%d] sid (%u) is already in listen state!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002186 getpid (), listen_session_index);
Dave Wallacee695cb42017-11-02 22:04:42 -04002187 return VPPCOM_OK;
2188 }
2189
Dave Wallace543852a2017-08-03 02:11:34 -04002190 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002191 clib_warning ("[%d] sid %d", getpid (), listen_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002192
2193 ASSERT (vcm->bind_session_index == ~0);
Dave Wallace33e002b2017-09-06 01:20:02 -04002194 vcm->bind_session_index = listen_session_index;
2195 vppcom_send_bind_sock (listen_session);
Dave Wallace543852a2017-08-03 02:11:34 -04002196 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace33e002b2017-09-06 01:20:02 -04002197 rv =
2198 vppcom_wait_for_session_state_change (listen_session_index, STATE_LISTEN,
2199 vcm->cfg.session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04002200 if (PREDICT_FALSE (rv))
2201 {
2202 vcm->bind_session_index = ~0;
2203 if (VPPCOM_DEBUG > 0)
2204 clib_warning ("[%d] server listen timed out, rv = %d (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002205 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -04002206 return rv;
2207 }
2208
2209 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallace33e002b2017-09-06 01:20:02 -04002210 rv = vppcom_session_at_index (listen_session_index, &listen_session);
Dave Wallace543852a2017-08-03 02:11:34 -04002211 if (PREDICT_FALSE (rv))
2212 {
2213 clib_spinlock_unlock (&vcm->sessions_lockp);
2214 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002215 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002216 getpid (), listen_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002217 return rv;
2218 }
Dave Wallace33e002b2017-09-06 01:20:02 -04002219 listen_session->is_listen = 1;
Dave Wallace543852a2017-08-03 02:11:34 -04002220 clib_fifo_validate (vcm->client_session_index_fifo, q_len);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002221 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04002222
2223 return VPPCOM_OK;
2224}
2225
2226int
2227vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep,
2228 double wait_for_time)
2229{
Dave Wallace33e002b2017-09-06 01:20:02 -04002230 session_t *listen_session = 0;
2231 session_t *client_session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04002232 u32 client_session_index;
2233 int rv;
2234 f64 wait_for;
2235
2236 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallace33e002b2017-09-06 01:20:02 -04002237 rv = vppcom_session_at_index (listen_session_index, &listen_session);
Dave Wallace543852a2017-08-03 02:11:34 -04002238 if (PREDICT_FALSE (rv))
2239 {
2240 clib_spinlock_unlock (&vcm->sessions_lockp);
2241 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002242 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002243 getpid (), listen_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002244 return rv;
2245 }
2246
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002247 if (listen_session->is_vep)
2248 {
2249 clib_spinlock_unlock (&vcm->sessions_lockp);
2250 if (VPPCOM_DEBUG > 0)
2251 clib_warning ("[%d] invalid session, sid (%u) is an epoll session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002252 getpid (), listen_session_index);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002253 return VPPCOM_EBADFD;
2254 }
2255
Dave Wallace33e002b2017-09-06 01:20:02 -04002256 if (listen_session->state != STATE_LISTEN)
Dave Wallace543852a2017-08-03 02:11:34 -04002257 {
2258 clib_spinlock_unlock (&vcm->sessions_lockp);
2259 if (VPPCOM_DEBUG > 0)
2260 clib_warning ("[%d] session not in listen state, state = %s",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002261 getpid (),
Dave Wallace33e002b2017-09-06 01:20:02 -04002262 vppcom_session_state_str (listen_session->state));
Dave Wallace543852a2017-08-03 02:11:34 -04002263 return VPPCOM_EBADFD;
2264 }
Dave Wallace33e002b2017-09-06 01:20:02 -04002265 wait_for = listen_session->is_nonblocking ? 0 :
Dave Wallace543852a2017-08-03 02:11:34 -04002266 (wait_for_time < 0) ? vcm->cfg.accept_timeout : wait_for_time;
2267
2268 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002269 clib_warning ("[%d] sid %d: %s (%d)", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -04002270 listen_session_index,
Dave Wallace33e002b2017-09-06 01:20:02 -04002271 vppcom_session_state_str (listen_session->state),
2272 listen_session->state);
Dave Wallace543852a2017-08-03 02:11:34 -04002273 clib_spinlock_unlock (&vcm->sessions_lockp);
2274
2275 while (1)
2276 {
2277 rv = vppcom_wait_for_client_session_index (wait_for);
2278 if (rv)
2279 {
2280 if ((VPPCOM_DEBUG > 0))
2281 clib_warning ("[%d] sid %d, accept timed out, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002282 getpid (), listen_session_index,
Dave Wallace543852a2017-08-03 02:11:34 -04002283 vppcom_retval_str (rv), rv);
2284 if ((wait_for == 0) || (wait_for_time > 0))
2285 return rv;
2286 }
2287 else
2288 break;
2289 }
2290
Dave Wallace543852a2017-08-03 02:11:34 -04002291 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002292 clib_fifo_sub1 (vcm->client_session_index_fifo, client_session_index);
Dave Wallace33e002b2017-09-06 01:20:02 -04002293 rv = vppcom_session_at_index (client_session_index, &client_session);
Dave Wallace543852a2017-08-03 02:11:34 -04002294 ASSERT (rv == VPPCOM_OK);
Dave Wallace35830af2017-10-09 01:43:42 -04002295 ASSERT (client_session->peer_addr.is_ip4 ==
2296 listen_session->lcl_addr.is_ip4);
Dave Wallace543852a2017-08-03 02:11:34 -04002297
2298 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002299 clib_warning ("[%d] Got a request: client sid %d", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -04002300 client_session_index);
2301
Stevenac1f96d2017-10-24 16:03:58 -07002302 // Copy the lcl information from the listening session to the client session
2303 // client_session->lcl_port = listen_session->lcl_port;
2304 // client_session->lcl_addr = listen_session->lcl_addr;
2305
Dave Wallace33e002b2017-09-06 01:20:02 -04002306 ep->vrf = client_session->vrf;
2307 ep->is_cut_thru = client_session->is_cut_thru;
Dave Wallace35830af2017-10-09 01:43:42 -04002308 ep->is_ip4 = client_session->peer_addr.is_ip4;
Stevenac1f96d2017-10-24 16:03:58 -07002309 ep->port = client_session->peer_port;
Dave Wallace35830af2017-10-09 01:43:42 -04002310 if (client_session->peer_addr.is_ip4)
2311 clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip4,
2312 sizeof (ip4_address_t));
Dave Wallace33e002b2017-09-06 01:20:02 -04002313 else
Dave Wallace35830af2017-10-09 01:43:42 -04002314 clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip6,
2315 sizeof (ip6_address_t));
Stevenac1f96d2017-10-24 16:03:58 -07002316 if (VPPCOM_DEBUG > 0)
2317 clib_warning ("[%d] sid %d, accepted peer address %U peer port %u",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002318 getpid (), client_session_index, format_ip46_address,
Stevenac1f96d2017-10-24 16:03:58 -07002319 &client_session->peer_addr.ip46,
2320 client_session->peer_addr.is_ip4,
2321 clib_net_to_host_u16 (client_session->peer_port));
Dave Wallace543852a2017-08-03 02:11:34 -04002322 clib_spinlock_unlock (&vcm->sessions_lockp);
2323 return (int) client_session_index;
2324}
2325
2326int
2327vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep)
2328{
Dave Wallace543852a2017-08-03 02:11:34 -04002329 session_t *session = 0;
2330 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002331
2332 clib_spinlock_lock (&vcm->sessions_lockp);
2333 rv = vppcom_session_at_index (session_index, &session);
2334 if (PREDICT_FALSE (rv))
2335 {
2336 clib_spinlock_unlock (&vcm->sessions_lockp);
2337 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002338 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002339 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002340 return rv;
2341 }
2342
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002343 if (session->is_vep)
2344 {
2345 clib_spinlock_unlock (&vcm->sessions_lockp);
2346 if (VPPCOM_DEBUG > 0)
2347 clib_warning ("[%d] invalid session, sid (%u) is an epoll session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002348 getpid (), session_index);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002349 return VPPCOM_EBADFD;
2350 }
2351
Dave Wallace543852a2017-08-03 02:11:34 -04002352 if (session->state == STATE_CONNECT)
2353 {
2354 clib_spinlock_unlock (&vcm->sessions_lockp);
2355 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002356 clib_warning ("[%d] session, sid (%u) already connected!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002357 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002358 return VPPCOM_OK;
2359 }
2360
2361 session->vrf = server_ep->vrf;
Dave Wallace35830af2017-10-09 01:43:42 -04002362 session->peer_addr.is_ip4 = server_ep->is_ip4;
2363 session->peer_addr.ip46 = to_ip46 (!server_ep->is_ip4, server_ep->ip);
Stevenac1f96d2017-10-24 16:03:58 -07002364 session->peer_port = server_ep->port;
Dave Wallace543852a2017-08-03 02:11:34 -04002365
2366 if (VPPCOM_DEBUG > 0)
2367 {
2368 u8 *ip_str = format (0, "%U", format_ip46_address,
Dave Wallace35830af2017-10-09 01:43:42 -04002369 &session->peer_addr.ip46,
2370 session->peer_addr.is_ip4);
Dave Wallace7876d392017-10-19 03:53:57 -04002371 clib_warning ("[%d] connect sid %d to %s server port %d proto %s",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002372 getpid (), session_index, ip_str,
Stevenac1f96d2017-10-24 16:03:58 -07002373 clib_net_to_host_u16 (session->peer_port),
Dave Wallace7876d392017-10-19 03:53:57 -04002374 session->proto ? "UDP" : "TCP");
Dave Wallace543852a2017-08-03 02:11:34 -04002375 vec_free (ip_str);
2376 }
2377
2378 vppcom_send_connect_sock (session, session_index);
2379 clib_spinlock_unlock (&vcm->sessions_lockp);
2380 rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
2381 vcm->cfg.session_timeout);
2382 if (PREDICT_FALSE (rv))
2383 {
2384 if (VPPCOM_DEBUG > 0)
2385 clib_warning ("[%d] connect timed out, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002386 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -04002387 return rv;
2388 }
Dave Wallace7876d392017-10-19 03:53:57 -04002389 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002390 clib_warning ("[%d] sid %d connected!", getpid (), session_index);
Dave Wallace7876d392017-10-19 03:53:57 -04002391
Dave Wallace543852a2017-08-03 02:11:34 -04002392 return VPPCOM_OK;
2393}
2394
Steven58f464e2017-10-25 12:33:12 -07002395static inline int
2396vppcom_session_read_internal (uint32_t session_index, void *buf, int n,
2397 u8 peek)
Dave Wallace543852a2017-08-03 02:11:34 -04002398{
Dave Wallace543852a2017-08-03 02:11:34 -04002399 session_t *session = 0;
2400 svm_fifo_t *rx_fifo;
2401 int n_read = 0;
2402 int rv;
2403 char *fifo_str;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002404 u32 poll_et;
Dave Wallace543852a2017-08-03 02:11:34 -04002405
2406 ASSERT (buf);
2407
2408 clib_spinlock_lock (&vcm->sessions_lockp);
2409 rv = vppcom_session_at_index (session_index, &session);
2410 if (PREDICT_FALSE (rv))
2411 {
2412 clib_spinlock_unlock (&vcm->sessions_lockp);
2413 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002414 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002415 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002416 return rv;
2417 }
2418
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002419 if (session->is_vep)
2420 {
2421 clib_spinlock_unlock (&vcm->sessions_lockp);
2422 if (VPPCOM_DEBUG > 0)
2423 clib_warning ("[%d] invalid session, sid (%u) is an epoll session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002424 getpid (), session_index);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002425 return VPPCOM_EBADFD;
2426 }
2427
Dave Wallace33e002b2017-09-06 01:20:02 -04002428 if (session->state == STATE_DISCONNECT)
Dave Wallace543852a2017-08-03 02:11:34 -04002429 {
Dave Wallace543852a2017-08-03 02:11:34 -04002430 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace33e002b2017-09-06 01:20:02 -04002431 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002432 clib_warning ("[%d] sid (%u) has been closed by remote peer!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002433 getpid (), session_index);
Dave Wallace33e002b2017-09-06 01:20:02 -04002434 return VPPCOM_ECONNRESET;
Dave Wallace543852a2017-08-03 02:11:34 -04002435 }
Dave Wallace543852a2017-08-03 02:11:34 -04002436
Dave Wallace33e002b2017-09-06 01:20:02 -04002437 rx_fifo = ((!session->is_cut_thru || session->is_server) ?
2438 session->server_rx_fifo : session->server_tx_fifo);
2439 fifo_str = ((!session->is_cut_thru || session->is_server) ?
2440 "server_rx_fifo" : "server_tx_fifo");
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002441 poll_et = EPOLLET & session->vep.ev.events;
2442 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002443
2444 do
2445 {
Steven58f464e2017-10-25 12:33:12 -07002446 if (peek)
2447 n_read = svm_fifo_peek (rx_fifo, 0, n, buf);
2448 else
2449 n_read = svm_fifo_dequeue_nowait (rx_fifo, n, buf);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002450 }
2451 while (!session->is_nonblocking && (n_read <= 0));
2452
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002453 if (poll_et && (n_read <= 0))
2454 {
2455 clib_spinlock_lock (&vcm->sessions_lockp);
2456 session->vep.et_mask |= EPOLLIN;
2457 clib_spinlock_unlock (&vcm->sessions_lockp);
2458 }
Dave Wallace543852a2017-08-03 02:11:34 -04002459
Dave Wallacef7f809c2017-10-03 01:48:42 -04002460 if ((VPPCOM_DEBUG > 2) && (n_read > 0))
Dave Wallace2e005bb2017-11-07 01:21:39 -05002461 clib_warning ("[%d] sid %d, read %d bytes from %s (%p)", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -04002462 session_index, n_read, fifo_str, rx_fifo);
Dave Wallace33e002b2017-09-06 01:20:02 -04002463
2464 return (n_read <= 0) ? VPPCOM_EAGAIN : n_read;
Dave Wallace543852a2017-08-03 02:11:34 -04002465}
2466
Steven58f464e2017-10-25 12:33:12 -07002467int
2468vppcom_session_read (uint32_t session_index, void *buf, int n)
2469{
2470 return (vppcom_session_read_internal (session_index, buf, n, 0));
2471}
2472
2473static int
2474vppcom_session_peek (uint32_t session_index, void *buf, int n)
2475{
2476 return (vppcom_session_read_internal (session_index, buf, n, 1));
2477}
2478
Dave Wallace543852a2017-08-03 02:11:34 -04002479static inline int
2480vppcom_session_read_ready (session_t * session, u32 session_index)
2481{
Dave Wallace498b3a52017-11-09 13:00:34 -05002482 svm_fifo_t *rx_fifo = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04002483 int ready = 0;
2484
2485 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002486 if (session->is_vep)
2487 {
2488 clib_spinlock_unlock (&vcm->sessions_lockp);
2489 if (VPPCOM_DEBUG > 0)
2490 clib_warning ("[%d] invalid session, sid (%u) is an epoll session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002491 getpid (), session_index);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002492 return VPPCOM_EBADFD;
2493 }
2494
Dave Wallace33e002b2017-09-06 01:20:02 -04002495 if (session->state == STATE_DISCONNECT)
Dave Wallace543852a2017-08-03 02:11:34 -04002496 {
Dave Wallace33e002b2017-09-06 01:20:02 -04002497 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002498 clib_warning ("[%d] sid (%u) has been closed by remote peer!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002499 getpid (), session_index);
Dave Wallace33e002b2017-09-06 01:20:02 -04002500 return VPPCOM_ECONNRESET;
Dave Wallace543852a2017-08-03 02:11:34 -04002501 }
Dave Wallace33e002b2017-09-06 01:20:02 -04002502
2503 if (session->is_listen)
Dave Wallace543852a2017-08-03 02:11:34 -04002504 ready = clib_fifo_elts (vcm->client_session_index_fifo);
2505 else
2506 {
Dave Wallace33e002b2017-09-06 01:20:02 -04002507 rx_fifo = ((!session->is_cut_thru || session->is_server) ?
2508 session->server_rx_fifo : session->server_tx_fifo);
Dave Wallace543852a2017-08-03 02:11:34 -04002509
Dave Wallace33e002b2017-09-06 01:20:02 -04002510 ready = svm_fifo_max_dequeue (rx_fifo);
Dave Wallace543852a2017-08-03 02:11:34 -04002511 }
2512
Dave Wallace33e002b2017-09-06 01:20:02 -04002513 if (VPPCOM_DEBUG > 3)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002514 clib_warning ("[%d] sid %d, is_listen %u, peek %s (%p), ready = %d",
2515 getpid (), session_index, session->is_listen,
Dave Wallace543852a2017-08-03 02:11:34 -04002516 session->is_server ? "server_rx_fifo" : "server_tx_fifo",
2517 rx_fifo, ready);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002518 if ((session->vep.ev.events & EPOLLET) && (ready == 0))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002519 session->vep.et_mask |= EPOLLIN;
2520
Dave Wallace543852a2017-08-03 02:11:34 -04002521 return ready;
2522}
2523
2524int
2525vppcom_session_write (uint32_t session_index, void *buf, int n)
2526{
Dave Wallace543852a2017-08-03 02:11:34 -04002527 session_t *session = 0;
2528 svm_fifo_t *tx_fifo;
2529 unix_shared_memory_queue_t *q;
2530 session_fifo_event_t evt;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002531 int rv, n_write;
Dave Wallace543852a2017-08-03 02:11:34 -04002532 char *fifo_str;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002533 u32 poll_et;
Dave Wallace543852a2017-08-03 02:11:34 -04002534
2535 ASSERT (buf);
2536
2537 clib_spinlock_lock (&vcm->sessions_lockp);
2538 rv = vppcom_session_at_index (session_index, &session);
2539 if (PREDICT_FALSE (rv))
2540 {
2541 clib_spinlock_unlock (&vcm->sessions_lockp);
2542 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002543 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002544 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002545 return rv;
2546 }
2547
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002548 if (session->is_vep)
2549 {
2550 clib_spinlock_unlock (&vcm->sessions_lockp);
2551 if (VPPCOM_DEBUG > 0)
2552 clib_warning ("[%d] invalid session, sid (%u) is an epoll session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002553 getpid (), session_index);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002554 return VPPCOM_EBADFD;
2555 }
2556
Dave Wallace33e002b2017-09-06 01:20:02 -04002557 if (session->state == STATE_DISCONNECT)
2558 {
2559 clib_spinlock_unlock (&vcm->sessions_lockp);
2560 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002561 clib_warning ("[%d] sid (%u) has been closed by remote peer!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002562 getpid (), session_index);
Dave Wallace33e002b2017-09-06 01:20:02 -04002563 return VPPCOM_ECONNRESET;
2564 }
2565
Dave Wallace543852a2017-08-03 02:11:34 -04002566 tx_fifo = ((!session->is_cut_thru || session->is_server) ?
2567 session->server_tx_fifo : session->server_rx_fifo);
2568 fifo_str = ((!session->is_cut_thru || session->is_server) ?
2569 "server_tx_fifo" : "server_rx_fifo");
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002570 q = session->vpp_event_queue;
2571 poll_et = EPOLLET & session->vep.ev.events;
2572 clib_spinlock_unlock (&vcm->sessions_lockp);
2573
Dave Wallace543852a2017-08-03 02:11:34 -04002574 do
2575 {
Dave Wallacef7f809c2017-10-03 01:48:42 -04002576 n_write = svm_fifo_enqueue_nowait (tx_fifo, n, buf);
Dave Wallace543852a2017-08-03 02:11:34 -04002577 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002578 while (!session->is_nonblocking && (n_write <= 0));
Dave Wallace543852a2017-08-03 02:11:34 -04002579
2580 /* If event wasn't set, add one */
Dave Wallacef7f809c2017-10-03 01:48:42 -04002581 if (!session->is_cut_thru && (n_write > 0) && svm_fifo_set_event (tx_fifo))
Dave Wallace543852a2017-08-03 02:11:34 -04002582 {
2583 int rval;
2584
2585 /* Fabricate TX event, send to vpp */
2586 evt.fifo = tx_fifo;
2587 evt.event_type = FIFO_EVENT_APP_TX;
Dave Wallace543852a2017-08-03 02:11:34 -04002588
Dave Wallace543852a2017-08-03 02:11:34 -04002589 rval = vppcom_session_at_index (session_index, &session);
2590 if (PREDICT_FALSE (rval))
2591 {
Dave Wallace543852a2017-08-03 02:11:34 -04002592 if (VPPCOM_DEBUG > 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002593 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002594 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002595 return rval;
2596 }
Dave Wallace543852a2017-08-03 02:11:34 -04002597 ASSERT (q);
2598 unix_shared_memory_queue_add (q, (u8 *) & evt,
2599 0 /* do wait for mutex */ );
2600 }
2601
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002602 if (poll_et && (n_write <= 0))
2603 {
2604 clib_spinlock_lock (&vcm->sessions_lockp);
2605 session->vep.et_mask |= EPOLLOUT;
2606 clib_spinlock_unlock (&vcm->sessions_lockp);
2607 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002608
Dave Wallace543852a2017-08-03 02:11:34 -04002609 if (VPPCOM_DEBUG > 2)
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002610 {
2611 if (n_write == -2)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002612 clib_warning ("[%d] sid %d, FIFO-FULL %s (%p)", getpid (),
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002613 session_index, fifo_str, tx_fifo);
2614 else
Dave Wallace2e005bb2017-11-07 01:21:39 -05002615 clib_warning ("[%d] sid %d, wrote %d bytes to %s (%p)", getpid (),
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002616 session_index, n_write, fifo_str, tx_fifo);
2617 }
2618 return (n_write < 0) ? VPPCOM_EAGAIN : n_write;
Dave Wallace543852a2017-08-03 02:11:34 -04002619}
2620
2621static inline int
2622vppcom_session_write_ready (session_t * session, u32 session_index)
2623{
Dave Wallace543852a2017-08-03 02:11:34 -04002624 svm_fifo_t *tx_fifo;
Dave Wallace33e002b2017-09-06 01:20:02 -04002625 char *fifo_str;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002626 int ready;
Dave Wallace543852a2017-08-03 02:11:34 -04002627
2628 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002629 if (session->is_vep)
2630 {
2631 clib_spinlock_unlock (&vcm->sessions_lockp);
2632 if (VPPCOM_DEBUG > 0)
2633 clib_warning ("[%d] invalid session, sid (%u) is an epoll session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002634 getpid (), session_index);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002635 return VPPCOM_EBADFD;
2636 }
2637
Dave Wallace33e002b2017-09-06 01:20:02 -04002638 if (session->state == STATE_DISCONNECT)
2639 {
2640 if (VPPCOM_DEBUG > 0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002641 clib_warning ("[%d] sid (%u) has been closed by remote peer!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002642 getpid (), session_index);
Dave Wallace33e002b2017-09-06 01:20:02 -04002643 return VPPCOM_ECONNRESET;
2644 }
2645
Dave Wallace543852a2017-08-03 02:11:34 -04002646 tx_fifo = ((!session->is_cut_thru || session->is_server) ?
2647 session->server_tx_fifo : session->server_rx_fifo);
Dave Wallace33e002b2017-09-06 01:20:02 -04002648 fifo_str = ((!session->is_cut_thru || session->is_server) ?
2649 "server_tx_fifo" : "server_rx_fifo");
Dave Wallace543852a2017-08-03 02:11:34 -04002650
Dave Wallacef7f809c2017-10-03 01:48:42 -04002651 ready = svm_fifo_max_enqueue (tx_fifo);
Dave Wallace543852a2017-08-03 02:11:34 -04002652
Dave Wallace33e002b2017-09-06 01:20:02 -04002653 if (VPPCOM_DEBUG > 3)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002654 clib_warning ("[%d] sid %d, peek %s (%p), ready = %d", getpid (),
Dave Wallacef7f809c2017-10-03 01:48:42 -04002655 session_index, fifo_str, tx_fifo, ready);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002656 if ((session->vep.ev.events & EPOLLET) && (ready == 0))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002657 session->vep.et_mask |= EPOLLOUT;
2658
2659 return ready;
Dave Wallace543852a2017-08-03 02:11:34 -04002660}
2661
2662int
2663vppcom_select (unsigned long n_bits, unsigned long *read_map,
2664 unsigned long *write_map, unsigned long *except_map,
2665 double time_to_wait)
2666{
Dave Wallace543852a2017-08-03 02:11:34 -04002667 u32 session_index;
2668 session_t *session = 0;
2669 int rv, bits_set = 0;
2670 f64 timeout = clib_time_now (&vcm->clib_time) + time_to_wait;
2671 u32 minbits = clib_max (n_bits, BITS (uword));
2672
2673 ASSERT (sizeof (clib_bitmap_t) == sizeof (long int));
2674
Dave Wallace7876d392017-10-19 03:53:57 -04002675 if (n_bits && read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002676 {
2677 clib_bitmap_validate (vcm->rd_bitmap, minbits);
2678 clib_memcpy (vcm->rd_bitmap, read_map, vec_len (vcm->rd_bitmap));
2679 memset (read_map, 0, vec_len (vcm->rd_bitmap));
2680 }
Dave Wallace7876d392017-10-19 03:53:57 -04002681 if (n_bits && write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002682 {
2683 clib_bitmap_validate (vcm->wr_bitmap, minbits);
2684 clib_memcpy (vcm->wr_bitmap, write_map, vec_len (vcm->wr_bitmap));
2685 memset (write_map, 0, vec_len (vcm->wr_bitmap));
2686 }
Dave Wallace7876d392017-10-19 03:53:57 -04002687 if (n_bits && except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002688 {
2689 clib_bitmap_validate (vcm->ex_bitmap, minbits);
2690 clib_memcpy (vcm->ex_bitmap, except_map, vec_len (vcm->ex_bitmap));
2691 memset (except_map, 0, vec_len (vcm->ex_bitmap));
2692 }
2693
2694 do
2695 {
2696 /* *INDENT-OFF* */
Dave Wallacee22aa742017-10-20 12:30:38 -04002697 if (n_bits)
2698 {
2699 if (read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002700 {
Dave Wallacee22aa742017-10-20 12:30:38 -04002701 clib_bitmap_foreach (session_index, vcm->rd_bitmap,
2702 ({
2703 clib_spinlock_lock (&vcm->sessions_lockp);
2704 rv = vppcom_session_at_index (session_index, &session);
2705 if (rv < 0)
2706 {
2707 clib_spinlock_unlock (&vcm->sessions_lockp);
2708 if (VPPCOM_DEBUG > 1)
2709 clib_warning ("[%d] session %d specified in "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002710 "read_map is closed.", getpid (),
Dave Wallacee22aa742017-10-20 12:30:38 -04002711 session_index);
2712 bits_set = VPPCOM_EBADFD;
2713 goto select_done;
2714 }
2715
2716 rv = vppcom_session_read_ready (session, session_index);
2717 clib_spinlock_unlock (&vcm->sessions_lockp);
2718 if (except_map && vcm->ex_bitmap &&
2719 clib_bitmap_get (vcm->ex_bitmap, session_index) &&
2720 (rv < 0))
2721 {
2722 // TBD: clib_warning
2723 clib_bitmap_set_no_check (except_map, session_index, 1);
2724 bits_set++;
2725 }
2726 else if (rv > 0)
2727 {
2728 // TBD: clib_warning
2729 clib_bitmap_set_no_check (read_map, session_index, 1);
2730 bits_set++;
2731 }
2732 }));
Dave Wallace543852a2017-08-03 02:11:34 -04002733 }
2734
Dave Wallacee22aa742017-10-20 12:30:38 -04002735 if (write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002736 {
Dave Wallacee22aa742017-10-20 12:30:38 -04002737 clib_bitmap_foreach (session_index, vcm->wr_bitmap,
2738 ({
2739 clib_spinlock_lock (&vcm->sessions_lockp);
2740 rv = vppcom_session_at_index (session_index, &session);
2741 if (rv < 0)
2742 {
2743 clib_spinlock_unlock (&vcm->sessions_lockp);
2744 if (VPPCOM_DEBUG > 0)
2745 clib_warning ("[%d] session %d specified in "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002746 "write_map is closed.", getpid (),
Dave Wallacee22aa742017-10-20 12:30:38 -04002747 session_index);
2748 bits_set = VPPCOM_EBADFD;
2749 goto select_done;
2750 }
Dave Wallace543852a2017-08-03 02:11:34 -04002751
Dave Wallacee22aa742017-10-20 12:30:38 -04002752 rv = vppcom_session_write_ready (session, session_index);
2753 clib_spinlock_unlock (&vcm->sessions_lockp);
2754 if (write_map && (rv > 0))
2755 {
2756 // TBD: clib_warning
2757 clib_bitmap_set_no_check (write_map, session_index, 1);
2758 bits_set++;
2759 }
2760 }));
Dave Wallace543852a2017-08-03 02:11:34 -04002761 }
2762
Dave Wallacee22aa742017-10-20 12:30:38 -04002763 if (except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002764 {
Dave Wallacee22aa742017-10-20 12:30:38 -04002765 clib_bitmap_foreach (session_index, vcm->ex_bitmap,
2766 ({
2767 clib_spinlock_lock (&vcm->sessions_lockp);
2768 rv = vppcom_session_at_index (session_index, &session);
2769 if (rv < 0)
2770 {
2771 clib_spinlock_unlock (&vcm->sessions_lockp);
2772 if (VPPCOM_DEBUG > 1)
2773 clib_warning ("[%d] session %d specified in "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002774 "except_map is closed.", getpid (),
Dave Wallacee22aa742017-10-20 12:30:38 -04002775 session_index);
2776 bits_set = VPPCOM_EBADFD;
2777 goto select_done;
2778 }
Dave Wallace543852a2017-08-03 02:11:34 -04002779
Dave Wallacee22aa742017-10-20 12:30:38 -04002780 rv = vppcom_session_read_ready (session, session_index);
2781 clib_spinlock_unlock (&vcm->sessions_lockp);
2782 if (rv < 0)
2783 {
2784 // TBD: clib_warning
2785 clib_bitmap_set_no_check (except_map, session_index, 1);
2786 bits_set++;
2787 }
2788 }));
Dave Wallace543852a2017-08-03 02:11:34 -04002789 }
Dave Wallacee22aa742017-10-20 12:30:38 -04002790 }
Dave Wallace543852a2017-08-03 02:11:34 -04002791 /* *INDENT-ON* */
2792 }
2793 while (clib_time_now (&vcm->clib_time) < timeout);
2794
2795select_done:
2796 return (bits_set);
2797}
2798
Dave Wallacef7f809c2017-10-03 01:48:42 -04002799static inline void
2800vep_verify_epoll_chain (u32 vep_idx)
2801{
2802 session_t *session;
2803 vppcom_epoll_t *vep;
2804 int rv;
Dave Wallace498b3a52017-11-09 13:00:34 -05002805 u32 sid = vep_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002806
Dave Wallace498b3a52017-11-09 13:00:34 -05002807 if (VPPCOM_DEBUG <= 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002808 return;
2809
2810 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
2811 rv = vppcom_session_at_index (vep_idx, &session);
2812 if (PREDICT_FALSE (rv))
2813 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05002814 clib_warning ("[%d] ERROR: Invalid vep_idx (%u)!", getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002815 goto done;
2816 }
2817 if (PREDICT_FALSE (!session->is_vep))
2818 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05002819 clib_warning ("[%d] ERROR: vep_idx (%u) is not a vep!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04002820 vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002821 goto done;
2822 }
Dave Wallace498b3a52017-11-09 13:00:34 -05002823 clib_warning ("[%d] vep_idx (%u): Dumping epoll chain\n"
2824 "{\n"
2825 " is_vep = %u\n"
2826 " is_vep_session = %u\n"
2827 " wait_cont_idx = 0x%x (%u)\n"
2828 "}\n", getpid (),
2829 vep_idx, session->is_vep, session->is_vep_session,
2830 session->wait_cont_idx, session->wait_cont_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002831 do
2832 {
2833 vep = &session->vep;
Dave Wallacee695cb42017-11-02 22:04:42 -04002834 sid = vep->next_sid;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002835 if (sid != ~0)
2836 {
2837 rv = vppcom_session_at_index (sid, &session);
2838 if (PREDICT_FALSE (rv))
2839 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05002840 clib_warning ("[%d] ERROR: Invalid sid (%u)!", getpid (), sid);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002841 goto done;
2842 }
2843 if (PREDICT_FALSE (session->is_vep))
Dave Wallace774169b2017-11-01 20:07:40 -04002844 clib_warning ("[%d] ERROR: sid (%u) is a vep!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002845 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002846 else if (PREDICT_FALSE (!session->is_vep_session))
2847 {
Dave Wallace774169b2017-11-01 20:07:40 -04002848 clib_warning ("[%d] ERROR: session (%u) is not a vep session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002849 getpid (), sid);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002850 goto done;
2851 }
2852 if (PREDICT_FALSE (session->vep.vep_idx != vep_idx))
Dave Wallace774169b2017-11-01 20:07:40 -04002853 clib_warning ("[%d] ERROR: session (%u) vep_idx (%u) != "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002854 "vep_idx (%u)!", getpid (),
Dave Wallacef7f809c2017-10-03 01:48:42 -04002855 sid, session->vep.vep_idx, vep_idx);
Dave Wallace498b3a52017-11-09 13:00:34 -05002856 if (session->is_vep_session)
2857 {
2858 clib_warning ("vep_idx[%u]: sid 0x%x (%u)\n"
2859 "{\n"
2860 " next_sid = 0x%x (%u)\n"
2861 " prev_sid = 0x%x (%u)\n"
2862 " vep_idx = 0x%x (%u)\n"
2863 " ev.events = 0x%x\n"
2864 " ev.data.u64 = 0x%llx\n"
2865 " et_mask = 0x%x\n"
2866 "}\n",
2867 vep_idx, sid, sid,
2868 vep->next_sid, vep->next_sid,
2869 vep->prev_sid, vep->prev_sid,
2870 vep->vep_idx, vep->vep_idx,
2871 vep->ev.events, vep->ev.data.u64, vep->et_mask);
2872 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002873 }
2874 }
2875 while (sid != ~0);
2876
2877done:
Dave Wallace498b3a52017-11-09 13:00:34 -05002878 clib_warning ("[%d] vep_idx (%u): Dump complete!\n", getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002879}
2880
2881int
2882vppcom_epoll_create (void)
2883{
Dave Wallacef7f809c2017-10-03 01:48:42 -04002884 session_t *vep_session;
2885 u32 vep_idx;
2886
2887 clib_spinlock_lock (&vcm->sessions_lockp);
2888 pool_get (vcm->sessions, vep_session);
2889 memset (vep_session, 0, sizeof (*vep_session));
2890 vep_idx = vep_session - vcm->sessions;
2891
2892 vep_session->is_vep = 1;
2893 vep_session->vep.vep_idx = ~0;
2894 vep_session->vep.next_sid = ~0;
2895 vep_session->vep.prev_sid = ~0;
2896 vep_session->wait_cont_idx = ~0;
2897 clib_spinlock_unlock (&vcm->sessions_lockp);
2898
2899 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002900 clib_warning ("[%d] Created vep_idx %u!", getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002901
2902 return (vep_idx);
2903}
2904
2905int
2906vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index,
2907 struct epoll_event *event)
2908{
Dave Wallacef7f809c2017-10-03 01:48:42 -04002909 session_t *vep_session;
2910 session_t *session;
2911 int rv;
2912
2913 if (vep_idx == session_index)
2914 {
2915 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04002916 clib_warning ("[%d] ERROR: vep_idx == session_index (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002917 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002918 return VPPCOM_EINVAL;
2919 }
2920
2921 clib_spinlock_lock (&vcm->sessions_lockp);
2922 rv = vppcom_session_at_index (vep_idx, &vep_session);
2923 if (PREDICT_FALSE (rv))
2924 {
2925 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04002926 clib_warning ("[%d] ERROR: Invalid vep_idx (%u)!", vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002927 goto done;
2928 }
2929 if (PREDICT_FALSE (!vep_session->is_vep))
2930 {
2931 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04002932 clib_warning ("[%d] ERROR: vep_idx (%u) is not a vep!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002933 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002934 rv = VPPCOM_EINVAL;
2935 goto done;
2936 }
2937
2938 ASSERT (vep_session->vep.vep_idx == ~0);
2939 ASSERT (vep_session->vep.prev_sid == ~0);
2940
2941 rv = vppcom_session_at_index (session_index, &session);
2942 if (PREDICT_FALSE (rv))
2943 {
2944 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04002945 clib_warning ("[%d] ERROR: Invalid session_index (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002946 getpid (), session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002947 goto done;
2948 }
2949 if (PREDICT_FALSE (session->is_vep))
2950 {
2951 if (VPPCOM_DEBUG > 0)
2952 clib_warning ("ERROR: session_index (%u) is a vep!", vep_idx);
2953 rv = VPPCOM_EINVAL;
2954 goto done;
2955 }
2956
2957 switch (op)
2958 {
2959 case EPOLL_CTL_ADD:
2960 if (PREDICT_FALSE (!event))
2961 {
Dave Wallace774169b2017-11-01 20:07:40 -04002962 clib_warning ("[%d] ERROR: EPOLL_CTL_ADD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002963 "epoll_event structure!", getpid ());
Dave Wallacef7f809c2017-10-03 01:48:42 -04002964 rv = VPPCOM_EINVAL;
2965 goto done;
2966 }
2967 if (vep_session->vep.next_sid != ~0)
2968 {
2969 session_t *next_session;
2970 rv = vppcom_session_at_index (vep_session->vep.next_sid,
2971 &next_session);
2972 if (PREDICT_FALSE (rv))
2973 {
2974 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04002975 clib_warning ("[%d] ERROR: EPOLL_CTL_ADD: Invalid "
2976 "vep.next_sid (%u) on vep_idx (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002977 getpid (), vep_session->vep.next_sid, vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002978 goto done;
2979 }
2980 ASSERT (next_session->vep.prev_sid == vep_idx);
2981 next_session->vep.prev_sid = session_index;
2982 }
2983 session->vep.next_sid = vep_session->vep.next_sid;
2984 session->vep.prev_sid = vep_idx;
2985 session->vep.vep_idx = vep_idx;
2986 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2987 session->vep.ev = *event;
2988 session->is_vep_session = 1;
2989 vep_session->vep.next_sid = session_index;
2990 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04002991 clib_warning ("[%d] EPOLL_CTL_ADD: vep_idx %u, sid %u, events 0x%x,"
Dave Wallace2e005bb2017-11-07 01:21:39 -05002992 " data 0x%llx!", getpid (), vep_idx, session_index,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002993 event->events, event->data.u64);
2994 break;
2995
2996 case EPOLL_CTL_MOD:
2997 if (PREDICT_FALSE (!event))
2998 {
Dave Wallace774169b2017-11-01 20:07:40 -04002999 clib_warning ("[%d] ERROR: EPOLL_CTL_MOD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003000 "epoll_event structure!", getpid ());
Dave Wallacef7f809c2017-10-03 01:48:42 -04003001 rv = VPPCOM_EINVAL;
3002 goto done;
3003 }
3004 if (PREDICT_FALSE (!session->is_vep_session &&
3005 (session->vep.vep_idx != vep_idx)))
3006 {
3007 if (VPPCOM_DEBUG > 0)
3008 {
3009 if (!session->is_vep_session)
Dave Wallace774169b2017-11-01 20:07:40 -04003010 clib_warning ("[%d] ERROR: EPOLL_CTL_MOD: session (%u) "
3011 "is not a vep session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003012 getpid (), session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003013 else
Dave Wallace774169b2017-11-01 20:07:40 -04003014 clib_warning ("[%d] ERROR: EPOLL_CTL_MOD: session (%u) "
3015 "vep_idx (%u) != vep_idx (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003016 getpid (), session_index,
Dave Wallacef7f809c2017-10-03 01:48:42 -04003017 session->vep.vep_idx, vep_idx);
3018 }
3019 rv = VPPCOM_EINVAL;
3020 goto done;
3021 }
3022 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
3023 session->vep.ev = *event;
3024 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003025 clib_warning ("[%d] EPOLL_CTL_MOD: vep_idx %u, sid %u, events 0x%x,"
Dave Wallace2e005bb2017-11-07 01:21:39 -05003026 " data 0x%llx!", getpid (), vep_idx, session_index,
Dave Wallacef7f809c2017-10-03 01:48:42 -04003027 event->events, event->data.u64);
3028 break;
3029
3030 case EPOLL_CTL_DEL:
3031 if (PREDICT_FALSE (!session->is_vep_session &&
3032 (session->vep.vep_idx != vep_idx)))
3033 {
3034 if (VPPCOM_DEBUG > 0)
3035 {
3036 if (!session->is_vep_session)
Dave Wallace774169b2017-11-01 20:07:40 -04003037 clib_warning ("[%d] ERROR: EPOLL_CTL_DEL: session (%u) "
3038 "is not a vep session!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003039 getpid (), session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003040 else
Dave Wallace774169b2017-11-01 20:07:40 -04003041 clib_warning ("[%d] ERROR: EPOLL_CTL_DEL: session (%u) "
3042 "vep_idx (%u) != vep_idx (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003043 getpid (), session_index,
Dave Wallacef7f809c2017-10-03 01:48:42 -04003044 session->vep.vep_idx, vep_idx);
3045 }
3046 rv = VPPCOM_EINVAL;
3047 goto done;
3048 }
3049
3050 vep_session->wait_cont_idx =
3051 (vep_session->wait_cont_idx == session_index) ?
3052 session->vep.next_sid : vep_session->wait_cont_idx;
3053
3054 if (session->vep.prev_sid == vep_idx)
3055 vep_session->vep.next_sid = session->vep.next_sid;
3056 else
3057 {
3058 session_t *prev_session;
3059 rv = vppcom_session_at_index (session->vep.prev_sid, &prev_session);
3060 if (PREDICT_FALSE (rv))
3061 {
3062 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04003063 clib_warning ("[%d] ERROR: EPOLL_CTL_DEL: Invalid "
3064 "vep.prev_sid (%u) on sid (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003065 getpid (), session->vep.prev_sid,
Dave Wallacef7f809c2017-10-03 01:48:42 -04003066 session_index);
3067 goto done;
3068 }
3069 ASSERT (prev_session->vep.next_sid == session_index);
3070 prev_session->vep.next_sid = session->vep.next_sid;
3071 }
3072 if (session->vep.next_sid != ~0)
3073 {
3074 session_t *next_session;
3075 rv = vppcom_session_at_index (session->vep.next_sid, &next_session);
3076 if (PREDICT_FALSE (rv))
3077 {
3078 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04003079 clib_warning ("[%d] ERROR: EPOLL_CTL_DEL: Invalid "
3080 "vep.next_sid (%u) on sid (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003081 getpid (), session->vep.next_sid,
Dave Wallacef7f809c2017-10-03 01:48:42 -04003082 session_index);
3083 goto done;
3084 }
3085 ASSERT (next_session->vep.prev_sid == session_index);
3086 next_session->vep.prev_sid = session->vep.prev_sid;
3087 }
3088
3089 memset (&session->vep, 0, sizeof (session->vep));
3090 session->vep.next_sid = ~0;
3091 session->vep.prev_sid = ~0;
3092 session->vep.vep_idx = ~0;
3093 session->is_vep_session = 0;
3094 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003095 clib_warning ("[%d] EPOLL_CTL_DEL: vep_idx %u, sid %u!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003096 getpid (), vep_idx, session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003097 break;
3098
3099 default:
Dave Wallace2e005bb2017-11-07 01:21:39 -05003100 clib_warning ("[%d] ERROR: Invalid operation (%d)!", getpid (), op);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003101 rv = VPPCOM_EINVAL;
3102 }
3103
3104 vep_verify_epoll_chain (vep_idx);
3105
3106done:
3107 clib_spinlock_unlock (&vcm->sessions_lockp);
3108 return rv;
3109}
3110
3111#define VCL_LOCK_AND_GET_SESSION(I, S) \
3112do { \
Dave Wallacef7f809c2017-10-03 01:48:42 -04003113 clib_spinlock_lock (&vcm->sessions_lockp); \
3114 rv = vppcom_session_at_index (I, S); \
3115 if (PREDICT_FALSE (rv)) \
3116 { \
3117 clib_spinlock_unlock (&vcm->sessions_lockp); \
3118 \
3119 if (VPPCOM_DEBUG > 0) \
Dave Wallace774169b2017-11-01 20:07:40 -04003120 clib_warning ("[%s] ERROR: Invalid ##I (%u)!", \
Dave Wallace2e005bb2017-11-07 01:21:39 -05003121 getpid (), I); \
Dave Wallacef7f809c2017-10-03 01:48:42 -04003122 \
3123 goto done; \
3124 } \
3125} while (0)
3126
3127int
3128vppcom_epoll_wait (uint32_t vep_idx, struct epoll_event *events,
3129 int maxevents, double wait_for_time)
3130{
Dave Wallacef7f809c2017-10-03 01:48:42 -04003131 session_t *vep_session;
3132 int rv;
3133 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
Dave Wallace2e005bb2017-11-07 01:21:39 -05003134 u32 keep_trying = 1;
Dave Wallacef7f809c2017-10-03 01:48:42 -04003135 int num_ev = 0;
3136 u32 vep_next_sid, wait_cont_idx;
3137 u8 is_vep;
3138
3139 if (PREDICT_FALSE (maxevents <= 0))
3140 {
3141 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04003142 clib_warning ("[%d] ERROR: Invalid maxevents (%d)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003143 getpid (), maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003144 return VPPCOM_EINVAL;
3145 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04003146 memset (events, 0, sizeof (*events) * maxevents);
3147
3148 VCL_LOCK_AND_GET_SESSION (vep_idx, &vep_session);
3149 vep_next_sid = vep_session->vep.next_sid;
3150 is_vep = vep_session->is_vep;
3151 wait_cont_idx = vep_session->wait_cont_idx;
3152 clib_spinlock_unlock (&vcm->sessions_lockp);
3153
3154 if (PREDICT_FALSE (!is_vep))
3155 {
3156 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04003157 clib_warning ("[%d] ERROR: vep_idx (%u) is not a vep!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003158 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003159 rv = VPPCOM_EINVAL;
3160 goto done;
3161 }
Dave Wallacee695cb42017-11-02 22:04:42 -04003162 if (PREDICT_FALSE (vep_next_sid == ~0))
Dave Wallacef7f809c2017-10-03 01:48:42 -04003163 {
Dave Wallacee695cb42017-11-02 22:04:42 -04003164 if (VPPCOM_DEBUG > 0)
3165 clib_warning ("[%d] WARNING: vep_idx (%u) is empty!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003166 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003167 goto done;
3168 }
3169
3170 do
3171 {
3172 u32 sid;
3173 u32 next_sid = ~0;
3174 session_t *session;
3175
3176 for (sid = (wait_cont_idx == ~0) ? vep_next_sid : wait_cont_idx;
3177 sid != ~0; sid = next_sid)
3178 {
3179 u32 session_events, et_mask, clear_et_mask, session_vep_idx;
3180 u8 add_event, is_vep_session;
3181 int ready;
3182 u64 session_ev_data;
3183
3184 VCL_LOCK_AND_GET_SESSION (sid, &session);
3185 next_sid = session->vep.next_sid;
3186 session_events = session->vep.ev.events;
3187 et_mask = session->vep.et_mask;
3188 is_vep = session->is_vep;
3189 is_vep_session = session->is_vep_session;
3190 session_vep_idx = session->vep.vep_idx;
3191 session_ev_data = session->vep.ev.data.u64;
3192 clib_spinlock_unlock (&vcm->sessions_lockp);
3193
3194 if (PREDICT_FALSE (is_vep))
3195 {
3196 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04003197 clib_warning ("[%d] ERROR: sid (%u) is a vep!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003198 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003199 rv = VPPCOM_EINVAL;
3200 goto done;
3201 }
3202 if (PREDICT_FALSE (!is_vep_session))
3203 {
3204 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04003205 clib_warning ("[%d] ERROR: session (%u) is not "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003206 "a vep session!", getpid (), sid);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003207 rv = VPPCOM_EINVAL;
3208 goto done;
3209 }
3210 if (PREDICT_FALSE (session_vep_idx != vep_idx))
3211 {
Dave Wallace774169b2017-11-01 20:07:40 -04003212 clib_warning ("[%d] ERROR: session (%u) "
Dave Wallacef7f809c2017-10-03 01:48:42 -04003213 "vep_idx (%u) != vep_idx (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003214 getpid (), sid, session->vep.vep_idx, vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003215 rv = VPPCOM_EINVAL;
3216 goto done;
3217 }
3218
3219 add_event = clear_et_mask = 0;
3220
3221 if ((EPOLLIN & session_events) && (EPOLLIN & et_mask))
3222 {
3223 VCL_LOCK_AND_GET_SESSION (sid, &session);
3224 ready = vppcom_session_read_ready (session, sid);
3225 clib_spinlock_unlock (&vcm->sessions_lockp);
3226 if (ready > 0)
3227 {
3228 add_event = 1;
3229 events[num_ev].events |= EPOLLIN;
3230 if (EPOLLET & session_events)
3231 clear_et_mask |= EPOLLIN;
3232 }
3233 else if (ready < 0)
3234 {
3235 add_event = 1;
3236 switch (ready)
3237 {
3238 case VPPCOM_ECONNRESET:
3239 events[num_ev].events |= EPOLLHUP | EPOLLRDHUP;
3240 break;
3241
3242 default:
3243 events[num_ev].events |= EPOLLERR;
3244 break;
3245 }
3246 }
3247 }
3248
3249 if ((EPOLLOUT & session_events) && (EPOLLOUT & et_mask))
3250 {
3251 VCL_LOCK_AND_GET_SESSION (sid, &session);
3252 ready = vppcom_session_write_ready (session, sid);
3253 clib_spinlock_unlock (&vcm->sessions_lockp);
3254 if (ready > 0)
3255 {
3256 add_event = 1;
3257 events[num_ev].events |= EPOLLOUT;
3258 if (EPOLLET & session_events)
3259 clear_et_mask |= EPOLLOUT;
3260 }
3261 else if (ready < 0)
3262 {
3263 add_event = 1;
3264 switch (ready)
3265 {
3266 case VPPCOM_ECONNRESET:
3267 events[num_ev].events |= EPOLLHUP;
3268 break;
3269
3270 default:
3271 events[num_ev].events |= EPOLLERR;
3272 break;
3273 }
3274 }
3275 }
3276
3277 if (add_event)
3278 {
3279 events[num_ev].data.u64 = session_ev_data;
3280 if (EPOLLONESHOT & session_events)
3281 {
3282 VCL_LOCK_AND_GET_SESSION (sid, &session);
3283 session->vep.ev.events = 0;
3284 clib_spinlock_unlock (&vcm->sessions_lockp);
3285 }
3286 num_ev++;
3287 if (num_ev == maxevents)
3288 {
3289 VCL_LOCK_AND_GET_SESSION (vep_idx, &vep_session);
3290 vep_session->wait_cont_idx = next_sid;
3291 clib_spinlock_unlock (&vcm->sessions_lockp);
3292 goto done;
3293 }
3294 }
3295 if (wait_cont_idx != ~0)
3296 {
3297 if (next_sid == ~0)
3298 next_sid = vep_next_sid;
3299 else if (next_sid == wait_cont_idx)
3300 next_sid = ~0;
3301 }
3302 }
Dave Wallace2e005bb2017-11-07 01:21:39 -05003303 if (wait_for_time != -1)
3304 keep_trying = (clib_time_now (&vcm->clib_time) <= timeout) ? 1 : 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04003305 }
Dave Wallace2e005bb2017-11-07 01:21:39 -05003306 while ((num_ev == 0) && keep_trying);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003307
3308 if (wait_cont_idx != ~0)
3309 {
3310 VCL_LOCK_AND_GET_SESSION (vep_idx, &vep_session);
3311 vep_session->wait_cont_idx = ~0;
3312 clib_spinlock_unlock (&vcm->sessions_lockp);
3313 }
3314done:
3315 return (rv != VPPCOM_OK) ? rv : num_ev;
3316}
3317
Dave Wallace35830af2017-10-09 01:43:42 -04003318int
3319vppcom_session_attr (uint32_t session_index, uint32_t op,
3320 void *buffer, uint32_t * buflen)
3321{
Dave Wallace35830af2017-10-09 01:43:42 -04003322 session_t *session;
3323 int rv = VPPCOM_OK;
3324 u32 *flags = buffer;
Steven2199aab2017-10-15 20:18:47 -07003325 vppcom_endpt_t *ep = buffer;
Dave Wallace35830af2017-10-09 01:43:42 -04003326
3327 VCL_LOCK_AND_GET_SESSION (session_index, &session);
3328 switch (op)
3329 {
3330 case VPPCOM_ATTR_GET_NREAD:
3331 rv = vppcom_session_read_ready (session, session_index);
Dave Wallacefaf9d772017-10-26 16:12:04 -04003332 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003333 clib_warning ("[%d] VPPCOM_ATTR_GET_NREAD: nread = %d",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003334 getpid (), rv);
Dave Wallace35830af2017-10-09 01:43:42 -04003335
3336 break;
3337
3338 case VPPCOM_ATTR_PEEK_NREAD:
3339 /* TBD */
3340 break;
3341
3342 case VPPCOM_ATTR_GET_FLAGS:
3343 if (buffer && buflen && (*buflen >= sizeof (*flags)))
3344 {
3345 *flags = O_RDWR | ((session->is_nonblocking) ? O_NONBLOCK : 0);
3346 *buflen = sizeof (*flags);
Dave Wallacefaf9d772017-10-26 16:12:04 -04003347 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003348 clib_warning ("[%d] VPPCOM_ATTR_GET_FLAGS: flags = 0x%08x, "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003349 "is_nonblocking = %u", getpid (), *flags,
Dave Wallace35830af2017-10-09 01:43:42 -04003350 session->is_nonblocking);
3351 }
3352 else
3353 rv = VPPCOM_EINVAL;
3354 break;
3355
3356 case VPPCOM_ATTR_SET_FLAGS:
3357 if (buffer && buflen && (*buflen >= sizeof (*flags)))
3358 {
3359 session->is_nonblocking = (*flags & O_NONBLOCK) ? 1 : 0;
Dave Wallacefaf9d772017-10-26 16:12:04 -04003360 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003361 clib_warning ("[%d] VPPCOM_ATTR_SET_FLAGS: flags = 0x%08x, "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003362 "is_nonblocking = %u", getpid (), *flags,
Dave Wallace35830af2017-10-09 01:43:42 -04003363 session->is_nonblocking);
3364 }
3365 else
3366 rv = VPPCOM_EINVAL;
3367 break;
3368
3369 case VPPCOM_ATTR_GET_PEER_ADDR:
Steven2199aab2017-10-15 20:18:47 -07003370 if (buffer && buflen && (*buflen >= sizeof (*ep)))
Dave Wallace35830af2017-10-09 01:43:42 -04003371 {
Steven2199aab2017-10-15 20:18:47 -07003372 ep->vrf = session->vrf;
3373 ep->is_ip4 = session->peer_addr.is_ip4;
Stevenac1f96d2017-10-24 16:03:58 -07003374 ep->port = session->peer_port;
Steven2199aab2017-10-15 20:18:47 -07003375 if (session->peer_addr.is_ip4)
3376 clib_memcpy (ep->ip, &session->peer_addr.ip46.ip4,
3377 sizeof (ip4_address_t));
3378 else
3379 clib_memcpy (ep->ip, &session->peer_addr.ip46.ip6,
3380 sizeof (ip6_address_t));
3381 *buflen = sizeof (*ep);
Dave Wallacefaf9d772017-10-26 16:12:04 -04003382 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003383 clib_warning ("[%d] VPPCOM_ATTR_GET_PEER_ADDR: sid %u is_ip4 = "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003384 "%u, addr = %U, port %u", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04003385 session_index, ep->is_ip4, format_ip46_address,
Stevenac1f96d2017-10-24 16:03:58 -07003386 &session->peer_addr.ip46, ep->is_ip4,
3387 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04003388 }
3389 else
3390 rv = VPPCOM_EINVAL;
3391 break;
3392
3393 case VPPCOM_ATTR_GET_LCL_ADDR:
Steven2199aab2017-10-15 20:18:47 -07003394 if (buffer && buflen && (*buflen >= sizeof (*ep)))
Dave Wallace35830af2017-10-09 01:43:42 -04003395 {
Steven2199aab2017-10-15 20:18:47 -07003396 ep->vrf = session->vrf;
3397 ep->is_ip4 = session->lcl_addr.is_ip4;
Stevenac1f96d2017-10-24 16:03:58 -07003398 ep->port = session->lcl_port;
Steven2199aab2017-10-15 20:18:47 -07003399 if (session->lcl_addr.is_ip4)
3400 clib_memcpy (ep->ip, &session->lcl_addr.ip46.ip4,
3401 sizeof (ip4_address_t));
3402 else
3403 clib_memcpy (ep->ip, &session->lcl_addr.ip46.ip6,
3404 sizeof (ip6_address_t));
3405 *buflen = sizeof (*ep);
Dave Wallacefaf9d772017-10-26 16:12:04 -04003406 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003407 clib_warning ("[%d] VPPCOM_ATTR_GET_LCL_ADDR: sid %u is_ip4 = "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003408 "%u, addr = %U port %d", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04003409 session_index, ep->is_ip4, format_ip46_address,
Stevenac1f96d2017-10-24 16:03:58 -07003410 &session->lcl_addr.ip46, ep->is_ip4,
3411 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04003412 }
3413 else
3414 rv = VPPCOM_EINVAL;
3415 break;
Stevenb5a11602017-10-11 09:59:30 -07003416
3417 case VPPCOM_ATTR_SET_REUSEADDR:
3418 break;
3419
3420 case VPPCOM_ATTR_SET_BROADCAST:
3421 break;
3422
3423 case VPPCOM_ATTR_SET_V6ONLY:
3424 break;
Stevenbccd3392017-10-12 20:42:21 -07003425
3426 case VPPCOM_ATTR_SET_KEEPALIVE:
3427 break;
3428
3429 case VPPCOM_ATTR_SET_TCP_KEEPIDLE:
3430 break;
3431
3432 case VPPCOM_ATTR_SET_TCP_KEEPINTVL:
3433 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003434
3435 default:
3436 rv = VPPCOM_EINVAL;
3437 break;
Dave Wallace35830af2017-10-09 01:43:42 -04003438 }
3439
3440done:
3441 clib_spinlock_unlock (&vcm->sessions_lockp);
3442 return rv;
3443}
3444
Stevenac1f96d2017-10-24 16:03:58 -07003445int
3446vppcom_session_recvfrom (uint32_t session_index, void *buffer,
3447 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3448{
Stevenac1f96d2017-10-24 16:03:58 -07003449 int rv = VPPCOM_OK;
3450 session_t *session = 0;
3451
3452 if (ep)
3453 {
3454 clib_spinlock_lock (&vcm->sessions_lockp);
3455 rv = vppcom_session_at_index (session_index, &session);
3456 if (PREDICT_FALSE (rv))
3457 {
3458 clib_spinlock_unlock (&vcm->sessions_lockp);
3459 if (VPPCOM_DEBUG > 0)
3460 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003461 getpid (), session_index);
Dave Wallacefaf9d772017-10-26 16:12:04 -04003462 rv = VPPCOM_EBADFD;
3463 clib_spinlock_unlock (&vcm->sessions_lockp);
3464 goto done;
Stevenac1f96d2017-10-24 16:03:58 -07003465 }
3466 ep->vrf = session->vrf;
3467 ep->is_ip4 = session->peer_addr.is_ip4;
3468 ep->port = session->peer_port;
3469 if (session->peer_addr.is_ip4)
3470 clib_memcpy (ep->ip, &session->peer_addr.ip46.ip4,
3471 sizeof (ip4_address_t));
3472 else
3473 clib_memcpy (ep->ip, &session->peer_addr.ip46.ip6,
3474 sizeof (ip6_address_t));
3475 clib_spinlock_unlock (&vcm->sessions_lockp);
Stevenac1f96d2017-10-24 16:03:58 -07003476 }
Steven58f464e2017-10-25 12:33:12 -07003477
3478 if (flags == 0)
Stevenac1f96d2017-10-24 16:03:58 -07003479 rv = vppcom_session_read (session_index, buffer, buflen);
3480 else if (flags & MSG_PEEK)
Steven58f464e2017-10-25 12:33:12 -07003481 rv = vppcom_session_peek (session_index, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003482 else
3483 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05003484 clib_warning ("[%d] Unsupport flags for recvfrom %d", getpid (), flags);
Stevenac1f96d2017-10-24 16:03:58 -07003485 rv = VPPCOM_EAFNOSUPPORT;
3486 }
3487
Dave Wallacefaf9d772017-10-26 16:12:04 -04003488done:
Stevenac1f96d2017-10-24 16:03:58 -07003489 return rv;
3490}
3491
3492int
3493vppcom_session_sendto (uint32_t session_index, void *buffer,
3494 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3495{
Dave Wallace617dffa2017-10-26 14:47:06 -04003496 if (!buffer)
3497 return VPPCOM_EINVAL;
3498
3499 if (ep)
3500 {
3501 // TBD
3502 return VPPCOM_EINVAL;
3503 }
3504
3505 if (flags)
3506 {
3507 // TBD check the flags and do the right thing
3508 if (VPPCOM_DEBUG > 2)
3509 clib_warning ("[%d] handling flags 0x%u (%d) not implemented yet.",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003510 getpid (), flags, flags);
Dave Wallace617dffa2017-10-26 14:47:06 -04003511 }
3512
3513 return (vppcom_session_write (session_index, buffer, buflen));
Stevenac1f96d2017-10-24 16:03:58 -07003514}
3515
Dave Wallacee22aa742017-10-20 12:30:38 -04003516/*
3517 * fd.io coding-style-patch-verification: ON
3518 *
3519 * Local Variables:
3520 * eval: (c-set-style "gnu")
3521 * End:
3522 */