blob: 2ccb2b8670557ec951f574bb7c65cf4dac39786d [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{
Dave Wallace4878cbe2017-11-21 03:45:09 -050069 STATE_START = 0x01,
70 STATE_CONNECT = 0x02,
71 STATE_LISTEN = 0x04,
72 STATE_ACCEPT = 0x08,
73 STATE_CLOSE_ON_EMPTY = 0x10,
74 STATE_DISCONNECT = 0x20,
75 STATE_FAILED = 0x40
Dave Wallace543852a2017-08-03 02:11:34 -040076} session_state_t;
77
Dave Wallace4878cbe2017-11-21 03:45:09 -050078#define SERVER_STATE_OPEN (STATE_ACCEPT|STATE_CLOSE_ON_EMPTY)
79#define CLIENT_STATE_OPEN (STATE_CONNECT|STATE_CLOSE_ON_EMPTY)
80
Dave Wallacef7f809c2017-10-03 01:48:42 -040081typedef struct epoll_event vppcom_epoll_event_t;
82
83typedef struct
84{
85 u32 next_sid;
86 u32 prev_sid;
87 u32 vep_idx;
88 vppcom_epoll_event_t ev;
89#define VEP_DEFAULT_ET_MASK (EPOLLIN|EPOLLOUT)
Dave Wallace60caa062017-11-10 17:07:13 -050090#define VEP_UNSUPPORTED_EVENTS (EPOLLONESHOT|EPOLLEXCLUSIVE)
Dave Wallacef7f809c2017-10-03 01:48:42 -040091 u32 et_mask;
92} vppcom_epoll_t;
93
Dave Wallace543852a2017-08-03 02:11:34 -040094typedef struct
95{
Dave Wallace35830af2017-10-09 01:43:42 -040096 u8 is_ip4;
97 ip46_address_t ip46;
98} vppcom_ip46_t;
99
100typedef struct
101{
Dave Wallace543852a2017-08-03 02:11:34 -0400102 volatile session_state_t state;
103
104 svm_fifo_t *server_rx_fifo;
105 svm_fifo_t *server_tx_fifo;
Dave Wallace60caa062017-11-10 17:07:13 -0500106 u8 *segment_name;
Dave Wallace543852a2017-08-03 02:11:34 -0400107 u32 sm_seg_index;
Dave Wallace60caa062017-11-10 17:07:13 -0500108 u32 client_context;
109 u64 vpp_handle;
Dave Wallace33e002b2017-09-06 01:20:02 -0400110 unix_shared_memory_queue_t *vpp_event_queue;
Dave Wallace543852a2017-08-03 02:11:34 -0400111
112 /* Socket configuration state */
Dave Wallacef7f809c2017-10-03 01:48:42 -0400113 /* TBD: covert 'is_*' vars to bit in u8 flags; */
Dave Wallace543852a2017-08-03 02:11:34 -0400114 u8 is_server;
115 u8 is_listen;
116 u8 is_cut_thru;
117 u8 is_nonblocking;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400118 u8 is_vep;
119 u8 is_vep_session;
120 u32 wait_cont_idx;
121 vppcom_epoll_t vep;
Dave Wallace543852a2017-08-03 02:11:34 -0400122 u32 vrf;
Dave Wallace35830af2017-10-09 01:43:42 -0400123 vppcom_ip46_t lcl_addr;
124 vppcom_ip46_t peer_addr;
Stevenac1f96d2017-10-24 16:03:58 -0700125 u16 lcl_port; // network order
126 u16 peer_port; // network order
Dave Wallace543852a2017-08-03 02:11:34 -0400127 u8 proto;
128 u64 client_queue_address;
129 u64 options[16];
130} session_t;
131
132typedef struct vppcom_cfg_t_
133{
134 u64 heapsize;
135 u64 segment_baseva;
136 u32 segment_size;
137 u32 add_segment_size;
138 u32 preallocated_fifo_pairs;
139 u32 rx_fifo_size;
140 u32 tx_fifo_size;
141 u32 event_queue_size;
142 u32 listen_queue_size;
Dave Wallace774169b2017-11-01 20:07:40 -0400143 u8 app_proxy_transport_tcp;
144 u8 app_proxy_transport_udp;
145 u8 app_scope_local;
146 u8 app_scope_global;
Dave Wallace8af20542017-10-26 03:29:30 -0400147 u8 *namespace_id;
148 u64 namespace_secret;
Dave Wallace543852a2017-08-03 02:11:34 -0400149 f64 app_timeout;
150 f64 session_timeout;
151 f64 accept_timeout;
152} vppcom_cfg_t;
153
154typedef struct vppcom_main_t_
155{
156 u8 init;
Dave Wallace498b3a52017-11-09 13:00:34 -0500157 u32 debug;
Dave Wallace543852a2017-08-03 02:11:34 -0400158 u32 *client_session_index_fifo;
Dave Wallace543852a2017-08-03 02:11:34 -0400159 int main_cpu;
160
161 /* vpe input queue */
162 unix_shared_memory_queue_t *vl_input_queue;
163
164 /* API client handle */
165 u32 my_client_index;
166
167 /* Session pool */
168 clib_spinlock_t sessions_lockp;
169 session_t *sessions;
170
171 /* Hash table for disconnect processing */
172 uword *session_index_by_vpp_handles;
173
174 /* Select bitmaps */
175 clib_bitmap_t *rd_bitmap;
176 clib_bitmap_t *wr_bitmap;
177 clib_bitmap_t *ex_bitmap;
178
179 /* Our event queue */
180 unix_shared_memory_queue_t *app_event_queue;
181
182 /* unique segment name counter */
183 u32 unique_segment_index;
184
Dave Wallace543852a2017-08-03 02:11:34 -0400185 /* For deadman timers */
186 clib_time_t clib_time;
187
188 /* State of the connection, shared between msg RX thread and main thread */
189 volatile app_state_t app_state;
190
191 vppcom_cfg_t cfg;
192
193 /* VNET_API_ERROR_FOO -> "Foo" hash table */
194 uword *error_string_by_error_number;
195} vppcom_main_t;
196
Dave Wallace2e005bb2017-11-07 01:21:39 -0500197/* NOTE: _vppcom_main is only used until the heap is allocated.
198 * Do not access it directly -- use vcm which will point to
199 * the heap allocated copy after init.
200 */
Dave Wallace498b3a52017-11-09 13:00:34 -0500201static vppcom_main_t _vppcom_main = {
202 .debug = VPPCOM_DEBUG_INIT,
203 .my_client_index = ~0
204};
Dave Wallace2e005bb2017-11-07 01:21:39 -0500205
206static vppcom_main_t *vcm = &_vppcom_main;
Dave Wallace543852a2017-08-03 02:11:34 -0400207
Dave Wallace60caa062017-11-10 17:07:13 -0500208#define VCL_LOCK_AND_GET_SESSION(I, S) \
209do { \
210 clib_spinlock_lock (&vcm->sessions_lockp); \
211 rv = vppcom_session_at_index (I, S); \
212 if (PREDICT_FALSE (rv)) \
213 { \
214 clib_spinlock_unlock (&vcm->sessions_lockp); \
Dave Wallace4878cbe2017-11-21 03:45:09 -0500215 clib_warning ("[%s] ERROR: Invalid ##I (%u)!", \
216 getpid (), I); \
Dave Wallace60caa062017-11-10 17:07:13 -0500217 goto done; \
218 } \
219} while (0)
220
Dave Wallace543852a2017-08-03 02:11:34 -0400221static const char *
222vppcom_app_state_str (app_state_t state)
223{
224 char *st;
225
226 switch (state)
227 {
228 case STATE_APP_START:
229 st = "STATE_APP_START";
230 break;
231
232 case STATE_APP_CONN_VPP:
233 st = "STATE_APP_CONN_VPP";
234 break;
235
236 case STATE_APP_ENABLED:
237 st = "STATE_APP_ENABLED";
238 break;
239
240 case STATE_APP_ATTACHED:
241 st = "STATE_APP_ATTACHED";
242 break;
243
244 default:
245 st = "UNKNOWN_APP_STATE";
246 break;
247 }
248
249 return st;
250}
251
252static const char *
253vppcom_session_state_str (session_state_t state)
254{
255 char *st;
256
257 switch (state)
258 {
259 case STATE_START:
260 st = "STATE_START";
261 break;
262
263 case STATE_CONNECT:
264 st = "STATE_CONNECT";
265 break;
266
267 case STATE_LISTEN:
268 st = "STATE_LISTEN";
269 break;
270
271 case STATE_ACCEPT:
272 st = "STATE_ACCEPT";
273 break;
274
Dave Wallace4878cbe2017-11-21 03:45:09 -0500275 case STATE_CLOSE_ON_EMPTY:
276 st = "STATE_CLOSE_ON_EMPTY";
277 break;
278
Dave Wallace543852a2017-08-03 02:11:34 -0400279 case STATE_DISCONNECT:
280 st = "STATE_DISCONNECT";
281 break;
282
283 case STATE_FAILED:
284 st = "STATE_FAILED";
285 break;
286
287 default:
288 st = "UNKNOWN_STATE";
289 break;
290 }
291
292 return st;
293}
294
295/*
296 * VPPCOM Utility Functions
297 */
298static inline int
299vppcom_session_at_index (u32 session_index, session_t * volatile *sess)
300{
Dave Wallace543852a2017-08-03 02:11:34 -0400301 /* Assumes that caller has acquired spinlock: vcm->sessions_lockp */
302 if (PREDICT_FALSE ((session_index == ~0) ||
303 pool_is_free_index (vcm->sessions, session_index)))
304 {
Dave Wallacef7f809c2017-10-03 01:48:42 -0400305 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500306 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400307 return VPPCOM_EBADFD;
308 }
309 *sess = pool_elt_at_index (vcm->sessions, session_index);
310 return VPPCOM_OK;
311}
312
Florin Corasdcf55ce2017-11-16 15:32:50 -0800313static inline void
314vppcom_session_table_add_listener (u64 listener_handle, u32 value)
315{
316 /* Session and listener handles have different formats. The latter has
317 * the thread index in the upper 32 bits while the former has the session
318 * type. Knowing that, for listeners we just flip the MSB to 1 */
319 listener_handle |= 1ULL << 63;
320 hash_set (vcm->session_index_by_vpp_handles, listener_handle, value);
321}
322
323static inline session_t *
324vppcom_session_table_lookup_listener (u64 listener_handle)
325{
326 uword *p;
327 u64 handle = listener_handle | (1ULL << 63);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500328 session_t *session;
329
Florin Corasdcf55ce2017-11-16 15:32:50 -0800330 p = hash_get (vcm->session_index_by_vpp_handles, handle);
331 if (!p)
332 {
333 clib_warning ("[%d] couldn't find listen session: unknown vpp "
334 "listener handle %llx", getpid (), listener_handle);
335 return 0;
336 }
337 if (pool_is_free_index (vcm->sessions, p[0]))
338 {
339 if (VPPCOM_DEBUG > 1)
340 clib_warning ("[%d] invalid listen session, sid (%u)", getpid (),
341 p[0]);
342 return 0;
343 }
344
Dave Wallace4878cbe2017-11-21 03:45:09 -0500345 session = pool_elt_at_index (vcm->sessions, p[0]);
346 ASSERT (session->is_listen);
347 return session;
Florin Corasdcf55ce2017-11-16 15:32:50 -0800348}
349
350static inline void
351vppcom_session_table_del_listener (u64 listener_handle)
352{
353 listener_handle |= 1ULL << 63;
354 hash_unset (vcm->session_index_by_vpp_handles, listener_handle);
355}
356
Dave Wallace543852a2017-08-03 02:11:34 -0400357static int
358vppcom_connect_to_vpp (char *app_name)
359{
360 api_main_t *am = &api_main;
Dave Wallace543852a2017-08-03 02:11:34 -0400361
362 if (VPPCOM_DEBUG > 0)
363 printf ("\nConnecting to VPP api...");
364 if (vl_client_connect_to_vlib ("/vpe-api", app_name, 32) < 0)
365 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500366 clib_warning ("[%d] connect to vpp (%s) failed!", getpid (), app_name);
Dave Wallace543852a2017-08-03 02:11:34 -0400367 return VPPCOM_ECONNREFUSED;
368 }
369
370 vcm->vl_input_queue = am->shmem_hdr->vl_input_queue;
371 vcm->my_client_index = am->my_client_index;
372 if (VPPCOM_DEBUG > 0)
373 printf (" connected!\n");
374
375 vcm->app_state = STATE_APP_CONN_VPP;
376 return VPPCOM_OK;
377}
378
379static u8 *
380format_api_error (u8 * s, va_list * args)
381{
Dave Wallace543852a2017-08-03 02:11:34 -0400382 i32 error = va_arg (*args, u32);
383 uword *p;
384
385 p = hash_get (vcm->error_string_by_error_number, -error);
386
387 if (p)
388 s = format (s, "%s (%d)", p[0], error);
389 else
390 s = format (s, "%d", error);
391 return s;
392}
393
394static void
395vppcom_init_error_string_table (void)
396{
Dave Wallace543852a2017-08-03 02:11:34 -0400397 vcm->error_string_by_error_number = hash_create (0, sizeof (uword));
398
399#define _(n,v,s) hash_set (vcm->error_string_by_error_number, -v, s);
400 foreach_vnet_api_error;
401#undef _
402
403 hash_set (vcm->error_string_by_error_number, 99, "Misc");
404}
405
406static inline int
407vppcom_wait_for_app_state_change (app_state_t app_state)
408{
Dave Wallace543852a2017-08-03 02:11:34 -0400409 f64 timeout = clib_time_now (&vcm->clib_time) + vcm->cfg.app_timeout;
410
411 while (clib_time_now (&vcm->clib_time) < timeout)
412 {
413 if (vcm->app_state == app_state)
414 return VPPCOM_OK;
415 }
416 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500417 clib_warning ("[%d] timeout waiting for state %s (%d)", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400418 vppcom_app_state_str (app_state), app_state);
419 return VPPCOM_ETIMEDOUT;
420}
421
422static inline int
423vppcom_wait_for_session_state_change (u32 session_index,
424 session_state_t state,
425 f64 wait_for_time)
426{
Dave Wallace543852a2017-08-03 02:11:34 -0400427 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
428 session_t *volatile session;
429 int rv;
430
431 do
432 {
433 clib_spinlock_lock (&vcm->sessions_lockp);
434 rv = vppcom_session_at_index (session_index, &session);
435 if (PREDICT_FALSE (rv))
436 {
437 clib_spinlock_unlock (&vcm->sessions_lockp);
438 return rv;
439 }
440 if (session->state == state)
441 {
442 clib_spinlock_unlock (&vcm->sessions_lockp);
443 return VPPCOM_OK;
444 }
Dave Wallace4878cbe2017-11-21 03:45:09 -0500445 if (session->state == STATE_FAILED)
446 {
447 clib_spinlock_unlock (&vcm->sessions_lockp);
448 return VPPCOM_ECONNREFUSED;
449 }
450
Dave Wallace543852a2017-08-03 02:11:34 -0400451 clib_spinlock_unlock (&vcm->sessions_lockp);
452 }
453 while (clib_time_now (&vcm->clib_time) < timeout);
454
455 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500456 clib_warning ("[%d] timeout waiting for state 0x%x (%s)", getpid (),
457 state, vppcom_session_state_str (state));
Dave Wallace543852a2017-08-03 02:11:34 -0400458 return VPPCOM_ETIMEDOUT;
459}
460
461static inline int
462vppcom_wait_for_client_session_index (f64 wait_for_time)
463{
Dave Wallace543852a2017-08-03 02:11:34 -0400464 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
465
466 do
467 {
468 if (clib_fifo_elts (vcm->client_session_index_fifo))
469 return VPPCOM_OK;
470 }
471 while (clib_time_now (&vcm->clib_time) < timeout);
472
473 if (wait_for_time == 0)
474 return VPPCOM_EAGAIN;
475
476 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500477 clib_warning ("[%d] timeout waiting for client_session_index", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -0400478 return VPPCOM_ETIMEDOUT;
479}
480
481/*
482 * VPP-API message functions
483 */
484static void
485vppcom_send_session_enable_disable (u8 is_enable)
486{
Dave Wallace543852a2017-08-03 02:11:34 -0400487 vl_api_session_enable_disable_t *bmp;
488 bmp = vl_msg_api_alloc (sizeof (*bmp));
489 memset (bmp, 0, sizeof (*bmp));
490
491 bmp->_vl_msg_id = ntohs (VL_API_SESSION_ENABLE_DISABLE);
492 bmp->client_index = vcm->my_client_index;
493 bmp->context = htonl (0xfeedface);
494 bmp->is_enable = is_enable;
495 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
496}
497
498static int
499vppcom_app_session_enable (void)
500{
Dave Wallace543852a2017-08-03 02:11:34 -0400501 int rv;
502
503 if (vcm->app_state != STATE_APP_ENABLED)
504 {
505 vppcom_send_session_enable_disable (1 /* is_enabled == TRUE */ );
506 rv = vppcom_wait_for_app_state_change (STATE_APP_ENABLED);
507 if (PREDICT_FALSE (rv))
508 {
509 if (VPPCOM_DEBUG > 0)
510 clib_warning ("[%d] Session enable timed out, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500511 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -0400512 return rv;
513 }
514 }
515 return VPPCOM_OK;
516}
517
518static void
519 vl_api_session_enable_disable_reply_t_handler
520 (vl_api_session_enable_disable_reply_t * mp)
521{
Dave Wallace543852a2017-08-03 02:11:34 -0400522 if (mp->retval)
523 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500524 clib_warning ("[%d] session_enable_disable failed: %U", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400525 format_api_error, ntohl (mp->retval));
526 }
527 else
528 vcm->app_state = STATE_APP_ENABLED;
529}
530
531static void
532vppcom_app_send_attach (void)
533{
Dave Wallace543852a2017-08-03 02:11:34 -0400534 vl_api_application_attach_t *bmp;
Dave Wallace8af20542017-10-26 03:29:30 -0400535 u8 nsid_len = vec_len (vcm->cfg.namespace_id);
Dave Wallace774169b2017-11-01 20:07:40 -0400536 u8 app_is_proxy = (vcm->cfg.app_proxy_transport_tcp ||
537 vcm->cfg.app_proxy_transport_udp);
Dave Wallace8af20542017-10-26 03:29:30 -0400538
Dave Wallace543852a2017-08-03 02:11:34 -0400539 bmp = vl_msg_api_alloc (sizeof (*bmp));
540 memset (bmp, 0, sizeof (*bmp));
541
542 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
543 bmp->client_index = vcm->my_client_index;
544 bmp->context = htonl (0xfeedface);
545 bmp->options[APP_OPTIONS_FLAGS] =
Florin Corascea194d2017-10-02 00:18:51 -0700546 APP_OPTIONS_FLAGS_ACCEPT_REDIRECT | APP_OPTIONS_FLAGS_ADD_SEGMENT |
Dave Wallace774169b2017-11-01 20:07:40 -0400547 (vcm->cfg.app_scope_local ? APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE : 0) |
548 (vcm->cfg.app_scope_global ? APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE : 0) |
549 (app_is_proxy ? APP_OPTIONS_FLAGS_IS_PROXY : 0);
550 bmp->options[APP_OPTIONS_PROXY_TRANSPORT] =
551 (vcm->cfg.app_proxy_transport_tcp ? 1 << TRANSPORT_PROTO_TCP : 0) |
552 (vcm->cfg.app_proxy_transport_udp ? 1 << TRANSPORT_PROTO_UDP : 0);
Dave Wallace543852a2017-08-03 02:11:34 -0400553 bmp->options[SESSION_OPTIONS_SEGMENT_SIZE] = vcm->cfg.segment_size;
554 bmp->options[SESSION_OPTIONS_ADD_SEGMENT_SIZE] = vcm->cfg.add_segment_size;
555 bmp->options[SESSION_OPTIONS_RX_FIFO_SIZE] = vcm->cfg.rx_fifo_size;
556 bmp->options[SESSION_OPTIONS_TX_FIFO_SIZE] = vcm->cfg.tx_fifo_size;
Dave Wallace8af20542017-10-26 03:29:30 -0400557 if (nsid_len)
558 {
559 bmp->namespace_id_len = nsid_len;
560 clib_memcpy (bmp->namespace_id, vcm->cfg.namespace_id, nsid_len);
561 bmp->options[APP_OPTIONS_NAMESPACE_SECRET] = vcm->cfg.namespace_secret;
562 }
Dave Wallace543852a2017-08-03 02:11:34 -0400563 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
564}
565
566static int
567vppcom_app_attach (void)
568{
Dave Wallace543852a2017-08-03 02:11:34 -0400569 int rv;
570
571 vppcom_app_send_attach ();
572 rv = vppcom_wait_for_app_state_change (STATE_APP_ATTACHED);
573 if (PREDICT_FALSE (rv))
574 {
575 if (VPPCOM_DEBUG > 0)
576 clib_warning ("[%d] application attach timed out, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500577 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -0400578 return rv;
579 }
580 return VPPCOM_OK;
581}
582
583static void
584vppcom_app_detach (void)
585{
Dave Wallace543852a2017-08-03 02:11:34 -0400586 vl_api_application_detach_t *bmp;
587 bmp = vl_msg_api_alloc (sizeof (*bmp));
588 memset (bmp, 0, sizeof (*bmp));
589
590 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
591 bmp->client_index = vcm->my_client_index;
592 bmp->context = htonl (0xfeedface);
593 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
594}
595
596static void
597vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t *
598 mp)
599{
Dave Wallace543852a2017-08-03 02:11:34 -0400600 static svm_fifo_segment_create_args_t _a;
601 svm_fifo_segment_create_args_t *a = &_a;
602 int rv;
603
604 memset (a, 0, sizeof (*a));
605 if (mp->retval)
606 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500607 clib_warning ("[%d] attach failed: %U", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400608 format_api_error, ntohl (mp->retval));
609 return;
610 }
611
612 if (mp->segment_name_length == 0)
613 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500614 clib_warning ("[%d] segment_name_length zero", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -0400615 return;
616 }
617
618 a->segment_name = (char *) mp->segment_name;
619 a->segment_size = mp->segment_size;
620
621 ASSERT (mp->app_event_queue_address);
622
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 {
Dave Wallace2e005bb2017-11-07 01:21:39 -0500628 clib_warning ("[%d] svm_fifo_segment_attach ('%s') failed", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400629 mp->segment_name);
630 return;
631 }
632
633 vcm->app_event_queue =
634 uword_to_pointer (mp->app_event_queue_address,
635 unix_shared_memory_queue_t *);
636
637 vcm->app_state = STATE_APP_ATTACHED;
638}
639
640static void
641vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t *
642 mp)
643{
Dave Wallace543852a2017-08-03 02:11:34 -0400644 if (mp->retval)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500645 clib_warning ("[%d] detach failed: %U", getpid (), format_api_error,
Dave Wallace543852a2017-08-03 02:11:34 -0400646 ntohl (mp->retval));
647
648 vcm->app_state = STATE_APP_ENABLED;
649}
650
651static void
652vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t *
653 mp)
654{
Dave Wallace543852a2017-08-03 02:11:34 -0400655 if (mp->retval)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500656 clib_warning ("[%d] vpp handle 0x%llx: disconnect session failed: %U",
657 getpid (), mp->handle, format_api_error,
658 ntohl (mp->retval));
Dave Wallace543852a2017-08-03 02:11:34 -0400659}
660
661static void
662vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
663{
Dave Wallace543852a2017-08-03 02:11:34 -0400664 static svm_fifo_segment_create_args_t _a;
665 svm_fifo_segment_create_args_t *a = &_a;
666 int rv;
667
668 memset (a, 0, sizeof (*a));
669 a->segment_name = (char *) mp->segment_name;
670 a->segment_size = mp->segment_size;
671 /* Attach to the segment vpp created */
672 rv = svm_fifo_segment_attach (a);
673 vec_reset_length (a->new_segment_indices);
674 if (PREDICT_FALSE (rv))
675 {
676 clib_warning ("[%d] svm_fifo_segment_attach ('%s') failed",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500677 getpid (), mp->segment_name);
Dave Wallace543852a2017-08-03 02:11:34 -0400678 return;
679 }
680 if (VPPCOM_DEBUG > 1)
Dave Wallace2e005bb2017-11-07 01:21:39 -0500681 clib_warning ("[%d] mapped new segment '%s' size %d", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -0400682 mp->segment_name, mp->segment_size);
683}
684
685static void
686vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp)
687{
Dave Wallace543852a2017-08-03 02:11:34 -0400688 uword *p;
Dave Wallace543852a2017-08-03 02:11:34 -0400689
690 p = hash_get (vcm->session_index_by_vpp_handles, mp->handle);
691 if (p)
692 {
Dave Wallace4878cbe2017-11-21 03:45:09 -0500693 int rv;
694 session_t *session = 0;
695 u32 session_index = p[0];
696
697 VCL_LOCK_AND_GET_SESSION (session_index, &session);
698 session->state = STATE_CLOSE_ON_EMPTY;
699
700 if (VPPCOM_DEBUG > 1)
701 clib_warning ("[%d] vpp handle 0x%llx, sid %u: "
702 "setting state to %d (%s)",
703 getpid (), mp->handle, session_index, session->state,
704 vppcom_session_state_str (session->state));
Dave Wallace543852a2017-08-03 02:11:34 -0400705 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500706 return;
707
708 done:
709 if (VPPCOM_DEBUG > 1)
710 clib_warning ("[%d] vpp handle 0x%llx, sid %u: "
711 "session lookup failed!",
712 getpid (), mp->handle, session_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400713 }
714 else
Dave Wallace4878cbe2017-11-21 03:45:09 -0500715 clib_warning ("[%d] vpp handle 0x%llx: session lookup by "
716 "handle failed!", getpid (), mp->handle);
Dave Wallace543852a2017-08-03 02:11:34 -0400717}
718
719static void
720vl_api_reset_session_t_handler (vl_api_reset_session_t * mp)
721{
Dave Wallace543852a2017-08-03 02:11:34 -0400722 session_t *session = 0;
723 vl_api_reset_session_reply_t *rmp;
724 uword *p;
725 int rv = 0;
726
727 p = hash_get (vcm->session_index_by_vpp_handles, mp->handle);
728 if (p)
729 {
730 int rval;
731 clib_spinlock_lock (&vcm->sessions_lockp);
732 rval = vppcom_session_at_index (p[0], &session);
733 if (PREDICT_FALSE (rval))
734 {
Dave Wallace4878cbe2017-11-21 03:45:09 -0500735 rv = VNET_API_ERROR_INVALID_VALUE_2;
736 clib_warning ("[%d] ERROR: sid %u: session lookup failed! "
737 "returning %d %U",
738 getpid (), p[0], rv, format_api_error, rv);
Dave Wallace543852a2017-08-03 02:11:34 -0400739 }
740 else
Dave Wallace4878cbe2017-11-21 03:45:09 -0500741 {
742 /* TBD: should this disconnect immediately and
743 * flush the fifos?
744 */
745 session->state = STATE_CLOSE_ON_EMPTY;
746
747 if (VPPCOM_DEBUG > 1)
748 clib_warning ("[%d] vpp handle 0x%llx, sid %u: "
749 "state set to %d (%s)!", getpid (),
750 mp->handle, p[0], session->state,
751 vppcom_session_state_str (session->state));
752 }
Dave Wallace543852a2017-08-03 02:11:34 -0400753 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -0400754 }
755 else
756 {
Dave Wallace4878cbe2017-11-21 03:45:09 -0500757 rv = VNET_API_ERROR_INVALID_VALUE;
758 clib_warning ("[%d] ERROR: vpp handle 0x%llx: session lookup "
759 "failed! returning %d %U",
760 getpid (), mp->handle, rv, format_api_error, rv);
Dave Wallace543852a2017-08-03 02:11:34 -0400761 }
762
763 rmp = vl_msg_api_alloc (sizeof (*rmp));
764 memset (rmp, 0, sizeof (*rmp));
765 rmp->_vl_msg_id = ntohs (VL_API_RESET_SESSION_REPLY);
766 rmp->retval = htonl (rv);
767 rmp->handle = mp->handle;
768 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
769}
770
771static void
Dave Wallace33e002b2017-09-06 01:20:02 -0400772vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp)
Dave Wallace543852a2017-08-03 02:11:34 -0400773{
Dave Wallace543852a2017-08-03 02:11:34 -0400774 session_t *session;
775 u32 session_index;
776 svm_fifo_t *rx_fifo, *tx_fifo;
777 u8 is_cut_thru = 0;
778 int rv;
779
Dave Wallace4878cbe2017-11-21 03:45:09 -0500780 session_index = mp->context;
Dave Wallace543852a2017-08-03 02:11:34 -0400781 if (mp->retval)
782 {
Dave Wallace4878cbe2017-11-21 03:45:09 -0500783 clib_warning ("[%d] ERROR: sid %u: connect failed! %U",
784 getpid (), session_index, format_api_error,
Dave Wallace543852a2017-08-03 02:11:34 -0400785 ntohl (mp->retval));
786 return;
787 }
788
Dave Wallace543852a2017-08-03 02:11:34 -0400789 if (VPPCOM_DEBUG > 1)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500790 clib_warning ("[%d] sid %u: got a connect reply!",
791 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400792
793 clib_spinlock_lock (&vcm->sessions_lockp);
794 if (pool_is_free_index (vcm->sessions, session_index))
795 {
796 clib_spinlock_unlock (&vcm->sessions_lockp);
797 if (VPPCOM_DEBUG > 1)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500798 clib_warning ("[%d] sid %d: session lookup failed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500799 getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400800 return;
801 }
802
803 /* We've been redirected */
804 if (mp->segment_name_length > 0)
805 {
806 static svm_fifo_segment_create_args_t _a;
807 svm_fifo_segment_create_args_t *a = &_a;
808
809 is_cut_thru = 1;
810 memset (a, 0, sizeof (*a));
811 a->segment_name = (char *) mp->segment_name;
812 if (VPPCOM_DEBUG > 1)
Dave Wallace60caa062017-11-10 17:07:13 -0500813 clib_warning ("[%d] cut-thru segment: %s\n",
814 getpid (), a->segment_name);
815
Dave Wallace543852a2017-08-03 02:11:34 -0400816 rv = svm_fifo_segment_attach (a);
817 vec_reset_length (a->new_segment_indices);
818 if (PREDICT_FALSE (rv))
819 {
Dave Wallacef7f809c2017-10-03 01:48:42 -0400820 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -0400821 clib_warning ("[%d] sm_fifo_segment_attach ('%s') failed",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500822 getpid (), a->segment_name);
Dave Wallace543852a2017-08-03 02:11:34 -0400823 return;
824 }
825 }
826
827 /*
828 * Setup session
829 */
Dave Wallace543852a2017-08-03 02:11:34 -0400830 session = pool_elt_at_index (vcm->sessions, session_index);
831 session->is_cut_thru = is_cut_thru;
Dave Wallace33e002b2017-09-06 01:20:02 -0400832 session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address,
833 unix_shared_memory_queue_t *);
Dave Wallace543852a2017-08-03 02:11:34 -0400834
835 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
836 rx_fifo->client_session_index = session_index;
837 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
838 tx_fifo->client_session_index = session_index;
839
840 session->server_rx_fifo = rx_fifo;
841 session->server_tx_fifo = tx_fifo;
Dave Wallace60caa062017-11-10 17:07:13 -0500842 session->vpp_handle = mp->handle;
Dave Wallace9d1d73a2017-11-20 02:31:48 -0500843 session->lcl_addr.is_ip4 = mp->is_ip4;
844 clib_memcpy (&session->lcl_addr.ip46, mp->lcl_ip,
845 sizeof (session->peer_addr.ip46));
846 session->lcl_port = mp->lcl_port;
Dave Wallace543852a2017-08-03 02:11:34 -0400847 session->state = STATE_CONNECT;
848
849 /* Add it to lookup table */
850 hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
Dave Wallace60caa062017-11-10 17:07:13 -0500851
852 if (VPPCOM_DEBUG > 1)
Dave Wallace3bd43b82017-11-11 22:45:38 -0500853 clib_warning ("[%d] client sid %d, vpp handle 0x%llx\n"
Dave Wallace60caa062017-11-10 17:07:13 -0500854 " session_rx_fifo %p, refcnt %d\n"
855 " session_tx_fifo %p, refcnt %d",
Dave Wallace3bd43b82017-11-11 22:45:38 -0500856 getpid (), session_index, mp->handle,
Dave Wallace60caa062017-11-10 17:07:13 -0500857 session->server_rx_fifo,
858 session->server_rx_fifo->refcnt,
859 session->server_tx_fifo, session->server_tx_fifo->refcnt);
860
Dave Wallace543852a2017-08-03 02:11:34 -0400861 clib_spinlock_unlock (&vcm->sessions_lockp);
862}
863
864static void
865vppcom_send_connect_sock (session_t * session, u32 session_index)
866{
Dave Wallace543852a2017-08-03 02:11:34 -0400867 vl_api_connect_sock_t *cmp;
868
869 /* Assumes caller as acquired the spinlock: vcm->sessions_lockp */
870 session->is_server = 0;
871 cmp = vl_msg_api_alloc (sizeof (*cmp));
872 memset (cmp, 0, sizeof (*cmp));
873 cmp->_vl_msg_id = ntohs (VL_API_CONNECT_SOCK);
874 cmp->client_index = vcm->my_client_index;
Dave Wallace33e002b2017-09-06 01:20:02 -0400875 cmp->context = session_index;
Dave Wallace543852a2017-08-03 02:11:34 -0400876
Dave Wallace543852a2017-08-03 02:11:34 -0400877 cmp->vrf = session->vrf;
Dave Wallace35830af2017-10-09 01:43:42 -0400878 cmp->is_ip4 = session->peer_addr.is_ip4;
879 clib_memcpy (cmp->ip, &session->peer_addr.ip46, sizeof (cmp->ip));
Stevenac1f96d2017-10-24 16:03:58 -0700880 cmp->port = session->peer_port;
Dave Wallace543852a2017-08-03 02:11:34 -0400881 cmp->proto = session->proto;
882 clib_memcpy (cmp->options, session->options, sizeof (cmp->options));
883 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & cmp);
884}
885
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400886static inline void
Dave Wallace4878cbe2017-11-21 03:45:09 -0500887vppcom_send_disconnect_session_reply (u64 vpp_handle, u32 session_index,
888 int rv)
889{
890 vl_api_disconnect_session_reply_t *rmp;
891
892 if (VPPCOM_DEBUG > 1)
893 clib_warning ("[%d] vpp handle 0x%llx, sid %u: sending disconnect msg",
894 getpid (), vpp_handle, session_index);
895
896 rmp = vl_msg_api_alloc (sizeof (*rmp));
897 memset (rmp, 0, sizeof (*rmp));
898
899 rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY);
900 rmp->retval = htonl (rv);
901 rmp->handle = vpp_handle;
902 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
903}
904
905static inline void
906vppcom_send_disconnect_session (u64 vpp_handle, u32 session_index)
Dave Wallace543852a2017-08-03 02:11:34 -0400907{
Dave Wallace543852a2017-08-03 02:11:34 -0400908 vl_api_disconnect_session_t *dmp;
Dave Wallace543852a2017-08-03 02:11:34 -0400909
Dave Wallace4878cbe2017-11-21 03:45:09 -0500910 if (VPPCOM_DEBUG > 1)
911 clib_warning ("[%d] vpp handle 0x%llx, sid %u: sending disconnect msg",
912 getpid (), vpp_handle, session_index);
913
Dave Wallace543852a2017-08-03 02:11:34 -0400914 dmp = vl_msg_api_alloc (sizeof (*dmp));
915 memset (dmp, 0, sizeof (*dmp));
916 dmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION);
917 dmp->client_index = vcm->my_client_index;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500918 dmp->handle = vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400919 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & dmp);
Dave Wallace543852a2017-08-03 02:11:34 -0400920}
921
922static void
923vl_api_bind_sock_reply_t_handler (vl_api_bind_sock_reply_t * mp)
924{
Dave Wallace543852a2017-08-03 02:11:34 -0400925 session_t *session = 0;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500926 u32 session_index = mp->context;
Dave Wallace543852a2017-08-03 02:11:34 -0400927 int rv;
928
929 if (mp->retval)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500930 {
931 clib_warning ("[%d] ERROR: sid %u: bind failed: %U",
932 getpid (), session_index, format_api_error,
933 ntohl (mp->retval));
934 rv = vppcom_session_at_index (session_index, &session);
935 if (rv == VPPCOM_OK)
936 session->state = STATE_FAILED;
937 return;
938 }
Dave Wallace543852a2017-08-03 02:11:34 -0400939
940 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500941 rv = vppcom_session_at_index (session_index, &session);
Dave Wallace543852a2017-08-03 02:11:34 -0400942 if (rv == VPPCOM_OK)
943 {
Dave Wallace60caa062017-11-10 17:07:13 -0500944 session->vpp_handle = mp->handle;
Florin Corasdcf55ce2017-11-16 15:32:50 -0800945 session->lcl_addr.is_ip4 = mp->lcl_is_ip4;
946 clib_memcpy (&session->lcl_addr.ip46, mp->lcl_ip,
947 sizeof (session->peer_addr.ip46));
948 session->lcl_port = mp->lcl_port;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500949 vppcom_session_table_add_listener (mp->handle, session_index);
950 session->is_listen = 1;
951 session->state = STATE_LISTEN;
952
953 if (VPPCOM_DEBUG > 1)
954 clib_warning ("[%d] sid %u: bind succeeded! ", getpid (),
955 mp->context);
Dave Wallace543852a2017-08-03 02:11:34 -0400956 }
957 clib_spinlock_unlock (&vcm->sessions_lockp);
958}
959
960static void
961vl_api_unbind_sock_reply_t_handler (vl_api_unbind_sock_reply_t * mp)
962{
Dave Wallace4878cbe2017-11-21 03:45:09 -0500963 if (mp->retval)
964 clib_warning ("[%d] ERROR: sid %u: unbind failed: %U",
965 getpid (), mp->context, format_api_error,
966 ntohl (mp->retval));
Dave Wallace543852a2017-08-03 02:11:34 -0400967
Dave Wallace4878cbe2017-11-21 03:45:09 -0500968 else if (VPPCOM_DEBUG > 1)
969 clib_warning ("[%d] sid %u: unbind succeeded!", getpid (), mp->context);
Dave Wallace543852a2017-08-03 02:11:34 -0400970}
971
972u8 *
973format_ip4_address (u8 * s, va_list * args)
974{
975 u8 *a = va_arg (*args, u8 *);
976 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
977}
978
979u8 *
980format_ip6_address (u8 * s, va_list * args)
981{
982 ip6_address_t *a = va_arg (*args, ip6_address_t *);
983 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
984
985 i_max_n_zero = ARRAY_LEN (a->as_u16);
986 max_n_zeros = 0;
987 i_first_zero = i_max_n_zero;
988 n_zeros = 0;
989 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
990 {
991 u32 is_zero = a->as_u16[i] == 0;
992 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
993 {
994 i_first_zero = i;
995 n_zeros = 0;
996 }
997 n_zeros += is_zero;
998 if ((!is_zero && n_zeros > max_n_zeros)
999 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
1000 {
1001 i_max_n_zero = i_first_zero;
1002 max_n_zeros = n_zeros;
1003 i_first_zero = ARRAY_LEN (a->as_u16);
1004 n_zeros = 0;
1005 }
1006 }
1007
1008 last_double_colon = 0;
1009 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
1010 {
1011 if (i == i_max_n_zero && max_n_zeros > 1)
1012 {
1013 s = format (s, "::");
1014 i += max_n_zeros - 1;
1015 last_double_colon = 1;
1016 }
1017 else
1018 {
1019 s = format (s, "%s%x",
1020 (last_double_colon || i == 0) ? "" : ":",
1021 clib_net_to_host_u16 (a->as_u16[i]));
1022 last_double_colon = 0;
1023 }
1024 }
1025
1026 return s;
1027}
1028
1029/* Format an IP46 address. */
1030u8 *
1031format_ip46_address (u8 * s, va_list * args)
1032{
1033 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
1034 ip46_type_t type = va_arg (*args, ip46_type_t);
1035 int is_ip4 = 1;
1036
1037 switch (type)
1038 {
1039 case IP46_TYPE_ANY:
1040 is_ip4 = ip46_address_is_ip4 (ip46);
1041 break;
1042 case IP46_TYPE_IP4:
1043 is_ip4 = 1;
1044 break;
1045 case IP46_TYPE_IP6:
1046 is_ip4 = 0;
1047 break;
1048 }
1049
1050 return is_ip4 ?
1051 format (s, "%U", format_ip4_address, &ip46->ip4) :
1052 format (s, "%U", format_ip6_address, &ip46->ip6);
1053}
1054
Dave Wallace60caa062017-11-10 17:07:13 -05001055static inline void
1056vppcom_send_accept_session_reply (u32 handle, int retval)
1057{
1058 vl_api_accept_session_reply_t *rmp;
1059
1060 rmp = vl_msg_api_alloc (sizeof (*rmp));
1061 memset (rmp, 0, sizeof (*rmp));
1062 rmp->_vl_msg_id = ntohs (VL_API_ACCEPT_SESSION_REPLY);
1063 rmp->retval = htonl (retval);
1064 rmp->handle = handle;
1065 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
1066}
1067
Dave Wallace543852a2017-08-03 02:11:34 -04001068static void
1069vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
1070{
Dave Wallace543852a2017-08-03 02:11:34 -04001071 svm_fifo_t *rx_fifo, *tx_fifo;
Florin Corasdcf55ce2017-11-16 15:32:50 -08001072 session_t *session, *listen_session;
Dave Wallace543852a2017-08-03 02:11:34 -04001073 u32 session_index;
Dave Wallace543852a2017-08-03 02:11:34 -04001074
Dave Wallace60caa062017-11-10 17:07:13 -05001075 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04001076 if (!clib_fifo_free_elts (vcm->client_session_index_fifo))
1077 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05001078 clib_warning ("[%d] client session queue is full!", getpid ());
Florin Corasdcf55ce2017-11-16 15:32:50 -08001079 vppcom_send_accept_session_reply (mp->handle,
1080 VNET_API_ERROR_QUEUE_FULL);
1081 clib_spinlock_unlock (&vcm->sessions_lockp);
1082 return;
1083 }
1084
1085 listen_session = vppcom_session_table_lookup_listener (mp->listener_handle);
1086 if (!listen_session)
1087 {
1088 clib_warning ("[%d] ERROR: couldn't find listen session: unknown vpp "
1089 "listener handle %llx", getpid (), mp->listener_handle);
Dave Wallace60caa062017-11-10 17:07:13 -05001090 clib_spinlock_unlock (&vcm->sessions_lockp);
1091 return;
Dave Wallace543852a2017-08-03 02:11:34 -04001092 }
1093
Dave Wallace543852a2017-08-03 02:11:34 -04001094 /* Allocate local session and set it up */
1095 pool_get (vcm->sessions, session);
1096 memset (session, 0, sizeof (*session));
1097 session_index = session - vcm->sessions;
1098
1099 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
1100 rx_fifo->client_session_index = session_index;
1101 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
1102 tx_fifo->client_session_index = session_index;
1103
Dave Wallace60caa062017-11-10 17:07:13 -05001104 session->vpp_handle = mp->handle;
Dave Wallace543852a2017-08-03 02:11:34 -04001105 session->server_rx_fifo = rx_fifo;
1106 session->server_tx_fifo = tx_fifo;
Dave Wallace33e002b2017-09-06 01:20:02 -04001107 session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address,
1108 unix_shared_memory_queue_t *);
Dave Wallace543852a2017-08-03 02:11:34 -04001109 session->state = STATE_ACCEPT;
1110 session->is_cut_thru = 0;
Dave Wallace19481612017-09-15 18:47:44 -04001111 session->is_server = 1;
Stevenac1f96d2017-10-24 16:03:58 -07001112 session->peer_port = mp->port;
Dave Wallace35830af2017-10-09 01:43:42 -04001113 session->peer_addr.is_ip4 = mp->is_ip4;
1114 clib_memcpy (&session->peer_addr.ip46, mp->ip,
1115 sizeof (session->peer_addr.ip46));
Dave Wallace543852a2017-08-03 02:11:34 -04001116
1117 /* Add it to lookup table */
1118 hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
Florin Corasdcf55ce2017-11-16 15:32:50 -08001119 session->lcl_port = listen_session->lcl_port;
1120 session->lcl_addr = listen_session->lcl_addr;
Dave Wallace227867f2017-11-13 21:21:53 -05001121
1122 /* TBD: move client_session_index_fifo into listener session */
Dave Wallace543852a2017-08-03 02:11:34 -04001123 clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
Florin Corasdcf55ce2017-11-16 15:32:50 -08001124
Dave Wallacef7f809c2017-10-03 01:48:42 -04001125 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04001126
Dave Wallace60caa062017-11-10 17:07:13 -05001127 if (VPPCOM_DEBUG > 1)
1128 {
1129 u8 *ip_str = format (0, "%U", format_ip46_address, &mp->ip, mp->is_ip4);
1130 clib_warning ("[%d] received request to accept session (sid %d) "
1131 "from %s:%d", getpid (), session_index, ip_str,
1132 clib_net_to_host_u16 (mp->port));
1133 vec_free (ip_str);
1134 }
1135}
1136
1137static void
Dave Wallace227867f2017-11-13 21:21:53 -05001138vppcom_send_connect_session_reply (session_t * session, int retval)
Dave Wallace60caa062017-11-10 17:07:13 -05001139{
1140 vl_api_connect_session_reply_t *rmp;
1141 u32 len;
1142 unix_shared_memory_queue_t *client_q;
1143
Dave Wallace543852a2017-08-03 02:11:34 -04001144 rmp = vl_msg_api_alloc (sizeof (*rmp));
1145 memset (rmp, 0, sizeof (*rmp));
Dave Wallace60caa062017-11-10 17:07:13 -05001146
1147 rmp->_vl_msg_id = ntohs (VL_API_CONNECT_SESSION_REPLY);
Dave Wallace227867f2017-11-13 21:21:53 -05001148 rmp->context = session->client_context;
Dave Wallace60caa062017-11-10 17:07:13 -05001149 rmp->retval = htonl (retval);
Dave Wallace227867f2017-11-13 21:21:53 -05001150 rmp->handle = session->vpp_handle;
1151 rmp->server_rx_fifo = pointer_to_uword (session->server_rx_fifo);
1152 rmp->server_tx_fifo = pointer_to_uword (session->server_tx_fifo);
1153 rmp->vpp_event_queue_address = pointer_to_uword (session->vpp_event_queue);
1154 rmp->segment_size = vcm->cfg.segment_size;
1155 len = vec_len (session->segment_name);
1156 rmp->segment_name_length = clib_min (len, sizeof (rmp->segment_name));
1157 clib_memcpy (rmp->segment_name, session->segment_name,
1158 rmp->segment_name_length - 1);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001159 clib_memcpy (rmp->lcl_ip, session->peer_addr.ip46.as_u8,
Dave Wallace227867f2017-11-13 21:21:53 -05001160 sizeof (rmp->lcl_ip));
Dave Wallace4878cbe2017-11-21 03:45:09 -05001161 rmp->is_ip4 = session->peer_addr.is_ip4;
1162 rmp->lcl_port = session->peer_port;
Dave Wallace60caa062017-11-10 17:07:13 -05001163 client_q = uword_to_pointer (session->client_queue_address,
1164 unix_shared_memory_queue_t *);
1165 ASSERT (client_q);
1166 vl_msg_api_send_shmem (client_q, (u8 *) & rmp);
Dave Wallace543852a2017-08-03 02:11:34 -04001167}
1168
1169/*
1170 * Acting as server for redirected connect requests
1171 */
1172static void
1173vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp)
1174{
Dave Wallace543852a2017-08-03 02:11:34 -04001175 u32 session_index;
Dave Wallace543852a2017-08-03 02:11:34 -04001176 session_t *session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001177
Dave Wallacef7f809c2017-10-03 01:48:42 -04001178 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04001179 if (!clib_fifo_free_elts (vcm->client_session_index_fifo))
1180 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05001181 clib_spinlock_unlock (&vcm->sessions_lockp);
1182
Dave Wallace543852a2017-08-03 02:11:34 -04001183 if (VPPCOM_DEBUG > 1)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001184 clib_warning ("[%d] client session queue is full!", getpid ());
Dave Wallace4878cbe2017-11-21 03:45:09 -05001185
1186 /* TBD: fix handle missing in api msg. */
Florin Corasdcf55ce2017-11-16 15:32:50 -08001187 vppcom_send_accept_session_reply (0, VNET_API_ERROR_QUEUE_FULL);
Dave Wallace60caa062017-11-10 17:07:13 -05001188 return;
Dave Wallace543852a2017-08-03 02:11:34 -04001189 }
1190
Dave Wallace543852a2017-08-03 02:11:34 -04001191 pool_get (vcm->sessions, session);
1192 memset (session, 0, sizeof (*session));
1193 session_index = session - vcm->sessions;
1194
Dave Wallace60caa062017-11-10 17:07:13 -05001195 session->client_context = mp->context;
1196 session->vpp_handle = session_index;
Dave Wallace543852a2017-08-03 02:11:34 -04001197 session->client_queue_address = mp->client_queue_address;
1198 session->is_cut_thru = 1;
1199 session->is_server = 1;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001200 session->lcl_port = mp->port;
1201 session->lcl_addr.is_ip4 = mp->is_ip4;
1202 clib_memcpy (&session->lcl_addr.ip46, mp->ip,
1203 sizeof (session->lcl_addr.ip46));
1204
1205 /* TBD: missing peer info in api msg.
1206 */
Dave Wallace35830af2017-10-09 01:43:42 -04001207 session->peer_addr.is_ip4 = mp->is_ip4;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001208 ASSERT (session->lcl_addr.is_ip4 == session->peer_addr.is_ip4);
Dave Wallace6d5c4cd2017-08-15 16:56:29 -04001209
Dave Wallace543852a2017-08-03 02:11:34 -04001210 session->state = STATE_ACCEPT;
Dave Wallace543852a2017-08-03 02:11:34 -04001211 clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
Dave Wallace2e005bb2017-11-07 01:21:39 -05001212 if (VPPCOM_DEBUG > 1)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001213 clib_warning ("[%d] sid %u: Got a cut-thru connect request! "
1214 "clib_fifo_elts %u!\n", getpid (), session_index,
1215 clib_fifo_elts (vcm->client_session_index_fifo));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001216 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace543852a2017-08-03 02:11:34 -04001217}
1218
1219static void
Dave Wallace4878cbe2017-11-21 03:45:09 -05001220vppcom_send_bind_sock (session_t * session, u32 session_index)
Dave Wallace543852a2017-08-03 02:11:34 -04001221{
Dave Wallace543852a2017-08-03 02:11:34 -04001222 vl_api_bind_sock_t *bmp;
1223
1224 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
1225 session->is_server = 1;
1226 bmp = vl_msg_api_alloc (sizeof (*bmp));
1227 memset (bmp, 0, sizeof (*bmp));
1228
1229 bmp->_vl_msg_id = ntohs (VL_API_BIND_SOCK);
1230 bmp->client_index = vcm->my_client_index;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001231 bmp->context = session_index;
Dave Wallace543852a2017-08-03 02:11:34 -04001232 bmp->vrf = session->vrf;
Dave Wallace35830af2017-10-09 01:43:42 -04001233 bmp->is_ip4 = session->lcl_addr.is_ip4;
1234 clib_memcpy (bmp->ip, &session->lcl_addr.ip46, sizeof (bmp->ip));
Stevenac1f96d2017-10-24 16:03:58 -07001235 bmp->port = session->lcl_port;
Dave Wallace543852a2017-08-03 02:11:34 -04001236 bmp->proto = session->proto;
1237 clib_memcpy (bmp->options, session->options, sizeof (bmp->options));
1238 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
1239}
1240
1241static void
Dave Wallace4878cbe2017-11-21 03:45:09 -05001242vppcom_send_unbind_sock (u64 vpp_handle)
Dave Wallace543852a2017-08-03 02:11:34 -04001243{
Dave Wallace543852a2017-08-03 02:11:34 -04001244 vl_api_unbind_sock_t *ump;
Dave Wallace543852a2017-08-03 02:11:34 -04001245
1246 ump = vl_msg_api_alloc (sizeof (*ump));
1247 memset (ump, 0, sizeof (*ump));
1248
1249 ump->_vl_msg_id = ntohs (VL_API_UNBIND_SOCK);
1250 ump->client_index = vcm->my_client_index;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001251 ump->handle = vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -04001252 vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & ump);
1253}
1254
1255static int
Dave Wallace543852a2017-08-03 02:11:34 -04001256vppcom_session_unbind (u32 session_index)
1257{
Dave Wallace4878cbe2017-11-21 03:45:09 -05001258 session_t *session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001259 int rv;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001260 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -04001261
Dave Wallace4878cbe2017-11-21 03:45:09 -05001262 VCL_LOCK_AND_GET_SESSION (session_index, &session);
1263
1264 vpp_handle = session->vpp_handle;
1265 vppcom_session_table_del_listener (vpp_handle);
1266 session->vpp_handle = ~0;
1267 session->state = STATE_DISCONNECT;
1268
Dave Wallace543852a2017-08-03 02:11:34 -04001269 clib_spinlock_unlock (&vcm->sessions_lockp);
1270
Dave Wallace4878cbe2017-11-21 03:45:09 -05001271 if (VPPCOM_DEBUG > 1)
1272 clib_warning ("[%d] vpp handle 0x%llx, sid %u: "
1273 "sending unbind msg! new state 0x%x (%s)",
1274 getpid (), vpp_handle, session_index,
1275 session->state, vppcom_session_state_str (session->state));
1276
1277 vppcom_send_unbind_sock (vpp_handle);
1278
1279done:
1280 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001281}
1282
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001283static inline int
Dave Wallace543852a2017-08-03 02:11:34 -04001284vppcom_session_disconnect (u32 session_index)
1285{
Dave Wallace543852a2017-08-03 02:11:34 -04001286 int rv;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001287 session_t *session;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001288 u8 is_cut_thru, is_listen, is_server;
1289 u64 vpp_handle;
1290 session_state_t state;
Dave Wallace543852a2017-08-03 02:11:34 -04001291
Dave Wallace4878cbe2017-11-21 03:45:09 -05001292 VCL_LOCK_AND_GET_SESSION (session_index, &session);
1293
1294 vpp_handle = session->vpp_handle;
1295 is_server = session->is_server;
1296 is_listen = session->is_listen;
1297 is_cut_thru = session->is_cut_thru;
1298 state = session->state;
1299 clib_spinlock_unlock (&vcm->sessions_lockp);
1300
1301 if (VPPCOM_DEBUG > 1)
Dave Wallace543852a2017-08-03 02:11:34 -04001302 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05001303 clib_warning ("[%d] vpp handle 0x%llx, sid %u: %s state 0x%x (%s), "
1304 "is_cut_thru %d, is_listen %d",
1305 getpid (), vpp_handle, session_index,
1306 is_server ? "server" : "client",
1307 state, vppcom_session_state_str (state),
1308 is_cut_thru, is_listen);
Dave Wallace543852a2017-08-03 02:11:34 -04001309 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001310
Dave Wallace4878cbe2017-11-21 03:45:09 -05001311 if (PREDICT_FALSE (is_listen))
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001312 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05001313 clib_warning ("[%d] ERROR: sid %u: Cannot disconnect a "
1314 "listen socket!", getpid (), session_index);
1315 rv = VPPCOM_EBADFD;
1316 goto done;
1317 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001318
Dave Wallace4878cbe2017-11-21 03:45:09 -05001319 /* Through the VPP host stack...
1320 */
1321 else if (!is_cut_thru)
1322 {
1323 /* The peer has already initiated the close,
1324 * so send the disconnect session reply.
Dave Wallace227867f2017-11-13 21:21:53 -05001325 */
Dave Wallace4878cbe2017-11-21 03:45:09 -05001326 if (state & STATE_CLOSE_ON_EMPTY)
1327 {
1328 vppcom_send_disconnect_session_reply (vpp_handle,
1329 session_index, 0 /* rv */ );
1330 if (VPPCOM_DEBUG > 1)
1331 clib_warning ("[%d] sid %u: sending disconnect REPLY...",
1332 getpid (), session_index);
1333 }
1334
1335 /* Otherwise, send a disconnect session msg...
1336 */
1337 else
1338 {
1339 if (VPPCOM_DEBUG > 1)
1340 clib_warning ("[%d] sid %u: sending disconnect...",
1341 getpid (), session_index, state,
1342 vppcom_session_state_str (state));
1343
1344 vppcom_send_disconnect_session (vpp_handle, session_index);
1345 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001346 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001347
1348 /* Cut-thru connections...
1349 *
1350 * server: free fifos and segment allocated during connect/redirect
1351 * client: no cleanup required
1352 */
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001353 else
Dave Wallace227867f2017-11-13 21:21:53 -05001354 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05001355 if (is_server)
1356 {
1357 svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
1358 svm_fifo_segment_private_t *seg;
1359
1360 VCL_LOCK_AND_GET_SESSION (session_index, &session);
1361
1362 if (VPPCOM_DEBUG > 1)
1363 clib_warning ("[%d] sid %d: freeing cut-thru fifos in "
1364 "sm_seg_index %d\n"
1365 " server_rx_fifo %p, refcnt = %d\n"
1366 " server_tx_fifo %p, refcnt = %d",
1367 getpid (), session_index, session->sm_seg_index,
1368 session->server_rx_fifo,
1369 session->server_rx_fifo->refcnt,
1370 session->server_tx_fifo,
1371 session->server_tx_fifo->refcnt);
1372
1373 seg = vec_elt_at_index (sm->segments, session->sm_seg_index);
1374 svm_fifo_segment_free_fifo (seg, session->server_rx_fifo,
1375 FIFO_SEGMENT_RX_FREELIST);
1376 svm_fifo_segment_free_fifo (seg, session->server_tx_fifo,
1377 FIFO_SEGMENT_TX_FREELIST);
1378 svm_fifo_segment_delete (seg);
1379
1380 /* TBD: Send cut-thru disconnect event to client */
1381
1382 clib_spinlock_unlock (&vcm->sessions_lockp);
1383 }
1384 else
1385 {
1386 /* TBD: Send cut-thru disconnect event to server */
1387 }
Dave Wallace227867f2017-11-13 21:21:53 -05001388 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001389
Dave Wallace4878cbe2017-11-21 03:45:09 -05001390done:
1391 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001392}
1393
1394#define foreach_sock_msg \
1395_(SESSION_ENABLE_DISABLE_REPLY, session_enable_disable_reply) \
1396_(BIND_SOCK_REPLY, bind_sock_reply) \
1397_(UNBIND_SOCK_REPLY, unbind_sock_reply) \
1398_(ACCEPT_SESSION, accept_session) \
1399_(CONNECT_SOCK, connect_sock) \
Dave Wallace33e002b2017-09-06 01:20:02 -04001400_(CONNECT_SESSION_REPLY, connect_session_reply) \
Dave Wallace543852a2017-08-03 02:11:34 -04001401_(DISCONNECT_SESSION, disconnect_session) \
1402_(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \
1403_(RESET_SESSION, reset_session) \
1404_(APPLICATION_ATTACH_REPLY, application_attach_reply) \
1405_(APPLICATION_DETACH_REPLY, application_detach_reply) \
1406_(MAP_ANOTHER_SEGMENT, map_another_segment)
1407
1408static void
1409vppcom_api_hookup (void)
1410{
1411#define _(N,n) \
1412 vl_msg_api_set_handlers(VL_API_##N, #n, \
1413 vl_api_##n##_t_handler, \
1414 vl_noop_handler, \
1415 vl_api_##n##_t_endian, \
1416 vl_api_##n##_t_print, \
1417 sizeof(vl_api_##n##_t), 1);
1418 foreach_sock_msg;
1419#undef _
1420}
1421
1422static void
1423vppcom_cfg_init (vppcom_cfg_t * vcl_cfg)
1424{
1425 ASSERT (vcl_cfg);
1426
1427 vcl_cfg->heapsize = (256ULL << 20);
1428 vcl_cfg->segment_baseva = 0x200000000ULL;
1429 vcl_cfg->segment_size = (256 << 20);
1430 vcl_cfg->add_segment_size = (128 << 20);
1431 vcl_cfg->preallocated_fifo_pairs = 8;
1432 vcl_cfg->rx_fifo_size = (1 << 20);
1433 vcl_cfg->tx_fifo_size = (1 << 20);
1434 vcl_cfg->event_queue_size = 2048;
1435 vcl_cfg->listen_queue_size = CLIB_CACHE_LINE_BYTES / sizeof (u32);
1436 vcl_cfg->app_timeout = 10 * 60.0;
1437 vcl_cfg->session_timeout = 10 * 60.0;
1438 vcl_cfg->accept_timeout = 60.0;
1439}
1440
1441static void
1442vppcom_cfg_heapsize (char *conf_fname)
1443{
Dave Wallace543852a2017-08-03 02:11:34 -04001444 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
1445 FILE *fp;
1446 char inbuf[4096];
1447 int argc = 1;
1448 char **argv = NULL;
1449 char *arg = NULL;
1450 char *p;
1451 int i;
1452 u8 *sizep;
1453 u32 size;
Dave Wallace2e005bb2017-11-07 01:21:39 -05001454 void *vcl_mem;
1455 void *heap;
Dave Wallace543852a2017-08-03 02:11:34 -04001456
1457 fp = fopen (conf_fname, "r");
1458 if (fp == NULL)
1459 {
1460 if (VPPCOM_DEBUG > 0)
1461 fprintf (stderr, "open configuration file '%s' failed\n", conf_fname);
1462 goto defaulted;
1463 }
1464 argv = calloc (1, sizeof (char *));
1465 if (argv == NULL)
1466 goto defaulted;
1467
1468 while (1)
1469 {
1470 if (fgets (inbuf, 4096, fp) == 0)
1471 break;
1472 p = strtok (inbuf, " \t\n");
1473 while (p != NULL)
1474 {
1475 if (*p == '#')
1476 break;
1477 argc++;
1478 char **tmp = realloc (argv, argc * sizeof (char *));
1479 if (tmp == NULL)
Chris Lukeab7b8d92017-09-07 07:40:13 -04001480 goto defaulted;
Dave Wallace543852a2017-08-03 02:11:34 -04001481 argv = tmp;
1482 arg = strndup (p, 1024);
1483 if (arg == NULL)
Chris Lukeab7b8d92017-09-07 07:40:13 -04001484 goto defaulted;
Dave Wallace543852a2017-08-03 02:11:34 -04001485 argv[argc - 1] = arg;
1486 p = strtok (NULL, " \t\n");
1487 }
1488 }
1489
1490 fclose (fp);
Chris Lukeab7b8d92017-09-07 07:40:13 -04001491 fp = NULL;
Dave Wallace543852a2017-08-03 02:11:34 -04001492
1493 char **tmp = realloc (argv, (argc + 1) * sizeof (char *));
1494 if (tmp == NULL)
1495 goto defaulted;
1496 argv = tmp;
1497 argv[argc] = NULL;
1498
1499 /*
1500 * Look for and parse the "heapsize" config parameter.
1501 * Manual since none of the clib infra has been bootstrapped yet.
1502 *
1503 * Format: heapsize <nn>[mM][gG]
1504 */
1505
1506 for (i = 1; i < (argc - 1); i++)
1507 {
1508 if (!strncmp (argv[i], "heapsize", 8))
1509 {
1510 sizep = (u8 *) argv[i + 1];
1511 size = 0;
1512 while (*sizep >= '0' && *sizep <= '9')
1513 {
1514 size *= 10;
1515 size += *sizep++ - '0';
1516 }
1517 if (size == 0)
1518 {
1519 if (VPPCOM_DEBUG > 0)
1520 clib_warning ("[%d] parse error '%s %s', "
1521 "using default heapsize %lld (0x%llx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001522 getpid (), argv[i], argv[i + 1],
Dave Wallace543852a2017-08-03 02:11:34 -04001523 vcl_cfg->heapsize, vcl_cfg->heapsize);
1524 goto defaulted;
1525 }
1526
1527 if (*sizep == 'g' || *sizep == 'G')
1528 vcl_cfg->heapsize = size << 30;
1529 else if (*sizep == 'm' || *sizep == 'M')
1530 vcl_cfg->heapsize = size << 20;
1531 else
1532 {
1533 if (VPPCOM_DEBUG > 0)
1534 clib_warning ("[%d] parse error '%s %s', "
1535 "using default heapsize %lld (0x%llx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001536 getpid (), argv[i], argv[i + 1],
Dave Wallace543852a2017-08-03 02:11:34 -04001537 vcl_cfg->heapsize, vcl_cfg->heapsize);
1538 goto defaulted;
1539 }
1540 }
1541 }
1542
1543defaulted:
Chris Lukeab7b8d92017-09-07 07:40:13 -04001544 if (fp != NULL)
1545 fclose (fp);
1546 if (argv != NULL)
1547 free (argv);
Dave Wallacee7fa24e2017-11-07 13:07:44 -05001548
Dave Wallace2e005bb2017-11-07 01:21:39 -05001549 vcl_mem = mmap (0, vcl_cfg->heapsize, PROT_READ | PROT_WRITE,
1550 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
Steven0cdd5bd2017-11-08 14:14:45 -08001551 if (vcl_mem == MAP_FAILED)
Dave Wallacee7fa24e2017-11-07 13:07:44 -05001552 {
1553 clib_unix_error ("[%d] ERROR: mmap(0, %lld == 0x%llx, "
1554 "PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, "
1555 "-1, 0) failed!",
1556 getpid (), vcl_cfg->heapsize, vcl_cfg->heapsize);
1557 return;
1558 }
Dave Wallace2e005bb2017-11-07 01:21:39 -05001559 heap = clib_mem_init (vcl_mem, vcl_cfg->heapsize);
1560 if (!heap)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001561 {
Dave Wallacee7fa24e2017-11-07 13:07:44 -05001562 clib_warning ("[%d] ERROR: clib_mem_init() failed!", getpid ());
1563 return;
Dave Wallace2e005bb2017-11-07 01:21:39 -05001564 }
Dave Wallacee7fa24e2017-11-07 13:07:44 -05001565 vcl_mem = clib_mem_alloc (sizeof (_vppcom_main));
1566 if (!vcl_mem)
1567 {
1568 clib_warning ("[%d] ERROR: clib_mem_alloc() failed!", getpid ());
1569 return;
1570 }
1571
1572 clib_memcpy (vcl_mem, &_vppcom_main, sizeof (_vppcom_main));
1573 vcm = vcl_mem;
1574
1575 if (VPPCOM_DEBUG > 0)
1576 clib_warning ("[%d] allocated VCL heap = %p, size %lld (0x%llx)",
1577 getpid (), heap, vcl_cfg->heapsize, vcl_cfg->heapsize);
Dave Wallace543852a2017-08-03 02:11:34 -04001578}
1579
1580static void
1581vppcom_cfg_read (char *conf_fname)
1582{
Dave Wallace543852a2017-08-03 02:11:34 -04001583 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
1584 int fd;
1585 unformat_input_t _input, *input = &_input;
1586 unformat_input_t _line_input, *line_input = &_line_input;
1587 u8 vc_cfg_input = 0;
1588 u8 *chroot_path;
1589 struct stat s;
1590 u32 uid, gid;
1591
1592 fd = open (conf_fname, O_RDONLY);
1593 if (fd < 0)
1594 {
1595 if (VPPCOM_DEBUG > 0)
1596 clib_warning ("[%d] open configuration file '%s' failed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001597 getpid (), conf_fname);
Dave Wallace543852a2017-08-03 02:11:34 -04001598 goto file_done;
1599 }
1600
1601 if (fstat (fd, &s) < 0)
1602 {
1603 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001604 clib_warning ("[%d] failed to stat `%s'", getpid (), conf_fname);
Dave Wallace543852a2017-08-03 02:11:34 -04001605 goto file_done;
1606 }
1607
1608 if (!(S_ISREG (s.st_mode) || S_ISLNK (s.st_mode)))
1609 {
1610 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001611 clib_warning ("[%d] not a regular file `%s'", getpid (), conf_fname);
Dave Wallace543852a2017-08-03 02:11:34 -04001612 goto file_done;
1613 }
1614
Dave Barach59b25652017-09-10 15:04:27 -04001615 unformat_init_clib_file (input, fd);
Dave Wallace543852a2017-08-03 02:11:34 -04001616
1617 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1618 {
Chris Lukeb2bcad62017-09-18 08:51:22 -04001619 (void) unformat_user (input, unformat_line_input, line_input);
Dave Wallace543852a2017-08-03 02:11:34 -04001620 unformat_skip_white_space (line_input);
1621
Dave Wallace8af20542017-10-26 03:29:30 -04001622 if (unformat (line_input, "vcl {"))
Dave Wallace543852a2017-08-03 02:11:34 -04001623 {
1624 vc_cfg_input = 1;
1625 continue;
1626 }
1627
1628 if (vc_cfg_input)
1629 {
1630 if (unformat (line_input, "heapsize %s", &chroot_path))
1631 {
1632 vec_terminate_c_string (chroot_path);
1633 if (VPPCOM_DEBUG > 0)
1634 clib_warning ("[%d] configured heapsize %s, "
1635 "actual heapsize %lld (0x%llx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001636 getpid (), chroot_path, vcl_cfg->heapsize,
Dave Wallace543852a2017-08-03 02:11:34 -04001637 vcl_cfg->heapsize);
1638 vec_free (chroot_path);
1639 }
1640 else if (unformat (line_input, "api-prefix %s", &chroot_path))
1641 {
1642 vec_terminate_c_string (chroot_path);
1643 vl_set_memory_root_path ((char *) chroot_path);
1644 if (VPPCOM_DEBUG > 0)
1645 clib_warning ("[%d] configured api-prefix %s",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001646 getpid (), chroot_path);
Dave Wallace543852a2017-08-03 02:11:34 -04001647 chroot_path = 0; /* Don't vec_free() it! */
1648 }
1649 else if (unformat (line_input, "uid %d", &uid))
1650 {
1651 vl_set_memory_uid (uid);
1652 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001653 clib_warning ("[%d] configured uid %d", getpid (), uid);
Dave Wallace543852a2017-08-03 02:11:34 -04001654 }
1655 else if (unformat (line_input, "gid %d", &gid))
1656 {
1657 vl_set_memory_gid (gid);
1658 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001659 clib_warning ("[%d] configured gid %d", getpid (), gid);
Dave Wallace543852a2017-08-03 02:11:34 -04001660 }
Dave Wallace8af20542017-10-26 03:29:30 -04001661 else if (unformat (line_input, "segment-baseva 0x%lx",
Dave Wallace543852a2017-08-03 02:11:34 -04001662 &vcl_cfg->segment_baseva))
1663 {
1664 if (VPPCOM_DEBUG > 0)
Dave Wallace8af20542017-10-26 03:29:30 -04001665 clib_warning ("[%d] configured segment_baseva 0x%lx",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001666 getpid (), vcl_cfg->segment_baseva);
Dave Wallace543852a2017-08-03 02:11:34 -04001667 }
1668 else if (unformat (line_input, "segment-size 0x%lx",
1669 &vcl_cfg->segment_size))
1670 {
1671 if (VPPCOM_DEBUG > 0)
1672 clib_warning ("[%d] configured segment_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001673 getpid (), vcl_cfg->segment_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001674 vcl_cfg->segment_size);
1675 }
1676 else if (unformat (line_input, "segment-size %ld",
1677 &vcl_cfg->segment_size))
1678 {
1679 if (VPPCOM_DEBUG > 0)
1680 clib_warning ("[%d] configured segment_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001681 getpid (), vcl_cfg->segment_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001682 vcl_cfg->segment_size);
1683 }
1684 else if (unformat (line_input, "add-segment-size 0x%lx",
1685 &vcl_cfg->add_segment_size))
1686 {
1687 if (VPPCOM_DEBUG > 0)
1688 clib_warning
1689 ("[%d] configured add_segment_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001690 getpid (), vcl_cfg->add_segment_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001691 vcl_cfg->add_segment_size);
1692 }
1693 else if (unformat (line_input, "add-segment-size %ld",
1694 &vcl_cfg->add_segment_size))
1695 {
1696 if (VPPCOM_DEBUG > 0)
1697 clib_warning
1698 ("[%d] configured add_segment_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001699 getpid (), vcl_cfg->add_segment_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001700 vcl_cfg->add_segment_size);
1701 }
1702 else if (unformat (line_input, "preallocated-fifo-pairs %d",
1703 &vcl_cfg->preallocated_fifo_pairs))
1704 {
1705 if (VPPCOM_DEBUG > 0)
1706 clib_warning ("[%d] configured preallocated_fifo_pairs "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001707 "%d (0x%x)", getpid (),
Dave Wallace543852a2017-08-03 02:11:34 -04001708 vcl_cfg->preallocated_fifo_pairs,
1709 vcl_cfg->preallocated_fifo_pairs);
1710 }
1711 else if (unformat (line_input, "rx-fifo-size 0x%lx",
1712 &vcl_cfg->rx_fifo_size))
1713 {
1714 if (VPPCOM_DEBUG > 0)
1715 clib_warning ("[%d] configured rx_fifo_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001716 getpid (), vcl_cfg->rx_fifo_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001717 vcl_cfg->rx_fifo_size);
1718 }
1719 else if (unformat (line_input, "rx-fifo-size %ld",
1720 &vcl_cfg->rx_fifo_size))
1721 {
1722 if (VPPCOM_DEBUG > 0)
1723 clib_warning ("[%d] configured rx_fifo_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001724 getpid (), vcl_cfg->rx_fifo_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001725 vcl_cfg->rx_fifo_size);
1726 }
1727 else if (unformat (line_input, "tx-fifo-size 0x%lx",
1728 &vcl_cfg->tx_fifo_size))
1729 {
1730 if (VPPCOM_DEBUG > 0)
1731 clib_warning ("[%d] configured tx_fifo_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001732 getpid (), vcl_cfg->tx_fifo_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001733 vcl_cfg->tx_fifo_size);
1734 }
1735 else if (unformat (line_input, "tx-fifo-size %ld",
1736 &vcl_cfg->tx_fifo_size))
1737 {
1738 if (VPPCOM_DEBUG > 0)
1739 clib_warning ("[%d] configured tx_fifo_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001740 getpid (), vcl_cfg->tx_fifo_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001741 vcl_cfg->tx_fifo_size);
1742 }
1743 else if (unformat (line_input, "event-queue-size 0x%lx",
1744 &vcl_cfg->event_queue_size))
1745 {
1746 if (VPPCOM_DEBUG > 0)
1747 clib_warning ("[%d] configured event_queue_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001748 getpid (), vcl_cfg->event_queue_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001749 vcl_cfg->event_queue_size);
1750 }
1751 else if (unformat (line_input, "event-queue-size %ld",
1752 &vcl_cfg->event_queue_size))
1753 {
1754 if (VPPCOM_DEBUG > 0)
1755 clib_warning ("[%d] configured event_queue_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001756 getpid (), vcl_cfg->event_queue_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001757 vcl_cfg->event_queue_size);
1758 }
1759 else if (unformat (line_input, "listen-queue-size 0x%lx",
1760 &vcl_cfg->listen_queue_size))
1761 {
1762 if (VPPCOM_DEBUG > 0)
1763 clib_warning ("[%d] configured listen_queue_size 0x%lx (%ld)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001764 getpid (), vcl_cfg->listen_queue_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001765 vcl_cfg->listen_queue_size);
1766 }
1767 else if (unformat (line_input, "listen-queue-size %ld",
1768 &vcl_cfg->listen_queue_size))
1769 {
1770 if (VPPCOM_DEBUG > 0)
1771 clib_warning ("[%d] configured listen_queue_size %ld (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001772 getpid (), vcl_cfg->listen_queue_size,
Dave Wallace543852a2017-08-03 02:11:34 -04001773 vcl_cfg->listen_queue_size);
1774 }
1775 else if (unformat (line_input, "app-timeout %f",
1776 &vcl_cfg->app_timeout))
1777 {
1778 if (VPPCOM_DEBUG > 0)
1779 clib_warning ("[%d] configured app_timeout %f",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001780 getpid (), vcl_cfg->app_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001781 }
1782 else if (unformat (line_input, "session-timeout %f",
1783 &vcl_cfg->session_timeout))
1784 {
1785 if (VPPCOM_DEBUG > 0)
1786 clib_warning ("[%d] configured session_timeout %f",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001787 getpid (), vcl_cfg->session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001788 }
1789 else if (unformat (line_input, "accept-timeout %f",
1790 &vcl_cfg->accept_timeout))
1791 {
1792 if (VPPCOM_DEBUG > 0)
1793 clib_warning ("[%d] configured accept_timeout %f",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001794 getpid (), vcl_cfg->accept_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001795 }
Dave Wallace774169b2017-11-01 20:07:40 -04001796 else if (unformat (line_input, "app-proxy-transport-tcp"))
Dave Wallace8af20542017-10-26 03:29:30 -04001797 {
Dave Wallace774169b2017-11-01 20:07:40 -04001798 vcl_cfg->app_proxy_transport_tcp = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001799 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001800 clib_warning ("[%d] configured app_proxy_transport_tcp (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001801 getpid (), vcl_cfg->app_proxy_transport_tcp);
Dave Wallace8af20542017-10-26 03:29:30 -04001802 }
Dave Wallace774169b2017-11-01 20:07:40 -04001803 else if (unformat (line_input, "app-proxy-transport-udp"))
Dave Wallace8af20542017-10-26 03:29:30 -04001804 {
Dave Wallace774169b2017-11-01 20:07:40 -04001805 vcl_cfg->app_proxy_transport_udp = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001806 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001807 clib_warning ("[%d] configured app_proxy_transport_udp (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001808 getpid (), vcl_cfg->app_proxy_transport_udp);
Dave Wallace8af20542017-10-26 03:29:30 -04001809 }
Dave Wallace774169b2017-11-01 20:07:40 -04001810 else if (unformat (line_input, "app-scope-local"))
Dave Wallace8af20542017-10-26 03:29:30 -04001811 {
Dave Wallace774169b2017-11-01 20:07:40 -04001812 vcl_cfg->app_scope_local = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001813 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001814 clib_warning ("[%d] configured app_scope_local (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001815 getpid (), vcl_cfg->app_scope_local);
Dave Wallace774169b2017-11-01 20:07:40 -04001816 }
1817 else if (unformat (line_input, "app-scope-global"))
1818 {
1819 vcl_cfg->app_scope_global = 1;
1820 if (VPPCOM_DEBUG > 0)
1821 clib_warning ("[%d] configured app_scope_global (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001822 getpid (), vcl_cfg->app_scope_global);
Dave Wallace8af20542017-10-26 03:29:30 -04001823 }
1824 else if (unformat (line_input, "namespace-secret %lu",
1825 &vcl_cfg->namespace_secret))
1826 {
1827 if (VPPCOM_DEBUG > 0)
1828 clib_warning
1829 ("[%d] configured namespace_secret %lu (0x%lx)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001830 getpid (), vcl_cfg->namespace_secret,
Dave Wallace8af20542017-10-26 03:29:30 -04001831 vcl_cfg->namespace_secret);
1832 }
1833 else if (unformat (line_input, "namespace-id %v",
1834 &vcl_cfg->namespace_id))
1835 {
1836 vl_api_application_attach_t *mp;
1837 u32 max_nsid_vec_len = sizeof (mp->namespace_id) - 1;
1838 u32 nsid_vec_len = vec_len (vcl_cfg->namespace_id);
1839 if (nsid_vec_len > max_nsid_vec_len)
1840 {
1841 _vec_len (vcl_cfg->namespace_id) = max_nsid_vec_len;
1842 if (VPPCOM_DEBUG > 0)
1843 clib_warning ("[%d] configured namespace_id is too long,"
Dave Wallace2e005bb2017-11-07 01:21:39 -05001844 " truncated to %d characters!", getpid (),
Dave Wallace8af20542017-10-26 03:29:30 -04001845 max_nsid_vec_len);
1846 }
1847
1848 if (VPPCOM_DEBUG > 0)
1849 clib_warning ("[%d] configured namespace_id %v",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001850 getpid (), vcl_cfg->namespace_id);
Dave Wallace8af20542017-10-26 03:29:30 -04001851 }
Dave Wallace543852a2017-08-03 02:11:34 -04001852 else if (unformat (line_input, "}"))
1853 {
1854 vc_cfg_input = 0;
1855 if (VPPCOM_DEBUG > 0)
1856 clib_warning ("[%d] completed parsing vppcom config!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001857 getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04001858 goto input_done;
1859 }
1860 else
1861 {
1862 if (line_input->buffer[line_input->index] != '#')
1863 {
1864 clib_warning ("[%d] Unknown vppcom config option: '%s'",
Dave Wallace2e005bb2017-11-07 01:21:39 -05001865 getpid (), (char *)
Dave Wallace543852a2017-08-03 02:11:34 -04001866 &line_input->buffer[line_input->index]);
1867 }
1868 }
1869 }
1870 }
1871
1872input_done:
1873 unformat_free (input);
1874
1875file_done:
Chris Lukeab7b8d92017-09-07 07:40:13 -04001876 if (fd >= 0)
Dave Wallace543852a2017-08-03 02:11:34 -04001877 close (fd);
1878}
1879
1880/*
1881 * VPPCOM Public API functions
1882 */
1883int
1884vppcom_app_create (char *app_name)
1885{
Dave Wallace543852a2017-08-03 02:11:34 -04001886 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
1887 u8 *heap;
1888 mheap_t *h;
1889 int rv;
1890
1891 if (!vcm->init)
1892 {
1893 char *conf_fname;
Dave Wallace8af20542017-10-26 03:29:30 -04001894 char *env_var_str;
Dave Wallace543852a2017-08-03 02:11:34 -04001895
1896 vcm->init = 1;
Dave Wallace543852a2017-08-03 02:11:34 -04001897 vppcom_cfg_init (vcl_cfg);
Dave Wallace498b3a52017-11-09 13:00:34 -05001898 env_var_str = getenv (VPPCOM_ENV_DEBUG);
1899 if (env_var_str)
1900 {
1901 u32 tmp;
1902 if (sscanf (env_var_str, "%u", &tmp) != 1)
1903 clib_warning ("[%d] Invalid debug level specified in "
1904 "the environment variable "
1905 VPPCOM_ENV_DEBUG
1906 " (%s)!\n", getpid (), env_var_str);
1907 else
1908 {
1909 vcm->debug = tmp;
1910 clib_warning ("[%d] configured debug level (%u) from "
1911 VPPCOM_ENV_DEBUG "!", getpid (), vcm->debug);
1912 }
1913 }
Dave Wallace8af20542017-10-26 03:29:30 -04001914 conf_fname = getenv (VPPCOM_ENV_CONF);
Dave Wallace543852a2017-08-03 02:11:34 -04001915 if (!conf_fname)
1916 {
1917 conf_fname = VPPCOM_CONF_DEFAULT;
1918 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05001919 clib_warning ("[%d] getenv '%s' failed!", getpid (),
Dave Wallace8af20542017-10-26 03:29:30 -04001920 VPPCOM_ENV_CONF);
Dave Wallace543852a2017-08-03 02:11:34 -04001921 }
1922 vppcom_cfg_heapsize (conf_fname);
Dave Wallace2e005bb2017-11-07 01:21:39 -05001923 clib_fifo_validate (vcm->client_session_index_fifo,
1924 vcm->cfg.listen_queue_size);
Dave Wallace543852a2017-08-03 02:11:34 -04001925 vppcom_cfg_read (conf_fname);
Dave Wallace8af20542017-10-26 03:29:30 -04001926 env_var_str = getenv (VPPCOM_ENV_APP_NAMESPACE_ID);
1927 if (env_var_str)
1928 {
1929 u32 ns_id_vec_len = strlen (env_var_str);
1930
1931 vec_reset_length (vcm->cfg.namespace_id);
1932 vec_validate (vcm->cfg.namespace_id, ns_id_vec_len - 1);
1933 clib_memcpy (vcm->cfg.namespace_id, env_var_str, ns_id_vec_len);
1934
1935 if (VPPCOM_DEBUG > 0)
1936 clib_warning ("[%d] configured namespace_id (%v) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001937 VPPCOM_ENV_APP_NAMESPACE_ID "!", getpid (),
Dave Wallace8af20542017-10-26 03:29:30 -04001938 vcm->cfg.namespace_id);
1939 }
1940 env_var_str = getenv (VPPCOM_ENV_APP_NAMESPACE_SECRET);
1941 if (env_var_str)
1942 {
1943 u64 tmp;
1944 if (sscanf (env_var_str, "%lu", &tmp) != 1)
1945 clib_warning ("[%d] Invalid namespace secret specified in "
1946 "the environment variable "
1947 VPPCOM_ENV_APP_NAMESPACE_SECRET
Dave Wallace2e005bb2017-11-07 01:21:39 -05001948 " (%s)!\n", getpid (), env_var_str);
Dave Wallace8af20542017-10-26 03:29:30 -04001949 else
1950 {
1951 vcm->cfg.namespace_secret = tmp;
1952 if (VPPCOM_DEBUG > 0)
1953 clib_warning ("[%d] configured namespace secret (%lu) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001954 VPPCOM_ENV_APP_NAMESPACE_ID "!", getpid (),
Dave Wallace8af20542017-10-26 03:29:30 -04001955 vcm->cfg.namespace_secret);
1956 }
1957 }
Dave Wallace774169b2017-11-01 20:07:40 -04001958 if (getenv (VPPCOM_ENV_APP_PROXY_TRANSPORT_TCP))
Dave Wallace8af20542017-10-26 03:29:30 -04001959 {
Dave Wallace774169b2017-11-01 20:07:40 -04001960 vcm->cfg.app_proxy_transport_tcp = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001961 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001962 clib_warning ("[%d] configured app_proxy_transport_tcp (%u) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001963 VPPCOM_ENV_APP_PROXY_TRANSPORT_TCP "!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04001964 vcm->cfg.app_proxy_transport_tcp);
Dave Wallace8af20542017-10-26 03:29:30 -04001965 }
Dave Wallace774169b2017-11-01 20:07:40 -04001966 if (getenv (VPPCOM_ENV_APP_PROXY_TRANSPORT_UDP))
Dave Wallace8af20542017-10-26 03:29:30 -04001967 {
Dave Wallace774169b2017-11-01 20:07:40 -04001968 vcm->cfg.app_proxy_transport_udp = 1;
Dave Wallace8af20542017-10-26 03:29:30 -04001969 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04001970 clib_warning ("[%d] configured app_proxy_transport_udp (%u) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001971 VPPCOM_ENV_APP_PROXY_TRANSPORT_UDP "!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04001972 vcm->cfg.app_proxy_transport_udp);
1973 }
1974 if (getenv (VPPCOM_ENV_APP_SCOPE_LOCAL))
1975 {
1976 vcm->cfg.app_scope_local = 1;
1977 if (VPPCOM_DEBUG > 0)
1978 clib_warning ("[%d] configured app_scope_local (%u) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001979 VPPCOM_ENV_APP_SCOPE_LOCAL "!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04001980 vcm->cfg.app_scope_local);
1981 }
1982 if (getenv (VPPCOM_ENV_APP_SCOPE_GLOBAL))
1983 {
1984 vcm->cfg.app_scope_global = 1;
1985 if (VPPCOM_DEBUG > 0)
1986 clib_warning ("[%d] configured app_scope_global (%u) from "
Dave Wallace2e005bb2017-11-07 01:21:39 -05001987 VPPCOM_ENV_APP_SCOPE_GLOBAL "!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04001988 vcm->cfg.app_scope_global);
Dave Wallace8af20542017-10-26 03:29:30 -04001989 }
1990
Dave Wallace543852a2017-08-03 02:11:34 -04001991 vcm->main_cpu = os_get_thread_index ();
1992 heap = clib_mem_get_per_cpu_heap ();
1993 h = mheap_header (heap);
1994
1995 /* make the main heap thread-safe */
1996 h->flags |= MHEAP_FLAG_THREAD_SAFE;
1997
1998 vcm->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
1999
2000 clib_time_init (&vcm->clib_time);
2001 vppcom_init_error_string_table ();
2002 svm_fifo_segment_init (vcl_cfg->segment_baseva,
2003 20 /* timeout in secs */ );
2004 clib_spinlock_init (&vcm->sessions_lockp);
2005 vppcom_api_hookup ();
2006 }
2007
2008 if (vcm->my_client_index == ~0)
2009 {
2010 vcm->app_state = STATE_APP_START;
2011 rv = vppcom_connect_to_vpp (app_name);
2012 if (rv)
2013 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002014 clib_warning ("[%d] ERROR: couldn't connect to VPP!", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04002015 return rv;
2016 }
2017
2018 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002019 clib_warning ("[%d] sending session enable", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04002020
2021 rv = vppcom_app_session_enable ();
2022 if (rv)
2023 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002024 clib_warning ("[%d] ERROR: vppcom_app_session_enable() failed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002025 getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04002026 return rv;
2027 }
2028
2029 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05002030 clib_warning ("[%d] sending app attach", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04002031
2032 rv = vppcom_app_attach ();
2033 if (rv)
2034 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002035 clib_warning ("[%d] ERROR: vppcom_app_attach() failed!", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -04002036 return rv;
2037 }
Dave Wallace543852a2017-08-03 02:11:34 -04002038
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002039 if (VPPCOM_DEBUG > 0)
2040 clib_warning ("[%d] app_name '%s', my_client_index %d (0x%x)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002041 getpid (), app_name, vcm->my_client_index,
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002042 vcm->my_client_index);
2043 }
Dave Wallace543852a2017-08-03 02:11:34 -04002044
2045 return VPPCOM_OK;
2046}
2047
2048void
2049vppcom_app_destroy (void)
2050{
Dave Wallace543852a2017-08-03 02:11:34 -04002051 int rv;
2052
2053 if (vcm->my_client_index == ~0)
2054 return;
2055
2056 if (VPPCOM_DEBUG > 0)
2057 clib_warning ("[%d] detaching from VPP, my_client_index %d (0x%x)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002058 getpid (), vcm->my_client_index, vcm->my_client_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002059
2060 vppcom_app_detach ();
2061 rv = vppcom_wait_for_app_state_change (STATE_APP_ENABLED);
2062 if (PREDICT_FALSE (rv))
2063 {
2064 if (VPPCOM_DEBUG > 0)
2065 clib_warning ("[%d] application detach timed out, rv = %s (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002066 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -04002067 }
2068 vl_client_disconnect_from_vlib ();
2069 vcm->my_client_index = ~0;
2070 vcm->app_state = STATE_APP_START;
2071}
2072
2073int
2074vppcom_session_create (u32 vrf, u8 proto, u8 is_nonblocking)
2075{
Dave Wallace543852a2017-08-03 02:11:34 -04002076 session_t *session;
2077 u32 session_index;
2078
2079 clib_spinlock_lock (&vcm->sessions_lockp);
2080 pool_get (vcm->sessions, session);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002081 memset (session, 0, sizeof (*session));
Dave Wallace543852a2017-08-03 02:11:34 -04002082 session_index = session - vcm->sessions;
2083
2084 session->vrf = vrf;
2085 session->proto = proto;
2086 session->state = STATE_START;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002087 session->is_nonblocking = is_nonblocking ? 1 : 0;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002088 session->vpp_handle = ~0;
Dave Wallace543852a2017-08-03 02:11:34 -04002089 clib_spinlock_unlock (&vcm->sessions_lockp);
2090
2091 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002092 clib_warning ("[%d] sid %u", getpid (), session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002093
2094 return (int) session_index;
2095}
2096
2097int
2098vppcom_session_close (uint32_t session_index)
2099{
Dave Wallace543852a2017-08-03 02:11:34 -04002100 session_t *session = 0;
2101 int rv;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002102 u8 is_listen;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002103 u8 is_vep;
2104 u8 is_vep_session;
2105 u32 next_sid;
2106 u32 vep_idx;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002107 uword *p;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002108 session_state_t state;
Dave Wallace543852a2017-08-03 02:11:34 -04002109
Dave Wallace4878cbe2017-11-21 03:45:09 -05002110 VCL_LOCK_AND_GET_SESSION (session_index, &session);
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002111 is_listen = session->is_listen;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002112 is_vep = session->is_vep;
2113 is_vep_session = session->is_vep_session;
2114 next_sid = session->vep.next_sid;
2115 vep_idx = session->vep.vep_idx;
2116 state = session->state;
Dave Wallace543852a2017-08-03 02:11:34 -04002117 clib_spinlock_unlock (&vcm->sessions_lockp);
2118
2119 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002120 clib_warning ("[%d] sid %d: closing session...", getpid (),
2121 session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002122
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002123 if (is_vep)
Dave Wallace543852a2017-08-03 02:11:34 -04002124 {
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002125 while (next_sid != ~0)
Dave Wallace19481612017-09-15 18:47:44 -04002126 {
Dave Wallacef7f809c2017-10-03 01:48:42 -04002127 rv = vppcom_epoll_ctl (session_index, EPOLL_CTL_DEL, next_sid, 0);
Dave Wallace19481612017-09-15 18:47:44 -04002128 if ((VPPCOM_DEBUG > 0) && (rv < 0))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002129 clib_warning ("[%d] sid %u: EPOLL_CTL_DEL vep_idx %u failed, "
2130 "rv = %d (%s)", getpid (), next_sid, vep_idx,
2131 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04002132
Dave Wallace4878cbe2017-11-21 03:45:09 -05002133 VCL_LOCK_AND_GET_SESSION (session_index, &session);
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002134 next_sid = session->vep.next_sid;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002135 clib_spinlock_unlock (&vcm->sessions_lockp);
2136 }
2137 }
2138 else
2139 {
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002140 if (is_vep_session)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002141 {
Dave Wallacef7f809c2017-10-03 01:48:42 -04002142 rv = vppcom_epoll_ctl (vep_idx, EPOLL_CTL_DEL, session_index, 0);
2143 if ((VPPCOM_DEBUG > 0) && (rv < 0))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002144 clib_warning ("[%d] sid %u: EPOLL_CTL_DEL vep_idx %u failed! "
2145 "rv = %d (%s)", getpid (), session_index, vep_idx,
2146 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04002147 }
2148
Dave Wallace4878cbe2017-11-21 03:45:09 -05002149 if (is_listen)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002150 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002151 if (state == STATE_LISTEN)
2152 {
2153 rv = vppcom_session_unbind (session_index);
2154 if (PREDICT_FALSE (rv < 0))
2155 {
2156 if (VPPCOM_DEBUG > 0)
2157 clib_warning ("[%d] sid %u: listener unbind failed! "
2158 "rv = %d (%s)",
2159 getpid (), session_index, rv,
2160 vppcom_retval_str (rv));
2161 }
2162 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002163 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002164
2165 else if (state & (CLIENT_STATE_OPEN | SERVER_STATE_OPEN))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002166 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002167 rv = vppcom_session_disconnect (session_index);
2168 if (PREDICT_FALSE (rv < 0))
2169 clib_warning ("[%d] ERROR: sid %u: session disconnect failed! "
2170 "rv %d (%s)", getpid (), session_index, rv,
2171 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04002172 }
Dave Wallace19481612017-09-15 18:47:44 -04002173 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002174
2175 VCL_LOCK_AND_GET_SESSION (session_index, &session);
2176
2177 if (session->vpp_handle != ~0)
2178 {
2179 p = hash_get (vcm->session_index_by_vpp_handles, session->vpp_handle);
2180 if (p)
2181 hash_unset (vcm->session_index_by_vpp_handles, session->vpp_handle);
2182 }
Dave Wallace543852a2017-08-03 02:11:34 -04002183 pool_put_index (vcm->sessions, session_index);
Dave Wallace66cf6eb2017-10-26 02:51:07 -04002184 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002185
2186 if (VPPCOM_DEBUG > 0)
2187 clib_warning ("[%d] sid %u: session removed.", getpid (), session_index);
2188
Dave Wallacef7f809c2017-10-03 01:48:42 -04002189done:
Dave Wallace543852a2017-08-03 02:11:34 -04002190 return rv;
2191}
2192
2193int
2194vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep)
2195{
Dave Wallace543852a2017-08-03 02:11:34 -04002196 session_t *session = 0;
2197 int rv;
2198
2199 if (!ep || !ep->ip)
2200 return VPPCOM_EINVAL;
2201
Dave Wallace4878cbe2017-11-21 03:45:09 -05002202 VCL_LOCK_AND_GET_SESSION (session_index, &session);
Dave Wallace543852a2017-08-03 02:11:34 -04002203
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002204 if (session->is_vep)
2205 {
2206 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002207 clib_warning ("[%d] ERROR: sid %u: cannot bind to an epoll session!",
2208 getpid (), session_index);
2209 rv = VPPCOM_EBADFD;
2210 goto done;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002211 }
2212
Dave Wallace543852a2017-08-03 02:11:34 -04002213 session->vrf = ep->vrf;
Dave Wallace35830af2017-10-09 01:43:42 -04002214 session->lcl_addr.is_ip4 = ep->is_ip4;
2215 session->lcl_addr.ip46 = to_ip46 (!ep->is_ip4, ep->ip);
Stevenac1f96d2017-10-24 16:03:58 -07002216 session->lcl_port = ep->port;
2217
2218 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002219 clib_warning ("[%d] sid %u: bound to local address %U "
2220 "port %u, proto %s",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002221 getpid (), session_index, format_ip46_address,
Stevenac1f96d2017-10-24 16:03:58 -07002222 &session->lcl_addr.ip46, session->lcl_addr.is_ip4,
Dave Wallace4878cbe2017-11-21 03:45:09 -05002223 clib_net_to_host_u16 (session->lcl_port),
2224 session->proto ? "UDP" : "TCP");
Dave Wallace543852a2017-08-03 02:11:34 -04002225
2226 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002227done:
2228 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002229}
2230
2231int
Dave Wallace33e002b2017-09-06 01:20:02 -04002232vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len)
Dave Wallace543852a2017-08-03 02:11:34 -04002233{
Dave Wallace33e002b2017-09-06 01:20:02 -04002234 session_t *listen_session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04002235 int rv;
2236
Dave Wallace4878cbe2017-11-21 03:45:09 -05002237 VCL_LOCK_AND_GET_SESSION (listen_session_index, &listen_session);
Dave Wallace543852a2017-08-03 02:11:34 -04002238
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002239 if (listen_session->is_vep)
2240 {
2241 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002242 clib_warning ("[%d] ERROR: sid %u: cannot listen on an "
2243 "epoll session!", getpid (), listen_session_index);
2244 rv = VPPCOM_EBADFD;
2245 goto done;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002246 }
2247
Dave Wallacee695cb42017-11-02 22:04:42 -04002248 if (listen_session->is_listen)
2249 {
2250 clib_spinlock_unlock (&vcm->sessions_lockp);
2251 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002252 clib_warning ("[%d] sid %u: already in listen state!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002253 getpid (), listen_session_index);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002254 rv = VPPCOM_OK;
2255 goto done;
Dave Wallacee695cb42017-11-02 22:04:42 -04002256 }
2257
Dave Wallace543852a2017-08-03 02:11:34 -04002258 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002259 clib_warning ("[%d] sid %u: sending bind request...",
2260 getpid (), listen_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002261
Dave Wallace4878cbe2017-11-21 03:45:09 -05002262 vppcom_send_bind_sock (listen_session, listen_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04002263 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace33e002b2017-09-06 01:20:02 -04002264 rv =
2265 vppcom_wait_for_session_state_change (listen_session_index, STATE_LISTEN,
2266 vcm->cfg.session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04002267 if (PREDICT_FALSE (rv))
2268 {
Dave Wallace543852a2017-08-03 02:11:34 -04002269 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002270 clib_warning ("[%d] sid %u: bind failed! returning %d (%d)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002271 getpid (), vppcom_retval_str (rv), rv);
Dave Wallace543852a2017-08-03 02:11:34 -04002272 return rv;
2273 }
2274
Dave Wallace4878cbe2017-11-21 03:45:09 -05002275 VCL_LOCK_AND_GET_SESSION (listen_session_index, &listen_session);
Dave Wallace543852a2017-08-03 02:11:34 -04002276 clib_fifo_validate (vcm->client_session_index_fifo, q_len);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002277 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002278done:
2279 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002280}
2281
2282int
2283vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep,
Dave Wallace227867f2017-11-13 21:21:53 -05002284 uint32_t flags, double wait_for_time)
Dave Wallace543852a2017-08-03 02:11:34 -04002285{
Dave Wallace33e002b2017-09-06 01:20:02 -04002286 session_t *listen_session = 0;
2287 session_t *client_session = 0;
Dave Wallace227867f2017-11-13 21:21:53 -05002288 u32 client_session_index = ~0;
Dave Wallace543852a2017-08-03 02:11:34 -04002289 int rv;
2290 f64 wait_for;
Dave Wallace60caa062017-11-10 17:07:13 -05002291 char *cut_thru_str;
Dave Wallace543852a2017-08-03 02:11:34 -04002292
Dave Wallace4878cbe2017-11-21 03:45:09 -05002293 VCL_LOCK_AND_GET_SESSION (listen_session_index, &listen_session);
Dave Wallace543852a2017-08-03 02:11:34 -04002294
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002295 if (listen_session->is_vep)
2296 {
2297 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002298 clib_warning ("[%d] ERROR: sid %u: cannot accept on an "
2299 "epoll session!", getpid (), listen_session_index);
2300 rv = VPPCOM_EBADFD;
2301 goto done;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002302 }
2303
Dave Wallace33e002b2017-09-06 01:20:02 -04002304 if (listen_session->state != STATE_LISTEN)
Dave Wallace543852a2017-08-03 02:11:34 -04002305 {
2306 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002307 clib_warning ("[%d] ERROR: sid %u: not in listen state! "
2308 "state 0x%x (%s)", getpid (), listen_session->state,
2309 vppcom_session_state_str (listen_session->state));
2310 rv = VPPCOM_EBADFD;
2311 goto done;
Dave Wallace543852a2017-08-03 02:11:34 -04002312 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002313 wait_for = ((listen_session->is_nonblocking) ? 0 :
2314 (wait_for_time < 0) ? vcm->cfg.accept_timeout : wait_for_time);
Dave Wallace543852a2017-08-03 02:11:34 -04002315
Dave Wallace543852a2017-08-03 02:11:34 -04002316 clib_spinlock_unlock (&vcm->sessions_lockp);
2317
2318 while (1)
2319 {
2320 rv = vppcom_wait_for_client_session_index (wait_for);
2321 if (rv)
2322 {
2323 if ((VPPCOM_DEBUG > 0))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002324 clib_warning ("[%d] sid %u: accept failed! "
2325 "returning = %d (%s)",
Dave Wallace2e005bb2017-11-07 01:21:39 -05002326 getpid (), listen_session_index,
Dave Wallace4878cbe2017-11-21 03:45:09 -05002327 rv, vppcom_retval_str (rv));
Dave Wallace543852a2017-08-03 02:11:34 -04002328 if ((wait_for == 0) || (wait_for_time > 0))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002329 goto done;
Dave Wallace543852a2017-08-03 02:11:34 -04002330 }
2331 else
2332 break;
2333 }
2334
Dave Wallace543852a2017-08-03 02:11:34 -04002335 clib_spinlock_lock (&vcm->sessions_lockp);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002336 clib_fifo_sub1 (vcm->client_session_index_fifo, client_session_index);
Dave Wallace33e002b2017-09-06 01:20:02 -04002337 rv = vppcom_session_at_index (client_session_index, &client_session);
Dave Wallace543852a2017-08-03 02:11:34 -04002338 ASSERT (rv == VPPCOM_OK);
Dave Wallace35830af2017-10-09 01:43:42 -04002339 ASSERT (client_session->peer_addr.is_ip4 ==
2340 listen_session->lcl_addr.is_ip4);
Dave Wallace543852a2017-08-03 02:11:34 -04002341
Dave Wallace227867f2017-11-13 21:21:53 -05002342 client_session->is_nonblocking = (flags & O_NONBLOCK) ? 1 : 0;
Dave Wallace543852a2017-08-03 02:11:34 -04002343 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002344 clib_warning ("[%d] sid %u: Got a client request! flags %d, "
2345 "is_nonblocking %u", getpid (), client_session_index,
Dave Wallace227867f2017-11-13 21:21:53 -05002346 flags, client_session->is_nonblocking);
Dave Wallace543852a2017-08-03 02:11:34 -04002347
Dave Wallace33e002b2017-09-06 01:20:02 -04002348 ep->vrf = client_session->vrf;
2349 ep->is_cut_thru = client_session->is_cut_thru;
Dave Wallace35830af2017-10-09 01:43:42 -04002350 ep->is_ip4 = client_session->peer_addr.is_ip4;
Stevenac1f96d2017-10-24 16:03:58 -07002351 ep->port = client_session->peer_port;
Dave Wallace35830af2017-10-09 01:43:42 -04002352 if (client_session->peer_addr.is_ip4)
2353 clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip4,
2354 sizeof (ip4_address_t));
Dave Wallace33e002b2017-09-06 01:20:02 -04002355 else
Dave Wallace35830af2017-10-09 01:43:42 -04002356 clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip6,
2357 sizeof (ip6_address_t));
Dave Wallace60caa062017-11-10 17:07:13 -05002358
2359 if (client_session->is_server && client_session->is_cut_thru)
2360 {
2361 static svm_fifo_segment_create_args_t _a;
2362 svm_fifo_segment_create_args_t *a = &_a;
2363 svm_fifo_segment_private_t *seg;
2364
Dave Wallace4878cbe2017-11-21 03:45:09 -05002365 cut_thru_str = " cut-thru ";
Dave Wallace60caa062017-11-10 17:07:13 -05002366
2367 /* Create the segment */
2368 memset (a, 0, sizeof (*a));
2369 a->segment_name = (char *)
2370 format ((u8 *) a->segment_name, "%d:segment%d%c",
2371 getpid (), vcm->unique_segment_index++, 0);
2372 a->segment_size = vcm->cfg.segment_size;
2373 a->preallocated_fifo_pairs = vcm->cfg.preallocated_fifo_pairs;
2374 a->rx_fifo_size = vcm->cfg.rx_fifo_size;
2375 a->tx_fifo_size = vcm->cfg.tx_fifo_size;
2376
2377 rv = svm_fifo_segment_create (a);
2378 if (PREDICT_FALSE (rv))
2379 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002380 clib_warning ("[%d] ERROR: sid %u: "
2381 "svm_fifo_segment_create ('%s') failed! rv %d",
2382 getpid (), client_session_index, a->segment_name, rv);
Dave Wallace60caa062017-11-10 17:07:13 -05002383 vec_reset_length (a->new_segment_indices);
2384 rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
Dave Wallace227867f2017-11-13 21:21:53 -05002385 vppcom_send_connect_session_reply (client_session, rv);
Dave Wallace60caa062017-11-10 17:07:13 -05002386 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002387 rv = VPPCOM_ENOMEM;
2388 goto done;
Dave Wallace60caa062017-11-10 17:07:13 -05002389 }
2390
2391 client_session->segment_name = vec_dup ((u8 *) a->segment_name);
2392 client_session->sm_seg_index = a->new_segment_indices[0];
2393 vec_free (a->new_segment_indices);
2394
2395 seg = svm_fifo_segment_get_segment (client_session->sm_seg_index);
2396 client_session->server_rx_fifo =
2397 svm_fifo_segment_alloc_fifo (seg, vcm->cfg.rx_fifo_size,
2398 FIFO_SEGMENT_RX_FREELIST);
2399 if (PREDICT_FALSE (!client_session->server_rx_fifo))
2400 {
2401 svm_fifo_segment_delete (seg);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002402 clib_warning ("[%d] ERROR: sid %u: rx fifo alloc failed! "
2403 "size %ld (0x%lx)", getpid (),
2404 client_session_index,
2405 vcm->cfg.rx_fifo_size, vcm->cfg.rx_fifo_size);
Dave Wallace60caa062017-11-10 17:07:13 -05002406 rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
Dave Wallace227867f2017-11-13 21:21:53 -05002407 vppcom_send_connect_session_reply (client_session, rv);
Dave Wallace60caa062017-11-10 17:07:13 -05002408 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002409 rv = VPPCOM_ENOMEM;
2410 goto done;
Dave Wallace60caa062017-11-10 17:07:13 -05002411 }
2412 client_session->server_rx_fifo->master_session_index =
2413 client_session_index;
2414
2415 client_session->server_tx_fifo =
2416 svm_fifo_segment_alloc_fifo (seg, vcm->cfg.tx_fifo_size,
2417 FIFO_SEGMENT_TX_FREELIST);
2418 if (PREDICT_FALSE (!client_session->server_tx_fifo))
2419 {
2420 svm_fifo_segment_delete (seg);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002421 clib_warning ("[%d] ERROR: sid %u: tx fifo alloc failed! "
2422 "size %ld (0x%lx)",
2423 getpid (), client_session_index,
2424 vcm->cfg.tx_fifo_size, vcm->cfg.tx_fifo_size);
Dave Wallace60caa062017-11-10 17:07:13 -05002425 rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
Dave Wallace227867f2017-11-13 21:21:53 -05002426 vppcom_send_connect_session_reply (client_session, rv);
Dave Wallace60caa062017-11-10 17:07:13 -05002427 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002428 rv = VPPCOM_ENOMEM;
2429 goto done;
Dave Wallace60caa062017-11-10 17:07:13 -05002430 }
2431 client_session->server_tx_fifo->master_session_index =
2432 client_session_index;
2433
2434 if (VPPCOM_DEBUG > 1)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002435 clib_warning ("[%d] sid %u: created segment '%s', "
2436 "rx_fifo %p, tx_fifo %p",
2437 getpid (), client_session_index,
2438 client_session->segment_name,
Dave Wallace60caa062017-11-10 17:07:13 -05002439 client_session->server_rx_fifo,
2440 client_session->server_tx_fifo);
2441
2442#ifdef CUT_THRU_EVENT_QUEUE /* TBD */
2443 {
2444 void *oldheap;
2445 ssvm_shared_header_t *sh = seg->ssvm.sh;
2446
2447 ssvm_lock_non_recursive (sh, 1);
2448 oldheap = ssvm_push_heap (sh);
2449 event_q = client_session->vpp_event_queue =
2450 unix_shared_memory_queue_init (vcm->cfg.event_queue_size,
2451 sizeof (session_fifo_event_t),
2452 getpid (), 0 /* signal not sent */ );
2453 ssvm_pop_heap (oldheap);
2454 ssvm_unlock_non_recursive (sh);
2455 }
2456#endif
Dave Wallace227867f2017-11-13 21:21:53 -05002457 vppcom_send_connect_session_reply (client_session, 0);
Dave Wallace60caa062017-11-10 17:07:13 -05002458 }
2459 else
2460 {
2461 cut_thru_str = " ";
Florin Corasdcf55ce2017-11-16 15:32:50 -08002462 vppcom_send_accept_session_reply (client_session->vpp_handle, 0);
Dave Wallace60caa062017-11-10 17:07:13 -05002463 }
2464
Stevenac1f96d2017-10-24 16:03:58 -07002465 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002466 clib_warning ("[%d] sid %u: accepted%sconnection to local %s address "
2467 "%U port %u",
Dave Wallace60caa062017-11-10 17:07:13 -05002468 getpid (), client_session_index, cut_thru_str,
Dave Wallace4878cbe2017-11-21 03:45:09 -05002469 client_session->lcl_addr.is_ip4 ? "IPv4" : "IPv6",
2470 format_ip46_address, &client_session->lcl_addr.ip46,
2471 client_session->lcl_addr.is_ip4,
2472 clib_net_to_host_u16 (client_session->lcl_port));
Dave Wallace60caa062017-11-10 17:07:13 -05002473
Dave Wallace543852a2017-08-03 02:11:34 -04002474 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002475 rv = (int) client_session_index;
2476done:
2477 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002478}
2479
2480int
2481vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep)
2482{
Dave Wallace543852a2017-08-03 02:11:34 -04002483 session_t *session = 0;
2484 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002485
Dave Wallace4878cbe2017-11-21 03:45:09 -05002486 VCL_LOCK_AND_GET_SESSION (session_index, &session);
2487
2488 if (PREDICT_FALSE (session->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04002489 {
2490 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002491 clib_warning ("[%d] ERROR: sid %u: cannot connect on an epoll session!",
2492 getpid (), session_index);
2493 rv = VPPCOM_EBADFD;
2494 goto done;
Dave Wallace543852a2017-08-03 02:11:34 -04002495 }
2496
Dave Wallace4878cbe2017-11-21 03:45:09 -05002497 if (PREDICT_FALSE (session->is_server))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002498 {
2499 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002500 clib_warning ("[%d] ERROR: sid %u: is in use as a server session!",
2501 getpid (), session_index);
2502 rv = VPPCOM_EBADFD;
2503 goto done;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002504 }
2505
Dave Wallace4878cbe2017-11-21 03:45:09 -05002506 if (PREDICT_FALSE (session->state & CLIENT_STATE_OPEN))
Dave Wallace543852a2017-08-03 02:11:34 -04002507 {
Dave Wallace543852a2017-08-03 02:11:34 -04002508 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002509 clib_warning ("[%d] sid %u: session already connected to "
2510 "%s %U port %d proto %s, state 0x%x (%s)",
2511 getpid (), session_index,
2512 session->peer_addr.is_ip4 ? "IPv4" : "IPv6",
2513 format_ip46_address,
2514 &session->peer_addr.ip46, session->peer_addr.is_ip4,
2515 clib_net_to_host_u16 (session->peer_port),
2516 session->proto ? "UDP" : "TCP", session->state,
2517 vppcom_session_state_str (session->state));
2518
2519 clib_spinlock_unlock (&vcm->sessions_lockp);
2520 rv = VPPCOM_OK;
2521 goto done;
Dave Wallace543852a2017-08-03 02:11:34 -04002522 }
2523
2524 session->vrf = server_ep->vrf;
Dave Wallace35830af2017-10-09 01:43:42 -04002525 session->peer_addr.is_ip4 = server_ep->is_ip4;
2526 session->peer_addr.ip46 = to_ip46 (!server_ep->is_ip4, server_ep->ip);
Stevenac1f96d2017-10-24 16:03:58 -07002527 session->peer_port = server_ep->port;
Dave Wallace543852a2017-08-03 02:11:34 -04002528
2529 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002530 clib_warning ("[%d] sid %u: connecting to server %s %U port %d proto %s",
2531 getpid (), session_index,
2532 session->peer_addr.is_ip4 ? "IPv4" : "IPv6",
2533 format_ip46_address,
2534 &session->peer_addr.ip46, session->peer_addr.is_ip4,
2535 clib_net_to_host_u16 (session->peer_port),
2536 session->proto ? "UDP" : "TCP");
Dave Wallace543852a2017-08-03 02:11:34 -04002537
2538 vppcom_send_connect_sock (session, session_index);
2539 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002540
Dave Wallace543852a2017-08-03 02:11:34 -04002541 rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
2542 vcm->cfg.session_timeout);
2543 if (PREDICT_FALSE (rv))
2544 {
2545 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002546 clib_warning ("[%d] sid %u: connect failed! returning %d (%s)",
2547 getpid (), session_index, rv, vppcom_retval_str (rv));
Dave Wallace543852a2017-08-03 02:11:34 -04002548 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002549 else if (VPPCOM_DEBUG > 0)
2550 clib_warning ("[%d] sid %d: connected!", getpid (), session_index);
Dave Wallace7876d392017-10-19 03:53:57 -04002551
Dave Wallace4878cbe2017-11-21 03:45:09 -05002552done:
2553 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002554}
2555
Steven58f464e2017-10-25 12:33:12 -07002556static inline int
2557vppcom_session_read_internal (uint32_t session_index, void *buf, int n,
2558 u8 peek)
Dave Wallace543852a2017-08-03 02:11:34 -04002559{
Dave Wallace543852a2017-08-03 02:11:34 -04002560 session_t *session = 0;
2561 svm_fifo_t *rx_fifo;
2562 int n_read = 0;
2563 int rv;
2564 char *fifo_str;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002565 u32 poll_et;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002566 session_state_t state;
2567 u8 is_server;
2568 u8 is_nonblocking;
Dave Wallace543852a2017-08-03 02:11:34 -04002569
2570 ASSERT (buf);
2571
Dave Wallace4878cbe2017-11-21 03:45:09 -05002572 VCL_LOCK_AND_GET_SESSION (session_index, &session);
2573
2574 if (PREDICT_FALSE (session->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04002575 {
2576 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002577 clib_warning ("[%d] ERROR: sid %u: cannot read from an epoll session!",
2578 getpid (), session_index);
2579 rv = VPPCOM_EBADFD;
2580 goto done;
Dave Wallace543852a2017-08-03 02:11:34 -04002581 }
2582
Dave Wallace4878cbe2017-11-21 03:45:09 -05002583 is_server = session->is_server;
2584 is_nonblocking = session->is_nonblocking;
2585 state = session->state;
2586 if (PREDICT_FALSE (!(state & (SERVER_STATE_OPEN | CLIENT_STATE_OPEN))))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002587 {
2588 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002589 rv = ((state == STATE_DISCONNECT) ?
2590 VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
2591
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002592 if (VPPCOM_DEBUG > 0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002593 clib_warning ("[%d] sid %u: %s session is not open! "
2594 "state 0x%x (%s), returning %d (%s)",
2595 getpid (), session_index, is_server ?
2596 "server" : "client", state,
2597 vppcom_session_state_str (state),
2598 rv, vppcom_retval_str (rv));
2599 goto done;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002600 }
2601
Dave Wallace4878cbe2017-11-21 03:45:09 -05002602 rx_fifo = ((!session->is_cut_thru || is_server) ?
Dave Wallace33e002b2017-09-06 01:20:02 -04002603 session->server_rx_fifo : session->server_tx_fifo);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002604 fifo_str = ((!session->is_cut_thru || is_server) ?
Dave Wallace33e002b2017-09-06 01:20:02 -04002605 "server_rx_fifo" : "server_tx_fifo");
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002606 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002607
2608 do
2609 {
Steven58f464e2017-10-25 12:33:12 -07002610 if (peek)
2611 n_read = svm_fifo_peek (rx_fifo, 0, n, buf);
2612 else
2613 n_read = svm_fifo_dequeue_nowait (rx_fifo, n, buf);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002614 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002615 while (!is_nonblocking && (n_read <= 0));
Dave Wallacef7f809c2017-10-03 01:48:42 -04002616
Dave Wallace4878cbe2017-11-21 03:45:09 -05002617 if (n_read <= 0)
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002618 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002619 VCL_LOCK_AND_GET_SESSION (session_index, &session);
2620
2621 poll_et = (((EPOLLET | EPOLLIN) & session->vep.ev.events) ==
2622 (EPOLLET | EPOLLIN));
2623 if (poll_et)
2624 session->vep.et_mask |= EPOLLIN;
2625
2626 if (state == STATE_CLOSE_ON_EMPTY)
2627 {
2628 session_state_t new_state = STATE_DISCONNECT;
2629 rv = VPPCOM_ECONNRESET;
2630
2631 if (VPPCOM_DEBUG > 1)
2632 {
2633 clib_warning ("[%d] sid %u: Empty fifo with %s session "
2634 "state 0x%x (%s)!\n"
2635 " Setting state to %d (%s), returning %d (%s)",
2636 getpid (), session_index,
2637 is_server ? "server" : "client",
2638 state, vppcom_session_state_str (state),
2639 new_state, vppcom_session_state_str (new_state),
2640 rv, vppcom_retval_str (rv));
2641 }
2642
2643 session->state = new_state;
2644 }
2645 else
2646 rv = VPPCOM_EAGAIN;
2647
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002648 clib_spinlock_unlock (&vcm->sessions_lockp);
2649 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002650 else
2651 rv = n_read;
Dave Wallace543852a2017-08-03 02:11:34 -04002652
Dave Wallace4878cbe2017-11-21 03:45:09 -05002653 if (VPPCOM_DEBUG > 2)
2654 {
2655 if (rv > 0)
2656 clib_warning ("[%d] sid %u: read %d bytes from %s (%p)", getpid (),
2657 session_index, n_read, fifo_str, rx_fifo);
2658 else
2659 clib_warning ("[%d] sid %u: nothing read, returning %d (%s)",
2660 getpid (), session_index, rv, vppcom_retval_str (rv));
2661 }
2662done:
2663 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002664}
2665
Steven58f464e2017-10-25 12:33:12 -07002666int
2667vppcom_session_read (uint32_t session_index, void *buf, int n)
2668{
2669 return (vppcom_session_read_internal (session_index, buf, n, 0));
2670}
2671
2672static int
2673vppcom_session_peek (uint32_t session_index, void *buf, int n)
2674{
2675 return (vppcom_session_read_internal (session_index, buf, n, 1));
2676}
2677
Dave Wallace543852a2017-08-03 02:11:34 -04002678static inline int
2679vppcom_session_read_ready (session_t * session, u32 session_index)
2680{
Dave Wallace498b3a52017-11-09 13:00:34 -05002681 svm_fifo_t *rx_fifo = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04002682 int ready = 0;
Dave Wallace60caa062017-11-10 17:07:13 -05002683 u32 poll_et;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002684 int rv;
2685 u8 is_server = session->is_server;
2686 session_state_t state = session->state;
Dave Wallace543852a2017-08-03 02:11:34 -04002687
2688 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05002689 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002690 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002691 clib_warning ("[%d] ERROR: sid %u: cannot read from an "
2692 "epoll session!", getpid (), session_index);
2693 rv = VPPCOM_EBADFD;
2694 goto done;
Dave Wallace543852a2017-08-03 02:11:34 -04002695 }
Dave Wallace33e002b2017-09-06 01:20:02 -04002696
2697 if (session->is_listen)
Dave Wallace543852a2017-08-03 02:11:34 -04002698 ready = clib_fifo_elts (vcm->client_session_index_fifo);
2699 else
2700 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002701 if (!(state & (SERVER_STATE_OPEN | CLIENT_STATE_OPEN | STATE_LISTEN)))
2702 {
2703 rv = ((state == STATE_DISCONNECT) ? VPPCOM_ECONNRESET :
2704 VPPCOM_ENOTCONN);
2705
2706 if (VPPCOM_DEBUG > 1)
2707 clib_warning ("[%d] sid %u: %s session is not open! "
2708 "state 0x%x (%s), returning %d (%s)", getpid (),
2709 session_index, is_server ? "server" : "client",
2710 state, vppcom_session_state_str (state),
2711 rv, vppcom_retval_str (rv));
2712 goto done;
2713 }
2714
2715 rx_fifo = ((!session->is_cut_thru || is_server) ?
Dave Wallace33e002b2017-09-06 01:20:02 -04002716 session->server_rx_fifo : session->server_tx_fifo);
Dave Wallace543852a2017-08-03 02:11:34 -04002717
Dave Wallace33e002b2017-09-06 01:20:02 -04002718 ready = svm_fifo_max_dequeue (rx_fifo);
Dave Wallace543852a2017-08-03 02:11:34 -04002719 }
2720
Dave Wallace4878cbe2017-11-21 03:45:09 -05002721 if (ready == 0)
Dave Wallace60caa062017-11-10 17:07:13 -05002722 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002723 poll_et =
2724 ((EPOLLET | EPOLLIN) & session->vep.ev.events) == (EPOLLET | EPOLLIN);
2725 if (poll_et)
2726 session->vep.et_mask |= EPOLLIN;
Dave Wallace60caa062017-11-10 17:07:13 -05002727
Dave Wallace4878cbe2017-11-21 03:45:09 -05002728 if (state == STATE_CLOSE_ON_EMPTY)
2729 {
2730 rv = VPPCOM_ECONNRESET;
2731 session_state_t new_state = STATE_DISCONNECT;
2732
2733 if (VPPCOM_DEBUG > 1)
2734 {
2735 clib_warning ("[%d] sid %u: Empty fifo with %s session "
2736 "state 0x%x (%s)!\n"
2737 " Setting state to %d (%s), returning %d (%s)",
2738 getpid (), session_index,
2739 is_server ? "server" : "client",
2740 state, vppcom_session_state_str (state),
2741 new_state, vppcom_session_state_str (new_state),
2742 rv, vppcom_retval_str (rv));
2743 }
2744 session->state = new_state;
2745 goto done;
2746 }
2747 }
2748 rv = ready;
2749done:
2750 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002751}
2752
2753int
2754vppcom_session_write (uint32_t session_index, void *buf, int n)
2755{
Dave Wallace543852a2017-08-03 02:11:34 -04002756 session_t *session = 0;
2757 svm_fifo_t *tx_fifo;
2758 unix_shared_memory_queue_t *q;
2759 session_fifo_event_t evt;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002760 int rv, n_write;
Dave Wallace543852a2017-08-03 02:11:34 -04002761 char *fifo_str;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002762 u32 poll_et;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002763 u8 is_server;
2764 u8 is_nonblocking;
2765 session_state_t state;
Dave Wallace543852a2017-08-03 02:11:34 -04002766
2767 ASSERT (buf);
2768
Dave Wallace4878cbe2017-11-21 03:45:09 -05002769 VCL_LOCK_AND_GET_SESSION (session_index, &session);
2770
2771 if (PREDICT_FALSE (session->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04002772 {
2773 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002774 clib_warning ("[%d] ERROR: sid %u: cannot write to an epoll session!",
2775 getpid (), session_index);
2776
2777 rv = VPPCOM_EBADFD;
2778 goto done;
Dave Wallace543852a2017-08-03 02:11:34 -04002779 }
2780
Dave Wallace4878cbe2017-11-21 03:45:09 -05002781 is_server = session->is_server;
2782 is_nonblocking = session->is_nonblocking;
2783 state = session->state;
2784 if (!(state & (SERVER_STATE_OPEN | CLIENT_STATE_OPEN)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002785 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002786 rv = ((state == STATE_DISCONNECT) ? VPPCOM_ECONNRESET :
2787 VPPCOM_ENOTCONN);
2788
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002789 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002790 if (VPPCOM_DEBUG > 1)
2791 clib_warning ("[%d] sid %u: %s session is not open! state 0x%x (%s)",
2792 getpid (), session_index, is_server ?
2793 "server" : "client", state,
2794 vppcom_session_state_str (state));
2795 goto done;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002796 }
2797
Dave Wallace4878cbe2017-11-21 03:45:09 -05002798 tx_fifo = ((!session->is_cut_thru || is_server) ?
Dave Wallace543852a2017-08-03 02:11:34 -04002799 session->server_tx_fifo : session->server_rx_fifo);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002800 fifo_str = ((!session->is_cut_thru || is_server) ?
Dave Wallace543852a2017-08-03 02:11:34 -04002801 "server_tx_fifo" : "server_rx_fifo");
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002802 clib_spinlock_unlock (&vcm->sessions_lockp);
2803
Dave Wallace543852a2017-08-03 02:11:34 -04002804 do
2805 {
Dave Wallacef7f809c2017-10-03 01:48:42 -04002806 n_write = svm_fifo_enqueue_nowait (tx_fifo, n, buf);
Dave Wallace543852a2017-08-03 02:11:34 -04002807 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002808 while (!is_nonblocking && (n_write <= 0));
Dave Wallace543852a2017-08-03 02:11:34 -04002809
2810 /* If event wasn't set, add one */
Dave Wallacef7f809c2017-10-03 01:48:42 -04002811 if (!session->is_cut_thru && (n_write > 0) && svm_fifo_set_event (tx_fifo))
Dave Wallace543852a2017-08-03 02:11:34 -04002812 {
Dave Wallace543852a2017-08-03 02:11:34 -04002813 /* Fabricate TX event, send to vpp */
2814 evt.fifo = tx_fifo;
2815 evt.event_type = FIFO_EVENT_APP_TX;
Dave Wallace543852a2017-08-03 02:11:34 -04002816
Dave Wallace4878cbe2017-11-21 03:45:09 -05002817 VCL_LOCK_AND_GET_SESSION (session_index, &session);
2818 q = session->vpp_event_queue;
Dave Wallace543852a2017-08-03 02:11:34 -04002819 ASSERT (q);
2820 unix_shared_memory_queue_add (q, (u8 *) & evt,
2821 0 /* do wait for mutex */ );
Dave Wallace4878cbe2017-11-21 03:45:09 -05002822 clib_spinlock_unlock (&vcm->sessions_lockp);
2823 if (VPPCOM_DEBUG > 1)
2824 clib_warning ("[%d] sid %u: added FIFO_EVENT_APP_TX to "
2825 "vpp_event_q %p, n_write %d", getpid (),
2826 session_index, q, n_write);
Dave Wallace543852a2017-08-03 02:11:34 -04002827 }
2828
Dave Wallace4878cbe2017-11-21 03:45:09 -05002829 if (n_write <= 0)
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002830 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002831 VCL_LOCK_AND_GET_SESSION (session_index, &session);
2832
2833 poll_et = (((EPOLLET | EPOLLOUT) & session->vep.ev.events) ==
2834 (EPOLLET | EPOLLOUT));
2835 if (poll_et)
2836 session->vep.et_mask |= EPOLLOUT;
2837
2838 if (state == STATE_CLOSE_ON_EMPTY)
2839 {
2840 session_state_t new_state = STATE_DISCONNECT;
2841 rv = VPPCOM_ECONNRESET;
2842
2843 if (VPPCOM_DEBUG > 1)
2844 {
2845 clib_warning ("[%d] sid %u: Empty fifo with %s session "
2846 "state 0x%x (%s)!\n"
2847 " Setting state to %d (%s), returning %d (%s)",
2848 getpid (), session_index,
2849 is_server ? "server" : "client",
2850 state, vppcom_session_state_str (state),
2851 new_state, vppcom_session_state_str (new_state),
2852 rv, vppcom_retval_str (rv));
2853 }
2854
2855 session->state = new_state;
2856 }
2857 else
2858 rv = VPPCOM_EAGAIN;
2859
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002860 clib_spinlock_unlock (&vcm->sessions_lockp);
2861 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002862 else
2863 rv = n_write;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002864
Dave Wallace543852a2017-08-03 02:11:34 -04002865 if (VPPCOM_DEBUG > 2)
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002866 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002867 if (n_write <= 0)
2868 clib_warning ("[%d] sid %u: FIFO-FULL %s (%p)", getpid (),
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002869 session_index, fifo_str, tx_fifo);
2870 else
Dave Wallace4878cbe2017-11-21 03:45:09 -05002871 clib_warning ("[%d] sid %u: wrote %d bytes to %s (%p)", getpid (),
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002872 session_index, n_write, fifo_str, tx_fifo);
2873 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002874done:
2875 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002876}
2877
2878static inline int
2879vppcom_session_write_ready (session_t * session, u32 session_index)
2880{
Dave Wallace543852a2017-08-03 02:11:34 -04002881 svm_fifo_t *tx_fifo;
Dave Wallace33e002b2017-09-06 01:20:02 -04002882 char *fifo_str;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002883 int ready;
Dave Wallace60caa062017-11-10 17:07:13 -05002884 u32 poll_et;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002885 int rv;
2886 u8 is_server = session->is_server;
2887 session_state_t state = session->state;
Dave Wallace543852a2017-08-03 02:11:34 -04002888
2889 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05002890 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002891 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002892 clib_warning ("[%d] ERROR: sid %u: cannot write to an "
2893 "epoll session!", getpid (), session_index);
2894 rv = VPPCOM_EBADFD;
2895 goto done;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002896 }
2897
Dave Wallace4878cbe2017-11-21 03:45:09 -05002898 if (PREDICT_FALSE (session->is_listen))
Dave Wallace33e002b2017-09-06 01:20:02 -04002899 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002900 clib_warning ("[%d] ERROR: sid %u: cannot write to a listen session!",
2901 getpid (), session_index);
2902 rv = VPPCOM_EBADFD;
2903 goto done;
2904 }
2905
2906 if (!(state & (SERVER_STATE_OPEN | CLIENT_STATE_OPEN)))
2907 {
2908 session_state_t state = session->state;
2909
2910 rv = ((state == STATE_DISCONNECT) ? VPPCOM_ECONNRESET :
2911 VPPCOM_ENOTCONN);
2912
2913 clib_warning ("[%d] ERROR: sid %u: %s session is not open! "
2914 "state 0x%x (%s), returning %d (%s)", getpid (),
2915 session_index, is_server ? "server" : "client",
2916 state, vppcom_session_state_str (state),
2917 rv, vppcom_retval_str (rv));
2918 goto done;
Dave Wallace33e002b2017-09-06 01:20:02 -04002919 }
2920
Dave Wallace543852a2017-08-03 02:11:34 -04002921 tx_fifo = ((!session->is_cut_thru || session->is_server) ?
2922 session->server_tx_fifo : session->server_rx_fifo);
Dave Wallace33e002b2017-09-06 01:20:02 -04002923 fifo_str = ((!session->is_cut_thru || session->is_server) ?
2924 "server_tx_fifo" : "server_rx_fifo");
Dave Wallace543852a2017-08-03 02:11:34 -04002925
Dave Wallacef7f809c2017-10-03 01:48:42 -04002926 ready = svm_fifo_max_enqueue (tx_fifo);
Dave Wallace543852a2017-08-03 02:11:34 -04002927
Dave Wallace33e002b2017-09-06 01:20:02 -04002928 if (VPPCOM_DEBUG > 3)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002929 clib_warning ("[%d] sid %u: peek %s (%p), ready = %d", getpid (),
Dave Wallacef7f809c2017-10-03 01:48:42 -04002930 session_index, fifo_str, tx_fifo, ready);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002931
Dave Wallace4878cbe2017-11-21 03:45:09 -05002932 if (ready == 0)
2933 {
2934 poll_et = (((EPOLLET | EPOLLOUT) & session->vep.ev.events) ==
2935 (EPOLLET | EPOLLOUT));
2936 if (poll_et)
2937 session->vep.et_mask |= EPOLLOUT;
2938
2939 if (state == STATE_CLOSE_ON_EMPTY)
2940 {
2941 rv = VPPCOM_ECONNRESET;
2942 session_state_t new_state = STATE_DISCONNECT;
2943
2944 if (VPPCOM_DEBUG > 1)
2945 {
2946 clib_warning ("[%d] sid %u: Empty fifo with %s session "
2947 "state 0x%x (%s)!\n"
2948 " Setting state to %d (%s), returning %d (%s)",
2949 getpid (), session_index,
2950 is_server ? "server" : "client",
2951 state, vppcom_session_state_str (state),
2952 new_state, vppcom_session_state_str (new_state),
2953 rv, vppcom_retval_str (rv));
2954 }
2955 session->state = new_state;
2956 goto done;
2957 }
2958 }
2959 rv = ready;
2960done:
2961 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04002962}
2963
2964int
2965vppcom_select (unsigned long n_bits, unsigned long *read_map,
2966 unsigned long *write_map, unsigned long *except_map,
2967 double time_to_wait)
2968{
Dave Wallace543852a2017-08-03 02:11:34 -04002969 u32 session_index;
2970 session_t *session = 0;
2971 int rv, bits_set = 0;
2972 f64 timeout = clib_time_now (&vcm->clib_time) + time_to_wait;
2973 u32 minbits = clib_max (n_bits, BITS (uword));
2974
2975 ASSERT (sizeof (clib_bitmap_t) == sizeof (long int));
2976
Dave Wallace7876d392017-10-19 03:53:57 -04002977 if (n_bits && read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002978 {
2979 clib_bitmap_validate (vcm->rd_bitmap, minbits);
2980 clib_memcpy (vcm->rd_bitmap, read_map, vec_len (vcm->rd_bitmap));
2981 memset (read_map, 0, vec_len (vcm->rd_bitmap));
2982 }
Dave Wallace7876d392017-10-19 03:53:57 -04002983 if (n_bits && write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002984 {
2985 clib_bitmap_validate (vcm->wr_bitmap, minbits);
2986 clib_memcpy (vcm->wr_bitmap, write_map, vec_len (vcm->wr_bitmap));
2987 memset (write_map, 0, vec_len (vcm->wr_bitmap));
2988 }
Dave Wallace7876d392017-10-19 03:53:57 -04002989 if (n_bits && except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002990 {
2991 clib_bitmap_validate (vcm->ex_bitmap, minbits);
2992 clib_memcpy (vcm->ex_bitmap, except_map, vec_len (vcm->ex_bitmap));
2993 memset (except_map, 0, vec_len (vcm->ex_bitmap));
2994 }
2995
2996 do
2997 {
2998 /* *INDENT-OFF* */
Dave Wallacee22aa742017-10-20 12:30:38 -04002999 if (n_bits)
3000 {
3001 if (read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04003002 {
Dave Wallacee22aa742017-10-20 12:30:38 -04003003 clib_bitmap_foreach (session_index, vcm->rd_bitmap,
3004 ({
3005 clib_spinlock_lock (&vcm->sessions_lockp);
3006 rv = vppcom_session_at_index (session_index, &session);
3007 if (rv < 0)
3008 {
3009 clib_spinlock_unlock (&vcm->sessions_lockp);
3010 if (VPPCOM_DEBUG > 1)
3011 clib_warning ("[%d] session %d specified in "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003012 "read_map is closed.", getpid (),
Dave Wallacee22aa742017-10-20 12:30:38 -04003013 session_index);
3014 bits_set = VPPCOM_EBADFD;
3015 goto select_done;
3016 }
3017
3018 rv = vppcom_session_read_ready (session, session_index);
3019 clib_spinlock_unlock (&vcm->sessions_lockp);
3020 if (except_map && vcm->ex_bitmap &&
3021 clib_bitmap_get (vcm->ex_bitmap, session_index) &&
3022 (rv < 0))
3023 {
3024 // TBD: clib_warning
3025 clib_bitmap_set_no_check (except_map, session_index, 1);
3026 bits_set++;
3027 }
3028 else if (rv > 0)
3029 {
3030 // TBD: clib_warning
3031 clib_bitmap_set_no_check (read_map, session_index, 1);
3032 bits_set++;
3033 }
3034 }));
Dave Wallace543852a2017-08-03 02:11:34 -04003035 }
3036
Dave Wallacee22aa742017-10-20 12:30:38 -04003037 if (write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04003038 {
Dave Wallacee22aa742017-10-20 12:30:38 -04003039 clib_bitmap_foreach (session_index, vcm->wr_bitmap,
3040 ({
3041 clib_spinlock_lock (&vcm->sessions_lockp);
3042 rv = vppcom_session_at_index (session_index, &session);
3043 if (rv < 0)
3044 {
3045 clib_spinlock_unlock (&vcm->sessions_lockp);
3046 if (VPPCOM_DEBUG > 0)
3047 clib_warning ("[%d] session %d specified in "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003048 "write_map is closed.", getpid (),
Dave Wallacee22aa742017-10-20 12:30:38 -04003049 session_index);
3050 bits_set = VPPCOM_EBADFD;
3051 goto select_done;
3052 }
Dave Wallace543852a2017-08-03 02:11:34 -04003053
Dave Wallacee22aa742017-10-20 12:30:38 -04003054 rv = vppcom_session_write_ready (session, session_index);
3055 clib_spinlock_unlock (&vcm->sessions_lockp);
3056 if (write_map && (rv > 0))
3057 {
3058 // TBD: clib_warning
3059 clib_bitmap_set_no_check (write_map, session_index, 1);
3060 bits_set++;
3061 }
3062 }));
Dave Wallace543852a2017-08-03 02:11:34 -04003063 }
3064
Dave Wallacee22aa742017-10-20 12:30:38 -04003065 if (except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04003066 {
Dave Wallacee22aa742017-10-20 12:30:38 -04003067 clib_bitmap_foreach (session_index, vcm->ex_bitmap,
3068 ({
3069 clib_spinlock_lock (&vcm->sessions_lockp);
3070 rv = vppcom_session_at_index (session_index, &session);
3071 if (rv < 0)
3072 {
3073 clib_spinlock_unlock (&vcm->sessions_lockp);
3074 if (VPPCOM_DEBUG > 1)
3075 clib_warning ("[%d] session %d specified in "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003076 "except_map is closed.", getpid (),
Dave Wallacee22aa742017-10-20 12:30:38 -04003077 session_index);
3078 bits_set = VPPCOM_EBADFD;
3079 goto select_done;
3080 }
Dave Wallace543852a2017-08-03 02:11:34 -04003081
Dave Wallacee22aa742017-10-20 12:30:38 -04003082 rv = vppcom_session_read_ready (session, session_index);
3083 clib_spinlock_unlock (&vcm->sessions_lockp);
3084 if (rv < 0)
3085 {
3086 // TBD: clib_warning
3087 clib_bitmap_set_no_check (except_map, session_index, 1);
3088 bits_set++;
3089 }
3090 }));
Dave Wallace543852a2017-08-03 02:11:34 -04003091 }
Dave Wallacee22aa742017-10-20 12:30:38 -04003092 }
Dave Wallace543852a2017-08-03 02:11:34 -04003093 /* *INDENT-ON* */
3094 }
3095 while (clib_time_now (&vcm->clib_time) < timeout);
3096
3097select_done:
3098 return (bits_set);
3099}
3100
Dave Wallacef7f809c2017-10-03 01:48:42 -04003101static inline void
3102vep_verify_epoll_chain (u32 vep_idx)
3103{
3104 session_t *session;
3105 vppcom_epoll_t *vep;
3106 int rv;
Dave Wallace498b3a52017-11-09 13:00:34 -05003107 u32 sid = vep_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04003108
Dave Wallace498b3a52017-11-09 13:00:34 -05003109 if (VPPCOM_DEBUG <= 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -04003110 return;
3111
3112 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
3113 rv = vppcom_session_at_index (vep_idx, &session);
3114 if (PREDICT_FALSE (rv))
3115 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05003116 clib_warning ("[%d] ERROR: Invalid vep_idx (%u)!", getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003117 goto done;
3118 }
3119 if (PREDICT_FALSE (!session->is_vep))
3120 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05003121 clib_warning ("[%d] ERROR: vep_idx (%u) is not a vep!", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04003122 vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003123 goto done;
3124 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05003125 vep = &session->vep;
Dave Wallace498b3a52017-11-09 13:00:34 -05003126 clib_warning ("[%d] vep_idx (%u): Dumping epoll chain\n"
3127 "{\n"
3128 " is_vep = %u\n"
3129 " is_vep_session = %u\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05003130 " next_sid = 0x%x (%u)\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05003131 " wait_cont_idx = 0x%x (%u)\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05003132 "}\n", getpid (), vep_idx,
3133 session->is_vep, session->is_vep_session,
3134 vep->next_sid, vep->next_sid,
Dave Wallace498b3a52017-11-09 13:00:34 -05003135 session->wait_cont_idx, session->wait_cont_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05003136
3137 for (sid = vep->next_sid; sid != ~0; sid = vep->next_sid)
Dave Wallacef7f809c2017-10-03 01:48:42 -04003138 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003139 rv = vppcom_session_at_index (sid, &session);
3140 if (PREDICT_FALSE (rv))
Dave Wallacef7f809c2017-10-03 01:48:42 -04003141 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003142 clib_warning ("[%d] ERROR: Invalid sid (%u)!", getpid (), sid);
3143 goto done;
3144 }
3145 if (PREDICT_FALSE (session->is_vep))
3146 clib_warning ("[%d] ERROR: sid (%u) is a vep!", getpid (), vep_idx);
3147 else if (PREDICT_FALSE (!session->is_vep_session))
3148 {
3149 clib_warning ("[%d] ERROR: session (%u) is not a vep session!",
3150 getpid (), sid);
3151 goto done;
3152 }
3153 vep = &session->vep;
3154 if (PREDICT_FALSE (vep->vep_idx != vep_idx))
3155 clib_warning ("[%d] ERROR: session (%u) vep_idx (%u) != "
3156 "vep_idx (%u)!", getpid (),
3157 sid, session->vep.vep_idx, vep_idx);
3158 if (session->is_vep_session)
3159 {
3160 clib_warning ("vep_idx[%u]: sid 0x%x (%u)\n"
3161 "{\n"
3162 " next_sid = 0x%x (%u)\n"
3163 " prev_sid = 0x%x (%u)\n"
3164 " vep_idx = 0x%x (%u)\n"
3165 " ev.events = 0x%x\n"
3166 " ev.data.u64 = 0x%llx\n"
3167 " et_mask = 0x%x\n"
3168 "}\n",
3169 vep_idx, sid, sid,
3170 vep->next_sid, vep->next_sid,
3171 vep->prev_sid, vep->prev_sid,
3172 vep->vep_idx, vep->vep_idx,
3173 vep->ev.events, vep->ev.data.u64, vep->et_mask);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003174 }
3175 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04003176
3177done:
Dave Wallace498b3a52017-11-09 13:00:34 -05003178 clib_warning ("[%d] vep_idx (%u): Dump complete!\n", getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003179}
3180
3181int
3182vppcom_epoll_create (void)
3183{
Dave Wallacef7f809c2017-10-03 01:48:42 -04003184 session_t *vep_session;
3185 u32 vep_idx;
3186
3187 clib_spinlock_lock (&vcm->sessions_lockp);
3188 pool_get (vcm->sessions, vep_session);
3189 memset (vep_session, 0, sizeof (*vep_session));
3190 vep_idx = vep_session - vcm->sessions;
3191
3192 vep_session->is_vep = 1;
3193 vep_session->vep.vep_idx = ~0;
3194 vep_session->vep.next_sid = ~0;
3195 vep_session->vep.prev_sid = ~0;
3196 vep_session->wait_cont_idx = ~0;
Dave Wallace4878cbe2017-11-21 03:45:09 -05003197 vep_session->vpp_handle = ~0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04003198 clib_spinlock_unlock (&vcm->sessions_lockp);
3199
3200 if (VPPCOM_DEBUG > 0)
Dave Wallace2e005bb2017-11-07 01:21:39 -05003201 clib_warning ("[%d] Created vep_idx %u!", getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003202
3203 return (vep_idx);
3204}
3205
3206int
3207vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index,
3208 struct epoll_event *event)
3209{
Dave Wallacef7f809c2017-10-03 01:48:42 -04003210 session_t *vep_session;
3211 session_t *session;
3212 int rv;
3213
3214 if (vep_idx == session_index)
3215 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003216 clib_warning ("[%d] ERROR: vep_idx == session_index (%u)!",
3217 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003218 return VPPCOM_EINVAL;
3219 }
3220
3221 clib_spinlock_lock (&vcm->sessions_lockp);
3222 rv = vppcom_session_at_index (vep_idx, &vep_session);
3223 if (PREDICT_FALSE (rv))
3224 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003225 clib_warning ("[%d] ERROR: Invalid vep_idx (%u)!", vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003226 goto done;
3227 }
3228 if (PREDICT_FALSE (!vep_session->is_vep))
3229 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003230 clib_warning ("[%d] ERROR: vep_idx (%u) is not a vep!",
3231 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003232 rv = VPPCOM_EINVAL;
3233 goto done;
3234 }
3235
3236 ASSERT (vep_session->vep.vep_idx == ~0);
3237 ASSERT (vep_session->vep.prev_sid == ~0);
3238
3239 rv = vppcom_session_at_index (session_index, &session);
3240 if (PREDICT_FALSE (rv))
3241 {
3242 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04003243 clib_warning ("[%d] ERROR: Invalid session_index (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003244 getpid (), session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003245 goto done;
3246 }
3247 if (PREDICT_FALSE (session->is_vep))
3248 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003249 clib_warning ("ERROR: session_index (%u) is a vep!", vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003250 rv = VPPCOM_EINVAL;
3251 goto done;
3252 }
3253
3254 switch (op)
3255 {
3256 case EPOLL_CTL_ADD:
3257 if (PREDICT_FALSE (!event))
3258 {
Dave Wallace774169b2017-11-01 20:07:40 -04003259 clib_warning ("[%d] ERROR: EPOLL_CTL_ADD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003260 "epoll_event structure!", getpid ());
Dave Wallacef7f809c2017-10-03 01:48:42 -04003261 rv = VPPCOM_EINVAL;
3262 goto done;
3263 }
3264 if (vep_session->vep.next_sid != ~0)
3265 {
3266 session_t *next_session;
3267 rv = vppcom_session_at_index (vep_session->vep.next_sid,
3268 &next_session);
3269 if (PREDICT_FALSE (rv))
3270 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003271 clib_warning ("[%d] ERROR: EPOLL_CTL_ADD: Invalid "
3272 "vep.next_sid (%u) on vep_idx (%u)!",
3273 getpid (), vep_session->vep.next_sid, vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003274 goto done;
3275 }
3276 ASSERT (next_session->vep.prev_sid == vep_idx);
3277 next_session->vep.prev_sid = session_index;
3278 }
3279 session->vep.next_sid = vep_session->vep.next_sid;
3280 session->vep.prev_sid = vep_idx;
3281 session->vep.vep_idx = vep_idx;
3282 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
3283 session->vep.ev = *event;
Dave Wallace4878cbe2017-11-21 03:45:09 -05003284 session->is_vep = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04003285 session->is_vep_session = 1;
3286 vep_session->vep.next_sid = session_index;
3287 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003288 clib_warning ("[%d] EPOLL_CTL_ADD: vep_idx %u, sid %u, events 0x%x,"
Dave Wallace2e005bb2017-11-07 01:21:39 -05003289 " data 0x%llx!", getpid (), vep_idx, session_index,
Dave Wallacef7f809c2017-10-03 01:48:42 -04003290 event->events, event->data.u64);
3291 break;
3292
3293 case EPOLL_CTL_MOD:
3294 if (PREDICT_FALSE (!event))
3295 {
Dave Wallace774169b2017-11-01 20:07:40 -04003296 clib_warning ("[%d] ERROR: EPOLL_CTL_MOD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003297 "epoll_event structure!", getpid ());
Dave Wallacef7f809c2017-10-03 01:48:42 -04003298 rv = VPPCOM_EINVAL;
3299 goto done;
3300 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05003301 else if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04003302 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003303 clib_warning ("[%d] ERROR: sid %u EPOLL_CTL_MOD: "
3304 "not a vep session!", getpid (), session_index);
3305 rv = VPPCOM_EINVAL;
3306 goto done;
3307 }
3308 else if (PREDICT_FALSE (session->vep.vep_idx != vep_idx))
3309 {
3310 clib_warning ("[%d] ERROR: sid %u EPOLL_CTL_MOD: "
3311 "vep_idx (%u) != vep_idx (%u)!",
3312 getpid (), session_index,
3313 session->vep.vep_idx, vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003314 rv = VPPCOM_EINVAL;
3315 goto done;
3316 }
3317 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
3318 session->vep.ev = *event;
3319 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003320 clib_warning ("[%d] EPOLL_CTL_MOD: vep_idx %u, sid %u, events 0x%x,"
Dave Wallace2e005bb2017-11-07 01:21:39 -05003321 " data 0x%llx!", getpid (), vep_idx, session_index,
Dave Wallacef7f809c2017-10-03 01:48:42 -04003322 event->events, event->data.u64);
3323 break;
3324
3325 case EPOLL_CTL_DEL:
Dave Wallace4878cbe2017-11-21 03:45:09 -05003326 if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04003327 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003328 clib_warning ("[%d] ERROR: sid %u EPOLL_CTL_DEL: "
3329 "not a vep session!", getpid (), session_index);
3330 rv = VPPCOM_EINVAL;
3331 goto done;
3332 }
3333 else if (PREDICT_FALSE (session->vep.vep_idx != vep_idx))
3334 {
3335 clib_warning ("[%d] ERROR: sid %u EPOLL_CTL_DEL: "
3336 "vep_idx (%u) != vep_idx (%u)!",
3337 getpid (), session_index,
3338 session->vep.vep_idx, vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003339 rv = VPPCOM_EINVAL;
3340 goto done;
3341 }
3342
3343 vep_session->wait_cont_idx =
3344 (vep_session->wait_cont_idx == session_index) ?
3345 session->vep.next_sid : vep_session->wait_cont_idx;
3346
3347 if (session->vep.prev_sid == vep_idx)
3348 vep_session->vep.next_sid = session->vep.next_sid;
3349 else
3350 {
3351 session_t *prev_session;
3352 rv = vppcom_session_at_index (session->vep.prev_sid, &prev_session);
3353 if (PREDICT_FALSE (rv))
3354 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003355 clib_warning ("[%d] ERROR: EPOLL_CTL_DEL: Invalid "
3356 "vep.prev_sid (%u) on sid (%u)!",
3357 getpid (), session->vep.prev_sid, session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003358 goto done;
3359 }
3360 ASSERT (prev_session->vep.next_sid == session_index);
3361 prev_session->vep.next_sid = session->vep.next_sid;
3362 }
3363 if (session->vep.next_sid != ~0)
3364 {
3365 session_t *next_session;
3366 rv = vppcom_session_at_index (session->vep.next_sid, &next_session);
3367 if (PREDICT_FALSE (rv))
3368 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003369 clib_warning ("[%d] ERROR: EPOLL_CTL_DEL: Invalid "
3370 "vep.next_sid (%u) on sid (%u)!",
3371 getpid (), session->vep.next_sid, session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003372 goto done;
3373 }
3374 ASSERT (next_session->vep.prev_sid == session_index);
3375 next_session->vep.prev_sid = session->vep.prev_sid;
3376 }
3377
3378 memset (&session->vep, 0, sizeof (session->vep));
3379 session->vep.next_sid = ~0;
3380 session->vep.prev_sid = ~0;
3381 session->vep.vep_idx = ~0;
3382 session->is_vep_session = 0;
3383 if (VPPCOM_DEBUG > 1)
Dave Wallace774169b2017-11-01 20:07:40 -04003384 clib_warning ("[%d] EPOLL_CTL_DEL: vep_idx %u, sid %u!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003385 getpid (), vep_idx, session_index);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003386 break;
3387
3388 default:
Dave Wallace2e005bb2017-11-07 01:21:39 -05003389 clib_warning ("[%d] ERROR: Invalid operation (%d)!", getpid (), op);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003390 rv = VPPCOM_EINVAL;
3391 }
3392
3393 vep_verify_epoll_chain (vep_idx);
3394
3395done:
3396 clib_spinlock_unlock (&vcm->sessions_lockp);
3397 return rv;
3398}
3399
Dave Wallacef7f809c2017-10-03 01:48:42 -04003400int
3401vppcom_epoll_wait (uint32_t vep_idx, struct epoll_event *events,
3402 int maxevents, double wait_for_time)
3403{
Dave Wallacef7f809c2017-10-03 01:48:42 -04003404 session_t *vep_session;
3405 int rv;
3406 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
Dave Wallace2e005bb2017-11-07 01:21:39 -05003407 u32 keep_trying = 1;
Dave Wallacef7f809c2017-10-03 01:48:42 -04003408 int num_ev = 0;
3409 u32 vep_next_sid, wait_cont_idx;
3410 u8 is_vep;
3411
3412 if (PREDICT_FALSE (maxevents <= 0))
3413 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003414 clib_warning ("[%d] ERROR: Invalid maxevents (%d)!",
3415 getpid (), maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003416 return VPPCOM_EINVAL;
3417 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04003418 memset (events, 0, sizeof (*events) * maxevents);
3419
3420 VCL_LOCK_AND_GET_SESSION (vep_idx, &vep_session);
3421 vep_next_sid = vep_session->vep.next_sid;
3422 is_vep = vep_session->is_vep;
3423 wait_cont_idx = vep_session->wait_cont_idx;
3424 clib_spinlock_unlock (&vcm->sessions_lockp);
3425
3426 if (PREDICT_FALSE (!is_vep))
3427 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05003428 clib_warning ("[%d] ERROR: vep_idx (%u) is not a vep!",
3429 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003430 rv = VPPCOM_EINVAL;
3431 goto done;
3432 }
Dave Wallacee695cb42017-11-02 22:04:42 -04003433 if (PREDICT_FALSE (vep_next_sid == ~0))
Dave Wallacef7f809c2017-10-03 01:48:42 -04003434 {
Dave Wallacee695cb42017-11-02 22:04:42 -04003435 if (VPPCOM_DEBUG > 0)
3436 clib_warning ("[%d] WARNING: vep_idx (%u) is empty!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003437 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003438 goto done;
3439 }
3440
3441 do
3442 {
3443 u32 sid;
3444 u32 next_sid = ~0;
3445 session_t *session;
3446
3447 for (sid = (wait_cont_idx == ~0) ? vep_next_sid : wait_cont_idx;
3448 sid != ~0; sid = next_sid)
3449 {
3450 u32 session_events, et_mask, clear_et_mask, session_vep_idx;
3451 u8 add_event, is_vep_session;
3452 int ready;
3453 u64 session_ev_data;
3454
3455 VCL_LOCK_AND_GET_SESSION (sid, &session);
3456 next_sid = session->vep.next_sid;
3457 session_events = session->vep.ev.events;
3458 et_mask = session->vep.et_mask;
3459 is_vep = session->is_vep;
3460 is_vep_session = session->is_vep_session;
3461 session_vep_idx = session->vep.vep_idx;
3462 session_ev_data = session->vep.ev.data.u64;
3463 clib_spinlock_unlock (&vcm->sessions_lockp);
3464
3465 if (PREDICT_FALSE (is_vep))
3466 {
3467 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04003468 clib_warning ("[%d] ERROR: sid (%u) is a vep!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003469 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003470 rv = VPPCOM_EINVAL;
3471 goto done;
3472 }
3473 if (PREDICT_FALSE (!is_vep_session))
3474 {
3475 if (VPPCOM_DEBUG > 0)
Dave Wallace774169b2017-11-01 20:07:40 -04003476 clib_warning ("[%d] ERROR: session (%u) is not "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003477 "a vep session!", getpid (), sid);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003478 rv = VPPCOM_EINVAL;
3479 goto done;
3480 }
3481 if (PREDICT_FALSE (session_vep_idx != vep_idx))
3482 {
Dave Wallace774169b2017-11-01 20:07:40 -04003483 clib_warning ("[%d] ERROR: session (%u) "
Dave Wallacef7f809c2017-10-03 01:48:42 -04003484 "vep_idx (%u) != vep_idx (%u)!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003485 getpid (), sid, session->vep.vep_idx, vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003486 rv = VPPCOM_EINVAL;
3487 goto done;
3488 }
3489
3490 add_event = clear_et_mask = 0;
3491
Dave Wallace60caa062017-11-10 17:07:13 -05003492 if (EPOLLIN & session_events)
Dave Wallacef7f809c2017-10-03 01:48:42 -04003493 {
3494 VCL_LOCK_AND_GET_SESSION (sid, &session);
3495 ready = vppcom_session_read_ready (session, sid);
3496 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace60caa062017-11-10 17:07:13 -05003497 if ((ready > 0) && (EPOLLIN & et_mask))
Dave Wallacef7f809c2017-10-03 01:48:42 -04003498 {
3499 add_event = 1;
3500 events[num_ev].events |= EPOLLIN;
Dave Wallace60caa062017-11-10 17:07:13 -05003501 if (((EPOLLET | EPOLLIN) & session_events) ==
3502 (EPOLLET | EPOLLIN))
Dave Wallacef7f809c2017-10-03 01:48:42 -04003503 clear_et_mask |= EPOLLIN;
3504 }
3505 else if (ready < 0)
3506 {
3507 add_event = 1;
3508 switch (ready)
3509 {
3510 case VPPCOM_ECONNRESET:
3511 events[num_ev].events |= EPOLLHUP | EPOLLRDHUP;
3512 break;
3513
3514 default:
3515 events[num_ev].events |= EPOLLERR;
3516 break;
3517 }
3518 }
3519 }
3520
Dave Wallace60caa062017-11-10 17:07:13 -05003521 if (EPOLLOUT & session_events)
Dave Wallacef7f809c2017-10-03 01:48:42 -04003522 {
3523 VCL_LOCK_AND_GET_SESSION (sid, &session);
3524 ready = vppcom_session_write_ready (session, sid);
3525 clib_spinlock_unlock (&vcm->sessions_lockp);
Dave Wallace60caa062017-11-10 17:07:13 -05003526 if ((ready > 0) && (EPOLLOUT & et_mask))
Dave Wallacef7f809c2017-10-03 01:48:42 -04003527 {
3528 add_event = 1;
3529 events[num_ev].events |= EPOLLOUT;
Dave Wallace60caa062017-11-10 17:07:13 -05003530 if (((EPOLLET | EPOLLOUT) & session_events) ==
3531 (EPOLLET | EPOLLOUT))
Dave Wallacef7f809c2017-10-03 01:48:42 -04003532 clear_et_mask |= EPOLLOUT;
3533 }
3534 else if (ready < 0)
3535 {
3536 add_event = 1;
3537 switch (ready)
3538 {
3539 case VPPCOM_ECONNRESET:
3540 events[num_ev].events |= EPOLLHUP;
3541 break;
3542
3543 default:
3544 events[num_ev].events |= EPOLLERR;
3545 break;
3546 }
3547 }
3548 }
3549
3550 if (add_event)
3551 {
3552 events[num_ev].data.u64 = session_ev_data;
3553 if (EPOLLONESHOT & session_events)
3554 {
3555 VCL_LOCK_AND_GET_SESSION (sid, &session);
3556 session->vep.ev.events = 0;
3557 clib_spinlock_unlock (&vcm->sessions_lockp);
3558 }
3559 num_ev++;
3560 if (num_ev == maxevents)
3561 {
3562 VCL_LOCK_AND_GET_SESSION (vep_idx, &vep_session);
3563 vep_session->wait_cont_idx = next_sid;
3564 clib_spinlock_unlock (&vcm->sessions_lockp);
3565 goto done;
3566 }
3567 }
3568 if (wait_cont_idx != ~0)
3569 {
3570 if (next_sid == ~0)
3571 next_sid = vep_next_sid;
3572 else if (next_sid == wait_cont_idx)
3573 next_sid = ~0;
3574 }
3575 }
Dave Wallace2e005bb2017-11-07 01:21:39 -05003576 if (wait_for_time != -1)
3577 keep_trying = (clib_time_now (&vcm->clib_time) <= timeout) ? 1 : 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04003578 }
Dave Wallace2e005bb2017-11-07 01:21:39 -05003579 while ((num_ev == 0) && keep_trying);
Dave Wallacef7f809c2017-10-03 01:48:42 -04003580
3581 if (wait_cont_idx != ~0)
3582 {
3583 VCL_LOCK_AND_GET_SESSION (vep_idx, &vep_session);
3584 vep_session->wait_cont_idx = ~0;
3585 clib_spinlock_unlock (&vcm->sessions_lockp);
3586 }
3587done:
3588 return (rv != VPPCOM_OK) ? rv : num_ev;
3589}
3590
Dave Wallace35830af2017-10-09 01:43:42 -04003591int
3592vppcom_session_attr (uint32_t session_index, uint32_t op,
3593 void *buffer, uint32_t * buflen)
3594{
Dave Wallace35830af2017-10-09 01:43:42 -04003595 session_t *session;
3596 int rv = VPPCOM_OK;
3597 u32 *flags = buffer;
Steven2199aab2017-10-15 20:18:47 -07003598 vppcom_endpt_t *ep = buffer;
Dave Wallace35830af2017-10-09 01:43:42 -04003599
3600 VCL_LOCK_AND_GET_SESSION (session_index, &session);
3601 switch (op)
3602 {
3603 case VPPCOM_ATTR_GET_NREAD:
3604 rv = vppcom_session_read_ready (session, session_index);
Dave Wallace227867f2017-11-13 21:21:53 -05003605 if (VPPCOM_DEBUG > 2)
3606 clib_warning ("[%d] VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003607 getpid (), rv);
Dave Wallace35830af2017-10-09 01:43:42 -04003608 break;
3609
Dave Wallace227867f2017-11-13 21:21:53 -05003610 case VPPCOM_ATTR_GET_NWRITE:
3611 rv = vppcom_session_write_ready (session, session_index);
3612 if (VPPCOM_DEBUG > 2)
3613 clib_warning ("[%d] VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d",
3614 getpid (), session_index, rv);
Dave Wallace35830af2017-10-09 01:43:42 -04003615 break;
3616
3617 case VPPCOM_ATTR_GET_FLAGS:
3618 if (buffer && buflen && (*buflen >= sizeof (*flags)))
3619 {
3620 *flags = O_RDWR | ((session->is_nonblocking) ? O_NONBLOCK : 0);
3621 *buflen = sizeof (*flags);
Dave Wallace227867f2017-11-13 21:21:53 -05003622 if (VPPCOM_DEBUG > 2)
3623 clib_warning ("[%d] VPPCOM_ATTR_GET_FLAGS: sid %u, "
3624 "flags = 0x%08x, is_nonblocking = %u", getpid (),
3625 session_index, *flags, session->is_nonblocking);
Dave Wallace35830af2017-10-09 01:43:42 -04003626 }
3627 else
3628 rv = VPPCOM_EINVAL;
3629 break;
3630
3631 case VPPCOM_ATTR_SET_FLAGS:
3632 if (buffer && buflen && (*buflen >= sizeof (*flags)))
3633 {
3634 session->is_nonblocking = (*flags & O_NONBLOCK) ? 1 : 0;
Dave Wallace227867f2017-11-13 21:21:53 -05003635 if (VPPCOM_DEBUG > 2)
3636 clib_warning ("[%d] VPPCOM_ATTR_SET_FLAGS: sid %u, "
3637 "flags = 0x%08x, is_nonblocking = %u",
Dave Wallace4878cbe2017-11-21 03:45:09 -05003638 getpid (), session_index, *flags,
3639 session->is_nonblocking);
Dave Wallace35830af2017-10-09 01:43:42 -04003640 }
3641 else
3642 rv = VPPCOM_EINVAL;
3643 break;
3644
3645 case VPPCOM_ATTR_GET_PEER_ADDR:
Steven2199aab2017-10-15 20:18:47 -07003646 if (buffer && buflen && (*buflen >= sizeof (*ep)))
Dave Wallace35830af2017-10-09 01:43:42 -04003647 {
Steven2199aab2017-10-15 20:18:47 -07003648 ep->vrf = session->vrf;
3649 ep->is_ip4 = session->peer_addr.is_ip4;
Stevenac1f96d2017-10-24 16:03:58 -07003650 ep->port = session->peer_port;
Steven2199aab2017-10-15 20:18:47 -07003651 if (session->peer_addr.is_ip4)
3652 clib_memcpy (ep->ip, &session->peer_addr.ip46.ip4,
3653 sizeof (ip4_address_t));
3654 else
3655 clib_memcpy (ep->ip, &session->peer_addr.ip46.ip6,
3656 sizeof (ip6_address_t));
3657 *buflen = sizeof (*ep);
Dave Wallacefaf9d772017-10-26 16:12:04 -04003658 if (VPPCOM_DEBUG > 1)
Dave Wallace227867f2017-11-13 21:21:53 -05003659 clib_warning ("[%d] VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003660 "%u, addr = %U, port %u", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04003661 session_index, ep->is_ip4, format_ip46_address,
Stevenac1f96d2017-10-24 16:03:58 -07003662 &session->peer_addr.ip46, ep->is_ip4,
3663 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04003664 }
3665 else
3666 rv = VPPCOM_EINVAL;
3667 break;
3668
3669 case VPPCOM_ATTR_GET_LCL_ADDR:
Steven2199aab2017-10-15 20:18:47 -07003670 if (buffer && buflen && (*buflen >= sizeof (*ep)))
Dave Wallace35830af2017-10-09 01:43:42 -04003671 {
Steven2199aab2017-10-15 20:18:47 -07003672 ep->vrf = session->vrf;
3673 ep->is_ip4 = session->lcl_addr.is_ip4;
Stevenac1f96d2017-10-24 16:03:58 -07003674 ep->port = session->lcl_port;
Steven2199aab2017-10-15 20:18:47 -07003675 if (session->lcl_addr.is_ip4)
3676 clib_memcpy (ep->ip, &session->lcl_addr.ip46.ip4,
3677 sizeof (ip4_address_t));
3678 else
3679 clib_memcpy (ep->ip, &session->lcl_addr.ip46.ip6,
3680 sizeof (ip6_address_t));
3681 *buflen = sizeof (*ep);
Dave Wallacefaf9d772017-10-26 16:12:04 -04003682 if (VPPCOM_DEBUG > 1)
Dave Wallace227867f2017-11-13 21:21:53 -05003683 clib_warning ("[%d] VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = "
Dave Wallace2e005bb2017-11-07 01:21:39 -05003684 "%u, addr = %U port %d", getpid (),
Dave Wallace774169b2017-11-01 20:07:40 -04003685 session_index, ep->is_ip4, format_ip46_address,
Stevenac1f96d2017-10-24 16:03:58 -07003686 &session->lcl_addr.ip46, ep->is_ip4,
3687 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04003688 }
3689 else
3690 rv = VPPCOM_EINVAL;
3691 break;
Stevenb5a11602017-10-11 09:59:30 -07003692
3693 case VPPCOM_ATTR_SET_REUSEADDR:
3694 break;
3695
3696 case VPPCOM_ATTR_SET_BROADCAST:
3697 break;
3698
3699 case VPPCOM_ATTR_SET_V6ONLY:
3700 break;
Stevenbccd3392017-10-12 20:42:21 -07003701
3702 case VPPCOM_ATTR_SET_KEEPALIVE:
3703 break;
3704
3705 case VPPCOM_ATTR_SET_TCP_KEEPIDLE:
3706 break;
3707
3708 case VPPCOM_ATTR_SET_TCP_KEEPINTVL:
3709 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003710
3711 default:
3712 rv = VPPCOM_EINVAL;
3713 break;
Dave Wallace35830af2017-10-09 01:43:42 -04003714 }
3715
3716done:
3717 clib_spinlock_unlock (&vcm->sessions_lockp);
3718 return rv;
3719}
3720
Stevenac1f96d2017-10-24 16:03:58 -07003721int
3722vppcom_session_recvfrom (uint32_t session_index, void *buffer,
3723 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3724{
Stevenac1f96d2017-10-24 16:03:58 -07003725 int rv = VPPCOM_OK;
3726 session_t *session = 0;
3727
3728 if (ep)
3729 {
3730 clib_spinlock_lock (&vcm->sessions_lockp);
3731 rv = vppcom_session_at_index (session_index, &session);
3732 if (PREDICT_FALSE (rv))
3733 {
3734 clib_spinlock_unlock (&vcm->sessions_lockp);
3735 if (VPPCOM_DEBUG > 0)
3736 clib_warning ("[%d] invalid session, sid (%u) has been closed!",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003737 getpid (), session_index);
Dave Wallacefaf9d772017-10-26 16:12:04 -04003738 rv = VPPCOM_EBADFD;
3739 clib_spinlock_unlock (&vcm->sessions_lockp);
3740 goto done;
Stevenac1f96d2017-10-24 16:03:58 -07003741 }
3742 ep->vrf = session->vrf;
3743 ep->is_ip4 = session->peer_addr.is_ip4;
3744 ep->port = session->peer_port;
3745 if (session->peer_addr.is_ip4)
3746 clib_memcpy (ep->ip, &session->peer_addr.ip46.ip4,
3747 sizeof (ip4_address_t));
3748 else
3749 clib_memcpy (ep->ip, &session->peer_addr.ip46.ip6,
3750 sizeof (ip6_address_t));
3751 clib_spinlock_unlock (&vcm->sessions_lockp);
Stevenac1f96d2017-10-24 16:03:58 -07003752 }
Steven58f464e2017-10-25 12:33:12 -07003753
3754 if (flags == 0)
Stevenac1f96d2017-10-24 16:03:58 -07003755 rv = vppcom_session_read (session_index, buffer, buflen);
3756 else if (flags & MSG_PEEK)
Steven58f464e2017-10-25 12:33:12 -07003757 rv = vppcom_session_peek (session_index, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003758 else
3759 {
Dave Wallace2e005bb2017-11-07 01:21:39 -05003760 clib_warning ("[%d] Unsupport flags for recvfrom %d", getpid (), flags);
Stevenac1f96d2017-10-24 16:03:58 -07003761 rv = VPPCOM_EAFNOSUPPORT;
3762 }
3763
Dave Wallacefaf9d772017-10-26 16:12:04 -04003764done:
Stevenac1f96d2017-10-24 16:03:58 -07003765 return rv;
3766}
3767
3768int
3769vppcom_session_sendto (uint32_t session_index, void *buffer,
3770 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3771{
Dave Wallace617dffa2017-10-26 14:47:06 -04003772 if (!buffer)
3773 return VPPCOM_EINVAL;
3774
3775 if (ep)
3776 {
3777 // TBD
3778 return VPPCOM_EINVAL;
3779 }
3780
3781 if (flags)
3782 {
3783 // TBD check the flags and do the right thing
3784 if (VPPCOM_DEBUG > 2)
3785 clib_warning ("[%d] handling flags 0x%u (%d) not implemented yet.",
Dave Wallace2e005bb2017-11-07 01:21:39 -05003786 getpid (), flags, flags);
Dave Wallace617dffa2017-10-26 14:47:06 -04003787 }
3788
3789 return (vppcom_session_write (session_index, buffer, buflen));
Stevenac1f96d2017-10-24 16:03:58 -07003790}
3791
Dave Wallacee22aa742017-10-20 12:30:38 -04003792/*
3793 * fd.io coding-style-patch-verification: ON
3794 *
3795 * Local Variables:
3796 * eval: (c-set-style "gnu")
3797 * End:
3798 */