blob: 6079bd18179e48f22d7654e8ad6884c681ef5c59 [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>
Dave Wallace543852a2017-08-03 02:11:34 -040018#include <svm/svm_fifo_segment.h>
Dave Wallace5c7cf1c2017-10-24 04:12:18 -040019#include <vcl/vppcom.h>
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -080020#include <vcl/vcl_event.h>
Florin Coras0d427d82018-06-27 03:24:07 -070021#include <vcl/vcl_debug.h>
Florin Coras697faea2018-06-27 17:10:49 -070022#include <vcl/vcl_private.h>
Dave Wallace7e607a72018-06-18 18:41:32 -040023
Florin Coras54693d22018-07-17 10:46:29 -070024static u8 not_ready;
25
26void
27sigsegv_signal (int signum)
28{
29 not_ready = 1;
30}
31
32static void
33vcl_wait_for_memory (void *mem)
34{
35 u8 __clib_unused test;
Florin Coras460dce62018-07-27 05:45:06 -070036 if (vcm->mounting_segment)
37 {
38 while (vcm->mounting_segment)
39 ;
40 return;
41 }
Florin Coras54693d22018-07-17 10:46:29 -070042 if (1 || vcm->debug)
43 {
Florin Coras460dce62018-07-27 05:45:06 -070044 usleep (1e5);
Florin Coras54693d22018-07-17 10:46:29 -070045 return;
46 }
47 if (signal (SIGSEGV, sigsegv_signal))
48 {
49 perror ("signal()");
50 return;
51 }
52 not_ready = 0;
53
54again:
55 test = *(u8 *) mem;
56 if (not_ready)
57 {
58 not_ready = 0;
59 usleep (1);
60 goto again;
61 }
62
63 signal (SIGSEGV, SIG_DFL);
64}
65
Dave Wallace543852a2017-08-03 02:11:34 -040066static const char *
67vppcom_app_state_str (app_state_t state)
68{
69 char *st;
70
71 switch (state)
72 {
73 case STATE_APP_START:
74 st = "STATE_APP_START";
75 break;
76
77 case STATE_APP_CONN_VPP:
78 st = "STATE_APP_CONN_VPP";
79 break;
80
81 case STATE_APP_ENABLED:
82 st = "STATE_APP_ENABLED";
83 break;
84
85 case STATE_APP_ATTACHED:
86 st = "STATE_APP_ATTACHED";
87 break;
88
89 default:
90 st = "UNKNOWN_APP_STATE";
91 break;
92 }
93
94 return st;
95}
96
Florin Coras697faea2018-06-27 17:10:49 -070097const char *
Dave Wallace543852a2017-08-03 02:11:34 -040098vppcom_session_state_str (session_state_t state)
99{
100 char *st;
101
102 switch (state)
103 {
104 case STATE_START:
105 st = "STATE_START";
106 break;
107
108 case STATE_CONNECT:
109 st = "STATE_CONNECT";
110 break;
111
112 case STATE_LISTEN:
113 st = "STATE_LISTEN";
114 break;
115
116 case STATE_ACCEPT:
117 st = "STATE_ACCEPT";
118 break;
119
Dave Wallace4878cbe2017-11-21 03:45:09 -0500120 case STATE_CLOSE_ON_EMPTY:
121 st = "STATE_CLOSE_ON_EMPTY";
122 break;
123
Dave Wallace543852a2017-08-03 02:11:34 -0400124 case STATE_DISCONNECT:
125 st = "STATE_DISCONNECT";
126 break;
127
128 case STATE_FAILED:
129 st = "STATE_FAILED";
130 break;
131
132 default:
133 st = "UNKNOWN_STATE";
134 break;
135 }
136
137 return st;
138}
139
Dave Wallace543852a2017-08-03 02:11:34 -0400140u8 *
141format_ip4_address (u8 * s, va_list * args)
142{
143 u8 *a = va_arg (*args, u8 *);
144 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
145}
146
147u8 *
148format_ip6_address (u8 * s, va_list * args)
149{
150 ip6_address_t *a = va_arg (*args, ip6_address_t *);
151 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
152
153 i_max_n_zero = ARRAY_LEN (a->as_u16);
154 max_n_zeros = 0;
155 i_first_zero = i_max_n_zero;
156 n_zeros = 0;
157 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
158 {
159 u32 is_zero = a->as_u16[i] == 0;
160 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
161 {
162 i_first_zero = i;
163 n_zeros = 0;
164 }
165 n_zeros += is_zero;
166 if ((!is_zero && n_zeros > max_n_zeros)
167 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
168 {
169 i_max_n_zero = i_first_zero;
170 max_n_zeros = n_zeros;
171 i_first_zero = ARRAY_LEN (a->as_u16);
172 n_zeros = 0;
173 }
174 }
175
176 last_double_colon = 0;
177 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
178 {
179 if (i == i_max_n_zero && max_n_zeros > 1)
180 {
181 s = format (s, "::");
182 i += max_n_zeros - 1;
183 last_double_colon = 1;
184 }
185 else
186 {
187 s = format (s, "%s%x",
188 (last_double_colon || i == 0) ? "" : ":",
189 clib_net_to_host_u16 (a->as_u16[i]));
190 last_double_colon = 0;
191 }
192 }
193
194 return s;
195}
196
197/* Format an IP46 address. */
198u8 *
199format_ip46_address (u8 * s, va_list * args)
200{
201 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
202 ip46_type_t type = va_arg (*args, ip46_type_t);
203 int is_ip4 = 1;
204
205 switch (type)
206 {
207 case IP46_TYPE_ANY:
208 is_ip4 = ip46_address_is_ip4 (ip46);
209 break;
210 case IP46_TYPE_IP4:
211 is_ip4 = 1;
212 break;
213 case IP46_TYPE_IP6:
214 is_ip4 = 0;
215 break;
216 }
217
218 return is_ip4 ?
219 format (s, "%U", format_ip4_address, &ip46->ip4) :
220 format (s, "%U", format_ip6_address, &ip46->ip6);
221}
222
Florin Coras697faea2018-06-27 17:10:49 -0700223/*
224 * VPPCOM Utility Functions
225 */
226
227static inline void
228vppcom_session_table_del_listener (u64 listener_handle)
Dave Wallace543852a2017-08-03 02:11:34 -0400229{
Florin Coras697faea2018-06-27 17:10:49 -0700230 listener_handle |= 1ULL << 63;
231 hash_unset (vcm->session_index_by_vpp_handles, listener_handle);
232}
233
234static inline int
235vppcom_wait_for_app_state_change (app_state_t app_state)
236{
237 f64 timeout = clib_time_now (&vcm->clib_time) + vcm->cfg.app_timeout;
238
239 while (clib_time_now (&vcm->clib_time) < timeout)
240 {
241 if (vcm->app_state == app_state)
242 return VPPCOM_OK;
243 }
244 VDBG (0, "VCL<%d>: timeout waiting for state %s (%d)", getpid (),
245 vppcom_app_state_str (app_state), app_state);
246 vcl_evt (VCL_EVT_SESSION_TIMEOUT, vcm, app_state);
247
248 return VPPCOM_ETIMEDOUT;
249}
250
Florin Corasc9fbd662018-08-24 12:59:56 -0700251static svm_msg_q_t *
252vcl_session_vpp_evt_q (vcl_session_t * s)
253{
254 if (vcl_session_is_ct (s))
255 return vcm->vpp_event_queues[0];
256 else
257 return vcm->vpp_event_queues[s->tx_fifo->master_thread_index];
258}
259
Florin Coras54693d22018-07-17 10:46:29 -0700260static void
261vcl_send_session_accepted_reply (svm_msg_q_t * mq, u32 context,
262 session_handle_t handle, int retval)
263{
264 app_session_evt_t _app_evt, *app_evt = &_app_evt;
265 session_accepted_reply_msg_t *rmp;
266 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_ACCEPTED_REPLY);
267 rmp = (session_accepted_reply_msg_t *) app_evt->evt->data;
268 rmp->handle = handle;
269 rmp->context = context;
270 rmp->retval = retval;
271 app_send_ctrl_evt_to_vpp (mq, app_evt);
272}
273
Florin Coras99368312018-08-02 10:45:44 -0700274static void
275vcl_send_session_disconnected_reply (svm_msg_q_t * mq, u32 context,
276 session_handle_t handle, int retval)
277{
278 app_session_evt_t _app_evt, *app_evt = &_app_evt;
279 session_disconnected_reply_msg_t *rmp;
280 app_alloc_ctrl_evt_to_vpp (mq, app_evt,
281 SESSION_CTRL_EVT_DISCONNECTED_REPLY);
282 rmp = (session_disconnected_reply_msg_t *) app_evt->evt->data;
283 rmp->handle = handle;
284 rmp->context = context;
285 rmp->retval = retval;
286 app_send_ctrl_evt_to_vpp (mq, app_evt);
287}
288
Florin Corasc9fbd662018-08-24 12:59:56 -0700289static void
290vcl_send_session_reset_reply (svm_msg_q_t * mq, u32 context,
291 session_handle_t handle, int retval)
292{
293 app_session_evt_t _app_evt, *app_evt = &_app_evt;
294 session_reset_reply_msg_t *rmp;
295 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_RESET_REPLY);
296 rmp = (session_reset_reply_msg_t *) app_evt->evt->data;
297 rmp->handle = handle;
298 rmp->context = context;
299 rmp->retval = retval;
300 app_send_ctrl_evt_to_vpp (mq, app_evt);
301}
302
Florin Coras54693d22018-07-17 10:46:29 -0700303static u32
304vcl_session_accepted_handler (session_accepted_msg_t * mp)
305{
306 vcl_session_t *session, *listen_session;
307 svm_fifo_t *rx_fifo, *tx_fifo;
Florin Coras99368312018-08-02 10:45:44 -0700308 u32 session_index, vpp_wrk_index;
309 svm_msg_q_t *evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700310
Florin Coras99368312018-08-02 10:45:44 -0700311 session = vcl_session_alloc ();
312 session_index = vcl_session_index (session);
313
Florin Coras54693d22018-07-17 10:46:29 -0700314 listen_session = vppcom_session_table_lookup_listener (mp->listener_handle);
315 if (!listen_session)
316 {
317 svm_msg_q_t *evt_q;
318 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
319 clib_warning ("VCL<%d>: ERROR: couldn't find listen session: "
320 "unknown vpp listener handle %llx",
321 getpid (), mp->listener_handle);
322 vcl_send_session_accepted_reply (evt_q, mp->context, mp->handle,
323 VNET_API_ERROR_INVALID_ARGUMENT);
Florin Coras99368312018-08-02 10:45:44 -0700324 vcl_session_free (session);
Florin Coras54693d22018-07-17 10:46:29 -0700325 return VCL_INVALID_SESSION_INDEX;
326 }
327
Florin Coras54693d22018-07-17 10:46:29 -0700328 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
329 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
330
331 if (mp->server_event_queue_address)
332 {
333 session->vpp_evt_q = uword_to_pointer (mp->client_event_queue_address,
334 svm_msg_q_t *);
335 session->our_evt_q = uword_to_pointer (mp->server_event_queue_address,
336 svm_msg_q_t *);
337 vcl_wait_for_memory (session->vpp_evt_q);
Florin Coras54693d22018-07-17 10:46:29 -0700338 rx_fifo->master_session_index = session_index;
339 tx_fifo->master_session_index = session_index;
Florin Coras99368312018-08-02 10:45:44 -0700340 vec_validate (vcm->vpp_event_queues, 0);
341 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
342 vcm->vpp_event_queues[0] = evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700343 }
344 else
345 {
346 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
347 svm_msg_q_t *);
348 rx_fifo->client_session_index = session_index;
349 tx_fifo->client_session_index = session_index;
Florin Coras99368312018-08-02 10:45:44 -0700350
351 vpp_wrk_index = tx_fifo->master_thread_index;
352 vec_validate (vcm->vpp_event_queues, vpp_wrk_index);
353 vcm->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700354 }
355
356 session->vpp_handle = mp->handle;
357 session->client_context = mp->context;
358 session->rx_fifo = rx_fifo;
359 session->tx_fifo = tx_fifo;
360
361 session->session_state = STATE_ACCEPT;
362 session->transport.rmt_port = mp->port;
363 session->transport.is_ip4 = mp->is_ip4;
364 clib_memcpy (&session->transport.rmt_ip, mp->ip, sizeof (ip46_address_t));
365
366 hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
367 session->transport.lcl_port = listen_session->transport.lcl_port;
368 session->transport.lcl_ip = listen_session->transport.lcl_ip;
Florin Coras460dce62018-07-27 05:45:06 -0700369 session->session_type = listen_session->session_type;
370 session->is_dgram = session->session_type == VPPCOM_PROTO_UDP;
Florin Coras54693d22018-07-17 10:46:29 -0700371
372 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: client accept request from %s"
373 " address %U port %d queue %p!", getpid (), mp->handle, session_index,
374 mp->is_ip4 ? "IPv4" : "IPv6", format_ip46_address, &mp->ip,
375 mp->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
376 clib_net_to_host_u16 (mp->port), session->vpp_evt_q);
377 vcl_evt (VCL_EVT_ACCEPT, session, listen_session, session_index);
378
Florin Coras54693d22018-07-17 10:46:29 -0700379 return session_index;
380}
381
382static u32
383vcl_session_connected_handler (session_connected_msg_t * mp)
384{
Florin Coras99368312018-08-02 10:45:44 -0700385 u32 session_index, vpp_wrk_index;
Florin Coras54693d22018-07-17 10:46:29 -0700386 svm_fifo_t *rx_fifo, *tx_fifo;
Florin Coras99368312018-08-02 10:45:44 -0700387 vcl_session_t *session = 0;
388 svm_msg_q_t *evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700389
390 session_index = mp->context;
Florin Coras070453d2018-08-24 17:04:27 -0700391 session = vcl_session_get (session_index);
392 if (!session)
393 {
394 clib_warning ("[%s] ERROR: vpp handle 0x%llx, sid %u: "
395 "Invalid session index (%u)!",
396 getpid (), mp->handle, session_index);
397 return VCL_INVALID_SESSION_INDEX;
398 }
Florin Coras54693d22018-07-17 10:46:29 -0700399 if (mp->retval)
400 {
Florin Coras070453d2018-08-24 17:04:27 -0700401 clib_warning ("VCL<%d>: ERROR: sid %u: connect failed! %U", getpid (),
402 mp->handle, session_index, format_api_error,
403 ntohl (mp->retval));
404 session->session_state = STATE_FAILED;
405 session->vpp_handle = mp->handle;
406 return session_index;
Florin Coras54693d22018-07-17 10:46:29 -0700407 }
408
Florin Coras460dce62018-07-27 05:45:06 -0700409 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
410 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
411 vcl_wait_for_memory (rx_fifo);
412 rx_fifo->client_session_index = session_index;
413 tx_fifo->client_session_index = session_index;
414
Florin Coras54693d22018-07-17 10:46:29 -0700415 if (mp->client_event_queue_address)
416 {
417 session->vpp_evt_q = uword_to_pointer (mp->server_event_queue_address,
418 svm_msg_q_t *);
419 session->our_evt_q = uword_to_pointer (mp->client_event_queue_address,
420 svm_msg_q_t *);
Florin Coras99368312018-08-02 10:45:44 -0700421
422 vec_validate (vcm->vpp_event_queues, 0);
423 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
424 vcm->vpp_event_queues[0] = evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700425 }
426 else
Florin Coras99368312018-08-02 10:45:44 -0700427 {
428 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
429 svm_msg_q_t *);
430 vpp_wrk_index = tx_fifo->master_thread_index;
431 vec_validate (vcm->vpp_event_queues, vpp_wrk_index);
432 vcm->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
433 }
Florin Coras54693d22018-07-17 10:46:29 -0700434
Florin Coras54693d22018-07-17 10:46:29 -0700435 session->rx_fifo = rx_fifo;
436 session->tx_fifo = tx_fifo;
437 session->vpp_handle = mp->handle;
438 session->transport.is_ip4 = mp->is_ip4;
439 clib_memcpy (&session->transport.lcl_ip, mp->lcl_ip,
440 sizeof (session->transport.lcl_ip));
441 session->transport.lcl_port = mp->lcl_port;
442 session->session_state = STATE_CONNECT;
443
444 /* Add it to lookup table */
445 hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
446
447 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: connect succeeded! "
448 "session_rx_fifo %p, refcnt %d, session_tx_fifo %p, refcnt %d",
449 getpid (), mp->handle, session_index, session->rx_fifo,
450 session->rx_fifo->refcnt, session->tx_fifo, session->tx_fifo->refcnt);
Florin Coras070453d2018-08-24 17:04:27 -0700451
Florin Coras54693d22018-07-17 10:46:29 -0700452 return session_index;
453}
454
Florin Corasc9fbd662018-08-24 12:59:56 -0700455static u32
Florin Coras60116992018-08-27 09:52:18 -0700456vcl_session_reset_handler (session_reset_msg_t * reset_msg)
Florin Corasc9fbd662018-08-24 12:59:56 -0700457{
458 vcl_session_t *session;
459 u32 sid;
460
461 sid = vcl_session_get_index_from_handle (reset_msg->handle);
462 session = vcl_session_get (sid);
463 if (!session)
464 {
465 VDBG (0, "request to reset unknown handle 0x%llx", reset_msg->handle);
466 return VCL_INVALID_SESSION_INDEX;
467 }
468 session->session_state = STATE_CLOSE_ON_EMPTY;
469 VDBG (0, "reset handle 0x%llx, sid %u ", reset_msg->handle, sid);
470 vcl_send_session_reset_reply (vcl_session_vpp_evt_q (session),
471 vcm->my_client_index, reset_msg->handle, 0);
472 return sid;
473}
474
Florin Coras60116992018-08-27 09:52:18 -0700475static u32
476vcl_session_bound_handler (session_bound_msg_t * mp)
477{
478 vcl_session_t *session;
479 u32 sid = mp->context;
480
481 session = vcl_session_get (sid);
482 if (mp->retval)
483 {
484 VDBG (0, "VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: bind failed: %U",
485 getpid (), mp->handle, sid, format_api_error, ntohl (mp->retval));
486 if (session)
487 {
488 session->session_state = STATE_FAILED;
489 session->vpp_handle = mp->handle;
490 return sid;
491 }
492 else
493 {
494 clib_warning ("[%s] ERROR: vpp handle 0x%llx, sid %u: "
495 "Invalid session index (%u)!",
496 getpid (), mp->handle, sid);
497 return VCL_INVALID_SESSION_INDEX;
498 }
499 }
500
501 session->vpp_handle = mp->handle;
502 session->transport.is_ip4 = mp->lcl_is_ip4;
503 clib_memcpy (&session->transport.lcl_ip, mp->lcl_ip,
504 sizeof (ip46_address_t));
505 session->transport.lcl_port = mp->lcl_port;
506 vppcom_session_table_add_listener (mp->handle, sid);
507 session->session_state = STATE_LISTEN;
508
509 if (session->is_dgram)
510 {
511 svm_fifo_t *rx_fifo, *tx_fifo;
512 session->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
513 rx_fifo = uword_to_pointer (mp->rx_fifo, svm_fifo_t *);
514 rx_fifo->client_session_index = sid;
515 tx_fifo = uword_to_pointer (mp->tx_fifo, svm_fifo_t *);
516 tx_fifo->client_session_index = sid;
517 session->rx_fifo = rx_fifo;
518 session->tx_fifo = tx_fifo;
519 }
520
521 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: bind succeeded!",
522 getpid (), mp->handle, sid);
523 return sid;
524}
525
Florin Coras54693d22018-07-17 10:46:29 -0700526int
527vcl_handle_mq_ctrl_event (session_event_t * e)
528{
529 session_accepted_msg_t *accepted_msg;
530 session_disconnected_msg_t *disconnected_msg;
531 vcl_session_msg_t *vcl_msg;
532 vcl_session_t *session;
533 u64 handle;
534 u32 sid;
535
536 switch (e->event_type)
537 {
538 case FIFO_EVENT_APP_RX:
539 clib_warning ("unhandled rx: sid %u (0x%x)",
540 e->fifo->client_session_index,
541 e->fifo->client_session_index);
542 break;
543 case SESSION_CTRL_EVT_ACCEPTED:
544 accepted_msg = (session_accepted_msg_t *) e->data;
545 handle = accepted_msg->listener_handle;
546 session = vppcom_session_table_lookup_listener (handle);
547 if (!session)
548 {
549 clib_warning ("VCL<%d>: ERROR: couldn't find listen session:"
550 "listener handle %llx", getpid (), handle);
551 break;
552 }
553
554 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
555 vcl_msg->accepted_msg = *accepted_msg;
556 break;
557 case SESSION_CTRL_EVT_CONNECTED:
558 vcl_session_connected_handler ((session_connected_msg_t *) e->data);
559 break;
560 case SESSION_CTRL_EVT_DISCONNECTED:
561 disconnected_msg = (session_disconnected_msg_t *) e->data;
562 sid = vcl_session_get_index_from_handle (disconnected_msg->handle);
563 session = vcl_session_get (sid);
Florin Corasc9fbd662018-08-24 12:59:56 -0700564 if (!session)
565 {
566 VDBG (0, "request to disconnect unknown handle 0x%llx",
567 disconnected_msg->handle);
568 break;
569 }
Florin Coras54693d22018-07-17 10:46:29 -0700570 session->session_state = STATE_DISCONNECT;
Florin Corasc9fbd662018-08-24 12:59:56 -0700571 VDBG (0, "disconnected handle 0xllx, sid %u", disconnected_msg->handle,
572 sid);
573 break;
574 case SESSION_CTRL_EVT_RESET:
Florin Coras60116992018-08-27 09:52:18 -0700575 vcl_session_reset_handler ((session_reset_msg_t *) e->data);
576 break;
577 case SESSION_CTRL_EVT_BOUND:
578 vcl_session_bound_handler ((session_bound_msg_t *) e->data);
Florin Coras54693d22018-07-17 10:46:29 -0700579 break;
580 default:
581 clib_warning ("unhandled %u", e->event_type);
582 }
583 return VPPCOM_OK;
584}
585
Florin Coras697faea2018-06-27 17:10:49 -0700586static inline int
587vppcom_wait_for_session_state_change (u32 session_index,
588 session_state_t state,
589 f64 wait_for_time)
590{
591 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
592 vcl_session_t *volatile session;
Florin Coras54693d22018-07-17 10:46:29 -0700593 svm_msg_q_msg_t msg;
594 session_event_t *e;
Dave Wallace543852a2017-08-03 02:11:34 -0400595
Florin Coras697faea2018-06-27 17:10:49 -0700596 do
Dave Wallace543852a2017-08-03 02:11:34 -0400597 {
Florin Coras070453d2018-08-24 17:04:27 -0700598 session = vcl_session_get (session_index);
599 if (PREDICT_FALSE (!session))
Florin Coras697faea2018-06-27 17:10:49 -0700600 {
Florin Coras070453d2018-08-24 17:04:27 -0700601 return VPPCOM_EBADFD;
Florin Coras697faea2018-06-27 17:10:49 -0700602 }
603 if (session->session_state & state)
604 {
Florin Coras697faea2018-06-27 17:10:49 -0700605 return VPPCOM_OK;
606 }
607 if (session->session_state & STATE_FAILED)
608 {
Florin Coras697faea2018-06-27 17:10:49 -0700609 return VPPCOM_ECONNREFUSED;
610 }
Florin Coras54693d22018-07-17 10:46:29 -0700611
612 if (svm_msg_q_sub (vcm->app_event_queue, &msg, SVM_Q_NOWAIT, 0))
613 continue;
614 e = svm_msg_q_msg_data (vcm->app_event_queue, &msg);
615 vcl_handle_mq_ctrl_event (e);
616 svm_msg_q_free_msg (vcm->app_event_queue, &msg);
Florin Corasdcf55ce2017-11-16 15:32:50 -0800617 }
Florin Coras697faea2018-06-27 17:10:49 -0700618 while (clib_time_now (&vcm->clib_time) < timeout);
Florin Corasdcf55ce2017-11-16 15:32:50 -0800619
Florin Coras697faea2018-06-27 17:10:49 -0700620 VDBG (0, "VCL<%d>: timeout waiting for state 0x%x (%s)", getpid (), state,
621 vppcom_session_state_str (state));
622 vcl_evt (VCL_EVT_SESSION_TIMEOUT, session, session_state);
Dave Wallace543852a2017-08-03 02:11:34 -0400623
Florin Coras697faea2018-06-27 17:10:49 -0700624 return VPPCOM_ETIMEDOUT;
Dave Wallace60caa062017-11-10 17:07:13 -0500625}
626
Florin Coras697faea2018-06-27 17:10:49 -0700627static int
628vppcom_app_session_enable (void)
Dave Wallace543852a2017-08-03 02:11:34 -0400629{
Florin Coras697faea2018-06-27 17:10:49 -0700630 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -0400631
Florin Coras697faea2018-06-27 17:10:49 -0700632 if (vcm->app_state != STATE_APP_ENABLED)
633 {
634 vppcom_send_session_enable_disable (1 /* is_enabled == TRUE */ );
635 rv = vppcom_wait_for_app_state_change (STATE_APP_ENABLED);
636 if (PREDICT_FALSE (rv))
637 {
638 VDBG (0, "VCL<%d>: application session enable timed out! "
639 "returning %d (%s)", getpid (), rv, vppcom_retval_str (rv));
640 return rv;
641 }
642 }
643 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400644}
645
Florin Coras697faea2018-06-27 17:10:49 -0700646static int
647vppcom_app_attach (void)
Dave Wallace543852a2017-08-03 02:11:34 -0400648{
Florin Coras697faea2018-06-27 17:10:49 -0700649 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -0400650
Florin Coras697faea2018-06-27 17:10:49 -0700651 vppcom_app_send_attach ();
652 rv = vppcom_wait_for_app_state_change (STATE_APP_ATTACHED);
653 if (PREDICT_FALSE (rv))
654 {
655 VDBG (0, "VCL<%d>: application attach timed out! returning %d (%s)",
656 getpid (), rv, vppcom_retval_str (rv));
657 return rv;
658 }
Dave Wallace543852a2017-08-03 02:11:34 -0400659
Florin Coras697faea2018-06-27 17:10:49 -0700660 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400661}
662
663static int
Dave Wallace543852a2017-08-03 02:11:34 -0400664vppcom_session_unbind (u32 session_index)
665{
Florin Coras7e12d942018-06-27 14:32:43 -0700666 vcl_session_t *session = 0;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500667 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400668
Florin Coras070453d2018-08-24 17:04:27 -0700669 session = vcl_session_get (session_index);
670 if (!session)
671 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500672
673 vpp_handle = session->vpp_handle;
674 vppcom_session_table_del_listener (vpp_handle);
675 session->vpp_handle = ~0;
Florin Coras7e12d942018-06-27 14:32:43 -0700676 session->session_state = STATE_DISCONNECT;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500677
Florin Coras0d427d82018-06-27 03:24:07 -0700678 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending unbind msg! new state"
679 " 0x%x (%s)", getpid (), vpp_handle, session_index, STATE_DISCONNECT,
680 vppcom_session_state_str (STATE_DISCONNECT));
681 vcl_evt (VCL_EVT_UNBIND, session);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500682 vppcom_send_unbind_sock (vpp_handle);
683
Florin Coras070453d2018-08-24 17:04:27 -0700684 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400685}
686
Florin Coras697faea2018-06-27 17:10:49 -0700687static int
Dave Wallace543852a2017-08-03 02:11:34 -0400688vppcom_session_disconnect (u32 session_index)
689{
Florin Coras99368312018-08-02 10:45:44 -0700690 svm_msg_q_t *vpp_evt_q;
Florin Coras7e12d942018-06-27 14:32:43 -0700691 vcl_session_t *session;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500692 session_state_t state;
Florin Coras99368312018-08-02 10:45:44 -0700693 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400694
Florin Coras070453d2018-08-24 17:04:27 -0700695 session = vcl_session_get (session_index);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500696 vpp_handle = session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -0700697 state = session->session_state;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500698
Florin Coras0d427d82018-06-27 03:24:07 -0700699 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u state 0x%x (%s)", getpid (),
700 vpp_handle, session_index, state, vppcom_session_state_str (state));
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400701
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800702 if (PREDICT_FALSE (state & STATE_LISTEN))
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400703 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500704 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -0500705 "Cannot disconnect a listen socket!",
706 getpid (), vpp_handle, session_index);
Florin Coras070453d2018-08-24 17:04:27 -0700707 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500708 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400709
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800710 if (state & STATE_CLOSE_ON_EMPTY)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500711 {
Florin Coras99368312018-08-02 10:45:44 -0700712 vpp_evt_q = vcl_session_vpp_evt_q (session);
713 vcl_send_session_disconnected_reply (vpp_evt_q, vcm->my_client_index,
714 vpp_handle, 0);
Florin Coras0d427d82018-06-27 03:24:07 -0700715 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect "
716 "REPLY...", getpid (), vpp_handle, session_index);
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400717 }
718 else
Dave Wallace227867f2017-11-13 21:21:53 -0500719 {
Florin Coras0d427d82018-06-27 03:24:07 -0700720 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect...",
721 getpid (), vpp_handle, session_index);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800722 vppcom_send_disconnect_session (vpp_handle, session_index);
Dave Wallace227867f2017-11-13 21:21:53 -0500723 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400724
Florin Coras070453d2018-08-24 17:04:27 -0700725 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400726}
727
Dave Wallace543852a2017-08-03 02:11:34 -0400728/*
729 * VPPCOM Public API functions
730 */
731int
732vppcom_app_create (char *app_name)
733{
Dave Wallace543852a2017-08-03 02:11:34 -0400734 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
Dave Wallace543852a2017-08-03 02:11:34 -0400735 int rv;
736
737 if (!vcm->init)
738 {
Dave Wallace543852a2017-08-03 02:11:34 -0400739 vcm->init = 1;
Dave Barach6a5adc32018-07-04 10:56:23 -0400740 vppcom_cfg (&vcm->cfg);
Florin Coras99368312018-08-02 10:45:44 -0700741 vcl_cfg = &vcm->cfg;
742
743 vcm->mqs_epfd = -1;
744 if (vcl_cfg->use_mq_eventfd)
745 vcm->mqs_epfd = epoll_create (1);
Dave Barach6a5adc32018-07-04 10:56:23 -0400746
Dave Wallace543852a2017-08-03 02:11:34 -0400747 vcm->main_cpu = os_get_thread_index ();
Dave Wallace543852a2017-08-03 02:11:34 -0400748 vcm->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
Florin Coras99368312018-08-02 10:45:44 -0700749 vcm->ct_registration_by_mq = hash_create (0, sizeof (uword));
750 clib_spinlock_init (&vcm->ct_registration_lock);
Dave Wallace543852a2017-08-03 02:11:34 -0400751
752 clib_time_init (&vcm->clib_time);
753 vppcom_init_error_string_table ();
Florin Corasa332c462018-01-31 06:52:17 -0800754 svm_fifo_segment_main_init (vcl_cfg->segment_baseva,
755 20 /* timeout in secs */ );
Florin Coras99368312018-08-02 10:45:44 -0700756 vec_validate (vcm->mq_events, 64);
757 vec_validate (vcm->mq_msg_vector, 128);
758 vec_reset_length (vcm->mq_msg_vector);
Dave Wallace543852a2017-08-03 02:11:34 -0400759 }
760
761 if (vcm->my_client_index == ~0)
762 {
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800763 /* API hookup and connect to VPP */
Dave Wallace048b1d62018-01-03 22:24:41 -0500764 vppcom_api_hookup ();
Florin Coras0d427d82018-06-27 03:24:07 -0700765 vcl_elog_init (vcm);
Dave Wallace543852a2017-08-03 02:11:34 -0400766 vcm->app_state = STATE_APP_START;
767 rv = vppcom_connect_to_vpp (app_name);
768 if (rv)
769 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500770 clib_warning ("VCL<%d>: ERROR: couldn't connect to VPP!",
Dave Wallace2e005bb2017-11-07 01:21:39 -0500771 getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -0400772 return rv;
773 }
774
Florin Coras0d427d82018-06-27 03:24:07 -0700775 VDBG (0, "VCL<%d>: sending session enable", getpid ());
Dave Wallace048b1d62018-01-03 22:24:41 -0500776 rv = vppcom_app_session_enable ();
Dave Wallace543852a2017-08-03 02:11:34 -0400777 if (rv)
778 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500779 clib_warning ("VCL<%d>: ERROR: vppcom_app_session_enable() "
780 "failed!", getpid ());
Dave Wallace543852a2017-08-03 02:11:34 -0400781 return rv;
782 }
Dave Wallace543852a2017-08-03 02:11:34 -0400783
Florin Coras0d427d82018-06-27 03:24:07 -0700784 VDBG (0, "VCL<%d>: sending app attach", getpid ());
Dave Wallace048b1d62018-01-03 22:24:41 -0500785 rv = vppcom_app_attach ();
786 if (rv)
787 {
788 clib_warning ("VCL<%d>: ERROR: vppcom_app_attach() failed!",
789 getpid ());
790 return rv;
791 }
792
Florin Coras0d427d82018-06-27 03:24:07 -0700793 VDBG (0, "VCL<%d>: app_name '%s', my_client_index %d (0x%x)",
794 getpid (), app_name, vcm->my_client_index, vcm->my_client_index);
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400795 }
Dave Wallace543852a2017-08-03 02:11:34 -0400796
797 return VPPCOM_OK;
798}
799
800void
801vppcom_app_destroy (void)
802{
Dave Wallace543852a2017-08-03 02:11:34 -0400803 int rv;
Dave Wallacede910062018-03-20 09:22:13 -0400804 f64 orig_app_timeout;
Dave Wallace543852a2017-08-03 02:11:34 -0400805
806 if (vcm->my_client_index == ~0)
807 return;
808
Florin Coras0d427d82018-06-27 03:24:07 -0700809 VDBG (0, "VCL<%d>: detaching from VPP, my_client_index %d (0x%x)",
810 getpid (), vcm->my_client_index, vcm->my_client_index);
811 vcl_evt (VCL_EVT_DETACH, vcm);
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -0800812
Florin Coras697faea2018-06-27 17:10:49 -0700813 vppcom_app_send_detach ();
Dave Wallacede910062018-03-20 09:22:13 -0400814 orig_app_timeout = vcm->cfg.app_timeout;
815 vcm->cfg.app_timeout = 2.0;
Dave Wallace543852a2017-08-03 02:11:34 -0400816 rv = vppcom_wait_for_app_state_change (STATE_APP_ENABLED);
Dave Wallacede910062018-03-20 09:22:13 -0400817 vcm->cfg.app_timeout = orig_app_timeout;
Dave Wallace543852a2017-08-03 02:11:34 -0400818 if (PREDICT_FALSE (rv))
Florin Coras0d427d82018-06-27 03:24:07 -0700819 VDBG (0, "VCL<%d>: application detach timed out! returning %d (%s)",
820 getpid (), rv, vppcom_retval_str (rv));
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -0800821
Florin Coras0d427d82018-06-27 03:24:07 -0700822 vcl_elog_stop (vcm);
Dave Wallace543852a2017-08-03 02:11:34 -0400823 vl_client_disconnect_from_vlib ();
824 vcm->my_client_index = ~0;
825 vcm->app_state = STATE_APP_START;
826}
827
828int
Dave Wallacec04cbf12018-02-07 18:14:02 -0500829vppcom_session_create (u8 proto, u8 is_nonblocking)
Dave Wallace543852a2017-08-03 02:11:34 -0400830{
Florin Coras7e12d942018-06-27 14:32:43 -0700831 vcl_session_t *session;
Dave Wallace543852a2017-08-03 02:11:34 -0400832 u32 session_index;
833
Dave Wallace543852a2017-08-03 02:11:34 -0400834 pool_get (vcm->sessions, session);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400835 memset (session, 0, sizeof (*session));
Dave Wallace543852a2017-08-03 02:11:34 -0400836 session_index = session - vcm->sessions;
837
Florin Coras7e12d942018-06-27 14:32:43 -0700838 session->session_type = proto;
839 session->session_state = STATE_START;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500840 session->vpp_handle = ~0;
Florin Coras460dce62018-07-27 05:45:06 -0700841 session->is_dgram = proto == VPPCOM_PROTO_UDP;
Dave Wallace543852a2017-08-03 02:11:34 -0400842
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800843 if (is_nonblocking)
844 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
Dave Wallace543852a2017-08-03 02:11:34 -0400845
Florin Coras7e12d942018-06-27 14:32:43 -0700846 vcl_evt (VCL_EVT_CREATE, session, session_type, session->session_state,
847 is_nonblocking, session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -0800848
Florin Coras0d427d82018-06-27 03:24:07 -0700849 VDBG (0, "VCL<%d>: sid %u", getpid (), session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -0800850
Dave Wallace543852a2017-08-03 02:11:34 -0400851 return (int) session_index;
852}
853
854int
855vppcom_session_close (uint32_t session_index)
856{
Florin Coras7e12d942018-06-27 14:32:43 -0700857 vcl_session_t *session = 0;
Florin Coras070453d2018-08-24 17:04:27 -0700858 int rv = VPPCOM_OK;
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400859 u8 is_vep;
860 u8 is_vep_session;
861 u32 next_sid;
862 u32 vep_idx;
Dave Wallaceee45d412017-11-24 21:44:06 -0500863 u64 vpp_handle;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500864 uword *p;
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400865 session_state_t state;
Dave Wallace543852a2017-08-03 02:11:34 -0400866
Florin Coras070453d2018-08-24 17:04:27 -0700867 session = vcl_session_get (session_index);
868 if (!session)
869 return VPPCOM_EBADFD;
870
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400871 is_vep = session->is_vep;
872 is_vep_session = session->is_vep_session;
873 next_sid = session->vep.next_sid;
874 vep_idx = session->vep.vep_idx;
Florin Coras7e12d942018-06-27 14:32:43 -0700875 state = session->session_state;
Dave Wallaceee45d412017-11-24 21:44:06 -0500876 vpp_handle = session->vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400877
878 if (VPPCOM_DEBUG > 0)
Dave Wallaceee45d412017-11-24 21:44:06 -0500879 {
880 if (is_vep)
Dave Wallace048b1d62018-01-03 22:24:41 -0500881 clib_warning ("VCL<%d>: vep_idx %u / sid %u: "
882 "closing epoll session...",
Dave Wallaceee45d412017-11-24 21:44:06 -0500883 getpid (), session_index, session_index);
884 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500885 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %d: "
886 "closing session...",
Dave Wallaceee45d412017-11-24 21:44:06 -0500887 getpid (), vpp_handle, session_index);
888 }
Dave Wallace543852a2017-08-03 02:11:34 -0400889
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400890 if (is_vep)
Dave Wallace543852a2017-08-03 02:11:34 -0400891 {
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400892 while (next_sid != ~0)
Dave Wallace19481612017-09-15 18:47:44 -0400893 {
Dave Wallacef7f809c2017-10-03 01:48:42 -0400894 rv = vppcom_epoll_ctl (session_index, EPOLL_CTL_DEL, next_sid, 0);
Florin Coras0d427d82018-06-27 03:24:07 -0700895 if (PREDICT_FALSE (rv < 0))
896 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL "
897 "vep_idx %u failed! rv %d (%s)",
898 getpid (), vpp_handle, next_sid, vep_idx,
899 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -0400900
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400901 next_sid = session->vep.next_sid;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400902 }
903 }
904 else
905 {
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400906 if (is_vep_session)
Dave Wallacef7f809c2017-10-03 01:48:42 -0400907 {
Dave Wallacef7f809c2017-10-03 01:48:42 -0400908 rv = vppcom_epoll_ctl (vep_idx, EPOLL_CTL_DEL, session_index, 0);
Florin Coras0d427d82018-06-27 03:24:07 -0700909 if (rv < 0)
910 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL "
911 "vep_idx %u failed! rv %d (%s)",
912 getpid (), vpp_handle, session_index,
913 vep_idx, rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -0400914 }
915
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800916 if (state & STATE_LISTEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -0400917 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800918 rv = vppcom_session_unbind (session_index);
919 if (PREDICT_FALSE (rv < 0))
Florin Coras0d427d82018-06-27 03:24:07 -0700920 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: listener unbind "
921 "failed! rv %d (%s)",
922 getpid (), vpp_handle, session_index,
923 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -0400924 }
Florin Coras070453d2018-08-24 17:04:27 -0700925 else if (state & STATE_OPEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -0400926 {
Dave Wallace4878cbe2017-11-21 03:45:09 -0500927 rv = vppcom_session_disconnect (session_index);
928 if (PREDICT_FALSE (rv < 0))
Dave Wallace048b1d62018-01-03 22:24:41 -0500929 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -0500930 "session disconnect failed! rv %d (%s)",
931 getpid (), vpp_handle, session_index,
932 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -0400933 }
Dave Wallace19481612017-09-15 18:47:44 -0400934 }
Dave Wallace4878cbe2017-11-21 03:45:09 -0500935
Florin Coras99368312018-08-02 10:45:44 -0700936 if (vcl_session_is_ct (session))
937 {
938 vcl_cut_through_registration_t *ctr;
939 uword mq_addr;
940
941 mq_addr = pointer_to_uword (session->our_evt_q);
942 ctr = vcl_ct_registration_lock_and_lookup (mq_addr);
943 ASSERT (ctr);
944 if (ctr->epoll_evt_conn_index != ~0)
945 vcl_mq_epoll_del_evfd (ctr->epoll_evt_conn_index);
946 VDBG (0, "Removing ct registration %u",
947 vcl_ct_registration_index (ctr));
948 vcl_ct_registration_del (ctr);
949 vcl_ct_registration_unlock ();
950 }
Florin Coras54693d22018-07-17 10:46:29 -0700951
Dave Wallaceee45d412017-11-24 21:44:06 -0500952 if (vpp_handle != ~0)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500953 {
Dave Wallaceee45d412017-11-24 21:44:06 -0500954 p = hash_get (vcm->session_index_by_vpp_handles, vpp_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500955 if (p)
Dave Wallaceee45d412017-11-24 21:44:06 -0500956 hash_unset (vcm->session_index_by_vpp_handles, vpp_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500957 }
Florin Coras070453d2018-08-24 17:04:27 -0700958 vcl_session_free (session);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500959
960 if (VPPCOM_DEBUG > 0)
Dave Wallaceee45d412017-11-24 21:44:06 -0500961 {
962 if (is_vep)
Dave Wallace048b1d62018-01-03 22:24:41 -0500963 clib_warning ("VCL<%d>: vep_idx %u / sid %u: epoll session removed.",
Dave Wallaceee45d412017-11-24 21:44:06 -0500964 getpid (), session_index, session_index);
965 else
Dave Wallace048b1d62018-01-03 22:24:41 -0500966 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: session removed.",
Dave Wallaceee45d412017-11-24 21:44:06 -0500967 getpid (), vpp_handle, session_index);
968 }
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -0800969
Florin Coras0d427d82018-06-27 03:24:07 -0700970 vcl_evt (VCL_EVT_CLOSE, session, rv);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -0800971
Dave Wallace543852a2017-08-03 02:11:34 -0400972 return rv;
973}
974
975int
976vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep)
977{
Florin Coras7e12d942018-06-27 14:32:43 -0700978 vcl_session_t *session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -0400979
980 if (!ep || !ep->ip)
981 return VPPCOM_EINVAL;
982
Florin Coras070453d2018-08-24 17:04:27 -0700983 session = vcl_session_get (session_index);
984 if (!session)
985 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -0400986
Dave Wallace9c4b5b22017-10-18 21:15:48 -0400987 if (session->is_vep)
988 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500989 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
990 "bind to an epoll session!", getpid (), session_index);
Florin Coras070453d2018-08-24 17:04:27 -0700991 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -0400992 }
993
Florin Coras7e12d942018-06-27 14:32:43 -0700994 session->transport.is_ip4 = ep->is_ip4;
Florin Coras54693d22018-07-17 10:46:29 -0700995 if (ep->is_ip4)
996 clib_memcpy (&session->transport.lcl_ip.ip4, ep->ip,
997 sizeof (ip4_address_t));
998 else
999 clib_memcpy (&session->transport.lcl_ip.ip6, ep->ip,
1000 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001001 session->transport.lcl_port = ep->port;
Stevenac1f96d2017-10-24 16:03:58 -07001002
Florin Coras0d427d82018-06-27 03:24:07 -07001003 VDBG (0, "VCL<%d>: sid %u: binding to local %s address %U port %u, "
1004 "proto %s", getpid (), session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001005 session->transport.is_ip4 ? "IPv4" : "IPv6",
1006 format_ip46_address, &session->transport.lcl_ip,
1007 session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
1008 clib_net_to_host_u16 (session->transport.lcl_port),
1009 session->session_type ? "UDP" : "TCP");
Florin Coras0d427d82018-06-27 03:24:07 -07001010 vcl_evt (VCL_EVT_BIND, session);
Florin Coras460dce62018-07-27 05:45:06 -07001011
1012 if (session->session_type == VPPCOM_PROTO_UDP)
1013 vppcom_session_listen (session_index, 10);
1014
Florin Coras070453d2018-08-24 17:04:27 -07001015 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001016}
1017
1018int
Dave Wallace33e002b2017-09-06 01:20:02 -04001019vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len)
Dave Wallace543852a2017-08-03 02:11:34 -04001020{
Florin Coras7e12d942018-06-27 14:32:43 -07001021 vcl_session_t *listen_session = 0;
Dave Wallaceee45d412017-11-24 21:44:06 -05001022 u64 listen_vpp_handle;
Florin Coras070453d2018-08-24 17:04:27 -07001023 int rv;
1024
1025 listen_session = vcl_session_get (listen_session_index);
1026 if (!listen_session)
1027 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001028
Keith Burns (alagalah)aba98de2018-02-22 03:23:40 -08001029 if (q_len == 0 || q_len == ~0)
1030 q_len = vcm->cfg.listen_queue_size;
1031
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001032 if (listen_session->is_vep)
1033 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001034 clib_warning ("VCL<%d>: ERROR: sid %u: cannot listen on an "
Dave Wallace4878cbe2017-11-21 03:45:09 -05001035 "epoll session!", getpid (), listen_session_index);
Florin Coras070453d2018-08-24 17:04:27 -07001036 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001037 }
1038
Dave Wallaceee45d412017-11-24 21:44:06 -05001039 listen_vpp_handle = listen_session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -07001040 if (listen_session->session_state & STATE_LISTEN)
Dave Wallacee695cb42017-11-02 22:04:42 -04001041 {
Florin Coras0d427d82018-06-27 03:24:07 -07001042 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: already in listen state!",
1043 getpid (), listen_vpp_handle, listen_session_index);
Florin Coras070453d2018-08-24 17:04:27 -07001044 return VPPCOM_OK;
Dave Wallacee695cb42017-11-02 22:04:42 -04001045 }
1046
Florin Coras0d427d82018-06-27 03:24:07 -07001047 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: sending VPP bind+listen "
1048 "request...", getpid (), listen_vpp_handle, listen_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001049
Florin Coras070453d2018-08-24 17:04:27 -07001050 /*
1051 * Send listen request to vpp and wait for reply
1052 */
Dave Wallace4878cbe2017-11-21 03:45:09 -05001053 vppcom_send_bind_sock (listen_session, listen_session_index);
Florin Coras070453d2018-08-24 17:04:27 -07001054 rv =
1055 vppcom_wait_for_session_state_change (listen_session_index, STATE_LISTEN,
1056 vcm->cfg.session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001057
Florin Coras070453d2018-08-24 17:04:27 -07001058 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001059 {
Florin Coras070453d2018-08-24 17:04:27 -07001060 listen_session = vcl_session_get (listen_session_index);
Florin Coras0d427d82018-06-27 03:24:07 -07001061 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: bind+listen failed! "
1062 "returning %d (%s)", getpid (), listen_session->vpp_handle,
Florin Coras070453d2018-08-24 17:04:27 -07001063 listen_session_index, rv, vppcom_retval_str (rv));
1064 return rv;
Dave Wallaceee45d412017-11-24 21:44:06 -05001065 }
1066
Florin Coras070453d2018-08-24 17:04:27 -07001067 return VPPCOM_OK;
Keith Burns (alagalah)0d2b0d52018-03-06 15:55:22 -08001068}
1069
1070int
Florin Coras7e12d942018-06-27 14:32:43 -07001071validate_args_session_accept_ (vcl_session_t * listen_session)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001072{
1073 u32 listen_session_index = listen_session - vcm->sessions;
1074
1075 /* Input validation - expects spinlock on sessions_lockp */
1076 if (listen_session->is_vep)
1077 {
1078 clib_warning ("VCL<%d>: ERROR: sid %u: cannot accept on an "
1079 "epoll session!", getpid (), listen_session_index);
1080 return VPPCOM_EBADFD;
1081 }
1082
Florin Coras7e12d942018-06-27 14:32:43 -07001083 if (listen_session->session_state != STATE_LISTEN)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001084 {
1085 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
1086 "not in listen state! state 0x%x (%s)", getpid (),
1087 listen_session->vpp_handle, listen_session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001088 listen_session->session_state,
1089 vppcom_session_state_str (listen_session->session_state));
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001090 return VPPCOM_EBADFD;
1091 }
1092 return VPPCOM_OK;
1093}
1094
1095int
Dave Wallace543852a2017-08-03 02:11:34 -04001096vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep,
Dave Wallace048b1d62018-01-03 22:24:41 -05001097 uint32_t flags)
Dave Wallace543852a2017-08-03 02:11:34 -04001098{
Florin Coras54693d22018-07-17 10:46:29 -07001099 session_accepted_msg_t accepted_msg;
Florin Coras7e12d942018-06-27 14:32:43 -07001100 vcl_session_t *listen_session = 0;
1101 vcl_session_t *client_session = 0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001102 u32 client_session_index = ~0;
Florin Coras54693d22018-07-17 10:46:29 -07001103 svm_msg_q_t *vpp_evt_q;
1104 vcl_session_msg_t *evt;
Dave Wallaceee45d412017-11-24 21:44:06 -05001105 u64 listen_vpp_handle;
Florin Coras54693d22018-07-17 10:46:29 -07001106 svm_msg_q_msg_t msg;
1107 session_event_t *e;
1108 u8 is_nonblocking;
1109 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001110
Florin Coras070453d2018-08-24 17:04:27 -07001111 listen_session = vcl_session_get (listen_session_index);
1112 if (!listen_session)
1113 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001114
Florin Coras070453d2018-08-24 17:04:27 -07001115 if ((rv = validate_args_session_accept_ (listen_session)))
1116 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001117
Florin Coras54693d22018-07-17 10:46:29 -07001118 if (clib_fifo_elts (listen_session->accept_evts_fifo))
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001119 {
Florin Coras54693d22018-07-17 10:46:29 -07001120 clib_fifo_sub2 (listen_session->accept_evts_fifo, evt);
1121 accepted_msg = evt->accepted_msg;
1122 goto handle;
1123 }
1124
1125 is_nonblocking = VCL_SESS_ATTR_TEST (listen_session->attr,
1126 VCL_SESS_ATTR_NONBLOCK);
1127 if (svm_msg_q_is_empty (vcm->app_event_queue) && is_nonblocking)
1128 return VPPCOM_EAGAIN;
1129
1130 while (1)
1131 {
1132 if (svm_msg_q_sub (vcm->app_event_queue, &msg, SVM_Q_WAIT, 0))
1133 return VPPCOM_EAGAIN;
1134
1135 e = svm_msg_q_msg_data (vcm->app_event_queue, &msg);
1136 if (e->event_type != SESSION_CTRL_EVT_ACCEPTED)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001137 {
Florin Coras54693d22018-07-17 10:46:29 -07001138 clib_warning ("discarded event: %u", e->event_type);
1139 svm_msg_q_free_msg (vcm->app_event_queue, &msg);
1140 continue;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001141 }
Florin Coras54693d22018-07-17 10:46:29 -07001142 clib_memcpy (&accepted_msg, e->data, sizeof (accepted_msg));
1143 svm_msg_q_free_msg (vcm->app_event_queue, &msg);
1144 break;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001145 }
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001146
Florin Coras54693d22018-07-17 10:46:29 -07001147handle:
Keith Burns (alagalah)00f44cc2018-03-07 09:26:38 -08001148
Florin Coras54693d22018-07-17 10:46:29 -07001149 client_session_index = vcl_session_accepted_handler (&accepted_msg);
Florin Coras99368312018-08-02 10:45:44 -07001150 listen_session = vcl_session_get (listen_session_index);
Florin Coras070453d2018-08-24 17:04:27 -07001151 client_session = vcl_session_get (client_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001152
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001153 if (flags & O_NONBLOCK)
1154 VCL_SESS_ATTR_SET (client_session->attr, VCL_SESS_ATTR_NONBLOCK);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001155
Florin Coras54693d22018-07-17 10:46:29 -07001156 listen_vpp_handle = listen_session->vpp_handle;
Florin Coras0d427d82018-06-27 03:24:07 -07001157 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: Got a client request! "
1158 "vpp handle 0x%llx, sid %u, flags %d, is_nonblocking %u",
1159 getpid (), listen_vpp_handle, listen_session_index,
1160 client_session->vpp_handle, client_session_index,
1161 flags, VCL_SESS_ATTR_TEST (client_session->attr,
1162 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace543852a2017-08-03 02:11:34 -04001163
Dave Wallace048b1d62018-01-03 22:24:41 -05001164 if (ep)
1165 {
Florin Coras7e12d942018-06-27 14:32:43 -07001166 ep->is_ip4 = client_session->transport.is_ip4;
1167 ep->port = client_session->transport.rmt_port;
1168 if (client_session->transport.is_ip4)
1169 clib_memcpy (ep->ip, &client_session->transport.rmt_ip.ip4,
Dave Wallace048b1d62018-01-03 22:24:41 -05001170 sizeof (ip4_address_t));
1171 else
Florin Coras7e12d942018-06-27 14:32:43 -07001172 clib_memcpy (ep->ip, &client_session->transport.rmt_ip.ip6,
Dave Wallace048b1d62018-01-03 22:24:41 -05001173 sizeof (ip6_address_t));
1174 }
Dave Wallace60caa062017-11-10 17:07:13 -05001175
Florin Coras54693d22018-07-17 10:46:29 -07001176 if (accepted_msg.server_event_queue_address)
1177 vpp_evt_q = uword_to_pointer (accepted_msg.vpp_event_queue_address,
1178 svm_msg_q_t *);
1179 else
1180 vpp_evt_q = client_session->vpp_evt_q;
Florin Coras99368312018-08-02 10:45:44 -07001181
Florin Coras54693d22018-07-17 10:46:29 -07001182 vcl_send_session_accepted_reply (vpp_evt_q, client_session->client_context,
1183 client_session->vpp_handle, 0);
Dave Wallace60caa062017-11-10 17:07:13 -05001184
Florin Coras54693d22018-07-17 10:46:29 -07001185 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: accepted vpp handle 0x%llx, "
1186 "sid %u connection from peer %s address %U port %u to local %s "
1187 "address %U port %u", getpid (), listen_vpp_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001188 listen_session_index, client_session->vpp_handle,
1189 client_session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001190 client_session->transport.is_ip4 ? "IPv4" : "IPv6",
1191 format_ip46_address, &client_session->transport.rmt_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001192 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001193 clib_net_to_host_u16 (client_session->transport.rmt_port),
1194 client_session->transport.is_ip4 ? "IPv4" : "IPv6",
1195 format_ip46_address, &client_session->transport.lcl_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001196 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001197 clib_net_to_host_u16 (client_session->transport.lcl_port));
Florin Coras0d427d82018-06-27 03:24:07 -07001198 vcl_evt (VCL_EVT_ACCEPT, client_session, listen_session,
1199 client_session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001200
Florin Coras070453d2018-08-24 17:04:27 -07001201 return client_session_index;
Dave Wallace543852a2017-08-03 02:11:34 -04001202}
1203
1204int
1205vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep)
1206{
Florin Coras7e12d942018-06-27 14:32:43 -07001207 vcl_session_t *session = 0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001208 u64 vpp_handle = 0;
Florin Coras070453d2018-08-24 17:04:27 -07001209 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001210
Florin Coras070453d2018-08-24 17:04:27 -07001211 session = vcl_session_get (session_index);
1212 if (!session)
1213 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001214
1215 if (PREDICT_FALSE (session->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001216 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001217 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
1218 "connect on an epoll session!", getpid (), session_index);
Florin Coras070453d2018-08-24 17:04:27 -07001219 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001220 }
1221
Florin Coras7e12d942018-06-27 14:32:43 -07001222 if (PREDICT_FALSE (session->session_state & CLIENT_STATE_OPEN))
Dave Wallace543852a2017-08-03 02:11:34 -04001223 {
Florin Coras0d427d82018-06-27 03:24:07 -07001224 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: session already "
1225 "connected to %s %U port %d proto %s, state 0x%x (%s)",
1226 getpid (), session->vpp_handle, session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001227 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001228 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001229 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001230 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001231 clib_net_to_host_u16 (session->transport.rmt_port),
1232 session->session_type ? "UDP" : "TCP", session->session_state,
1233 vppcom_session_state_str (session->session_state));
Florin Coras070453d2018-08-24 17:04:27 -07001234 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001235 }
1236
Florin Coras7e12d942018-06-27 14:32:43 -07001237 session->transport.is_ip4 = server_ep->is_ip4;
1238 if (session->transport.is_ip4)
1239 clib_memcpy (&session->transport.rmt_ip.ip4, server_ep->ip,
Dave Wallaced239f8d2018-06-19 13:37:30 -04001240 sizeof (ip4_address_t));
1241 else
Florin Coras7e12d942018-06-27 14:32:43 -07001242 clib_memcpy (&session->transport.rmt_ip.ip6, server_ep->ip,
Dave Wallaced239f8d2018-06-19 13:37:30 -04001243 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001244 session->transport.rmt_port = server_ep->port;
Dave Wallace543852a2017-08-03 02:11:34 -04001245
Florin Coras0d427d82018-06-27 03:24:07 -07001246 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connecting to server %s %U "
1247 "port %d proto %s",
1248 getpid (), session->vpp_handle, session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001249 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001250 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001251 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001252 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001253 clib_net_to_host_u16 (session->transport.rmt_port),
1254 session->session_type ? "UDP" : "TCP");
Dave Wallace543852a2017-08-03 02:11:34 -04001255
Florin Coras070453d2018-08-24 17:04:27 -07001256 /*
1257 * Send connect request and wait for reply from vpp
1258 */
Dave Wallace543852a2017-08-03 02:11:34 -04001259 vppcom_send_connect_sock (session, session_index);
Florin Coras070453d2018-08-24 17:04:27 -07001260 rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
1261 vcm->cfg.session_timeout);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001262
Florin Coras070453d2018-08-24 17:04:27 -07001263 session = vcl_session_get (session_index);
Dave Wallaceee45d412017-11-24 21:44:06 -05001264 vpp_handle = session->vpp_handle;
Dave Wallace7876d392017-10-19 03:53:57 -04001265
Florin Coras070453d2018-08-24 17:04:27 -07001266 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001267 {
Dave Wallaceee45d412017-11-24 21:44:06 -05001268 if (VPPCOM_DEBUG > 0)
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001269 {
1270 if (session)
Florin Coras0d427d82018-06-27 03:24:07 -07001271 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connect "
1272 "failed! returning %d (%s)", getpid (), vpp_handle,
1273 session_index, rv, vppcom_retval_str (rv));
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001274 else
1275 clib_warning ("VCL<%d>: no session for sid %u: connect failed! "
1276 "returning %d (%s)", getpid (),
1277 session_index, rv, vppcom_retval_str (rv));
1278 }
Dave Wallaceee45d412017-11-24 21:44:06 -05001279 }
Florin Coras0d427d82018-06-27 03:24:07 -07001280 else
1281 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connected!",
1282 getpid (), vpp_handle, session_index);
Dave Wallaceee45d412017-11-24 21:44:06 -05001283
Dave Wallace4878cbe2017-11-21 03:45:09 -05001284 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001285}
1286
Florin Coras54693d22018-07-17 10:46:29 -07001287static u8
1288vcl_is_rx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1289{
1290 if (!is_ct)
1291 return (e->event_type == FIFO_EVENT_APP_RX
1292 && e->fifo->client_session_index == sid);
1293 else
1294 return (e->event_type == SESSION_IO_EVT_CT_TX);
1295}
1296
Florin Coras460dce62018-07-27 05:45:06 -07001297static inline u8
1298vcl_session_is_readable (vcl_session_t * s)
1299{
1300 return ((s->session_state & STATE_OPEN)
1301 || (s->session_state == STATE_LISTEN
1302 && s->session_type == VPPCOM_PROTO_UDP));
1303}
1304
Steven58f464e2017-10-25 12:33:12 -07001305static inline int
1306vppcom_session_read_internal (uint32_t session_index, void *buf, int n,
1307 u8 peek)
Dave Wallace543852a2017-08-03 02:11:34 -04001308{
Florin Coras54693d22018-07-17 10:46:29 -07001309 int n_read = 0, rv, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001310 vcl_session_t *s = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001311 svm_fifo_t *rx_fifo;
Florin Coras54693d22018-07-17 10:46:29 -07001312 svm_msg_q_msg_t msg;
1313 session_event_t *e;
1314 svm_msg_q_t *mq;
1315 u8 is_full;
Dave Wallace543852a2017-08-03 02:11:34 -04001316
Florin Coras070453d2018-08-24 17:04:27 -07001317 if (PREDICT_FALSE (!buf))
1318 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001319
Florin Coras070453d2018-08-24 17:04:27 -07001320 s = vcl_session_get (session_index);
1321 if (PREDICT_FALSE (!s))
1322 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001323
Florin Coras460dce62018-07-27 05:45:06 -07001324 if (PREDICT_FALSE (s->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001325 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001326 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
1327 "read from an epoll session!", getpid (), session_index);
Florin Coras070453d2018-08-24 17:04:27 -07001328 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001329 }
1330
Florin Coras460dce62018-07-27 05:45:06 -07001331 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1332 rx_fifo = s->rx_fifo;
Florin Coras54693d22018-07-17 10:46:29 -07001333
Florin Coras460dce62018-07-27 05:45:06 -07001334 if (PREDICT_FALSE (!vcl_session_is_readable (s)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001335 {
Florin Coras460dce62018-07-27 05:45:06 -07001336 session_state_t state = s->session_state;
Keith Burns (alagalah)56a0d062018-02-15 07:52:50 -08001337 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001338
Florin Coras0d427d82018-06-27 03:24:07 -07001339 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: %s session is not open! "
1340 "state 0x%x (%s), returning %d (%s)",
Florin Coras460dce62018-07-27 05:45:06 -07001341 getpid (), s->vpp_handle, session_index, state,
Florin Coras0d427d82018-06-27 03:24:07 -07001342 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001343 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001344 }
1345
Florin Coras460dce62018-07-27 05:45:06 -07001346 mq = vcl_session_is_ct (s) ? s->our_evt_q : vcm->app_event_queue;
Florin Coras99368312018-08-02 10:45:44 -07001347 svm_fifo_unset_event (rx_fifo);
Florin Coras54693d22018-07-17 10:46:29 -07001348 is_full = svm_fifo_is_full (rx_fifo);
Dave Wallacef7f809c2017-10-03 01:48:42 -04001349
Florin Coras54693d22018-07-17 10:46:29 -07001350 if (svm_fifo_is_empty (rx_fifo))
Dave Wallacef7f809c2017-10-03 01:48:42 -04001351 {
Florin Coras54693d22018-07-17 10:46:29 -07001352 if (is_nonblocking)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001353 {
Florin Coras070453d2018-08-24 17:04:27 -07001354 return VPPCOM_OK;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001355 }
Florin Coras54693d22018-07-17 10:46:29 -07001356 while (1)
1357 {
Florin Coras99368312018-08-02 10:45:44 -07001358 svm_msg_q_lock (mq);
Florin Coras54693d22018-07-17 10:46:29 -07001359 if (svm_msg_q_is_empty (mq))
1360 svm_msg_q_wait (mq);
Florin Coras99368312018-08-02 10:45:44 -07001361
Florin Coras54693d22018-07-17 10:46:29 -07001362 svm_msg_q_sub_w_lock (mq, &msg);
1363 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001364 svm_msg_q_unlock (mq);
Florin Coras54693d22018-07-17 10:46:29 -07001365 if (!vcl_is_rx_evt_for_session (e, session_index,
Florin Coras460dce62018-07-27 05:45:06 -07001366 s->our_evt_q != 0))
Florin Coras54693d22018-07-17 10:46:29 -07001367 {
1368 vcl_handle_mq_ctrl_event (e);
1369 svm_msg_q_free_msg (mq, &msg);
1370 continue;
1371 }
Florin Coras99368312018-08-02 10:45:44 -07001372 svm_fifo_unset_event (rx_fifo);
Florin Coras54693d22018-07-17 10:46:29 -07001373 svm_msg_q_free_msg (mq, &msg);
Florin Coras60f1fc12018-08-16 14:57:31 -07001374 if (PREDICT_FALSE (s->session_state == STATE_CLOSE_ON_EMPTY))
1375 return 0;
1376 if (svm_fifo_is_empty (rx_fifo))
1377 continue;
Florin Coras54693d22018-07-17 10:46:29 -07001378 break;
1379 }
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001380 }
Florin Coras54693d22018-07-17 10:46:29 -07001381
Florin Coras460dce62018-07-27 05:45:06 -07001382 if (s->is_dgram)
Florin Coras99368312018-08-02 10:45:44 -07001383 n_read = app_recv_dgram_raw (rx_fifo, buf, n, &s->transport, 0, peek);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001384 else
Florin Coras99368312018-08-02 10:45:44 -07001385 n_read = app_recv_stream_raw (rx_fifo, buf, n, 0, peek);
Florin Coras54693d22018-07-17 10:46:29 -07001386
Florin Coras460dce62018-07-27 05:45:06 -07001387 if (vcl_session_is_ct (s) && is_full)
Florin Coras99368312018-08-02 10:45:44 -07001388 {
1389 /* If the peer is not polling send notification */
1390 if (!svm_fifo_has_event (s->rx_fifo))
1391 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo,
1392 SESSION_IO_EVT_CT_RX, SVM_Q_WAIT);
1393 }
Florin Coras54693d22018-07-17 10:46:29 -07001394
Dave Wallace4878cbe2017-11-21 03:45:09 -05001395 if (VPPCOM_DEBUG > 2)
1396 {
Florin Coras54693d22018-07-17 10:46:29 -07001397 if (n_read > 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001398 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: read %d bytes "
Florin Coras460dce62018-07-27 05:45:06 -07001399 "from (%p)", getpid (), s->vpp_handle,
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001400 session_index, n_read, rx_fifo);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001401 else
Dave Wallace048b1d62018-01-03 22:24:41 -05001402 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: nothing read! "
Florin Coras460dce62018-07-27 05:45:06 -07001403 "returning %d (%s)", getpid (), s->vpp_handle,
Florin Coras070453d2018-08-24 17:04:27 -07001404 session_index, n_read, vppcom_retval_str (n_read));
Dave Wallace4878cbe2017-11-21 03:45:09 -05001405 }
Florin Coras54693d22018-07-17 10:46:29 -07001406 return n_read;
Dave Wallace543852a2017-08-03 02:11:34 -04001407}
1408
Steven58f464e2017-10-25 12:33:12 -07001409int
Dave Wallace048b1d62018-01-03 22:24:41 -05001410vppcom_session_read (uint32_t session_index, void *buf, size_t n)
Steven58f464e2017-10-25 12:33:12 -07001411{
1412 return (vppcom_session_read_internal (session_index, buf, n, 0));
1413}
1414
1415static int
1416vppcom_session_peek (uint32_t session_index, void *buf, int n)
1417{
1418 return (vppcom_session_read_internal (session_index, buf, n, 1));
1419}
1420
Dave Wallace543852a2017-08-03 02:11:34 -04001421static inline int
Florin Coras54693d22018-07-17 10:46:29 -07001422vppcom_session_read_ready (vcl_session_t * session)
Dave Wallace543852a2017-08-03 02:11:34 -04001423{
Dave Wallace543852a2017-08-03 02:11:34 -04001424 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05001425 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001426 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001427 clib_warning ("VCL<%d>: ERROR: sid %u: cannot read from an "
Florin Coras54693d22018-07-17 10:46:29 -07001428 "epoll session!", getpid (), vcl_session_index (session));
1429 return VPPCOM_EBADFD;
1430 }
1431
1432 if (PREDICT_FALSE (!(session->session_state & (STATE_OPEN | STATE_LISTEN))))
1433 {
1434 session_state_t state = session->session_state;
1435 int rv;
1436
1437 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1438
1439 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open!"
1440 " state 0x%x (%s), returning %d (%s)", getpid (),
1441 session->vpp_handle, vcl_session_index (session), state,
1442 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
1443 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001444 }
Dave Wallace33e002b2017-09-06 01:20:02 -04001445
Florin Coras7e12d942018-06-27 14:32:43 -07001446 if (session->session_state & STATE_LISTEN)
Florin Coras54693d22018-07-17 10:46:29 -07001447 return clib_fifo_elts (session->accept_evts_fifo);
1448
1449 return svm_fifo_max_dequeue (session->rx_fifo);
1450}
1451
1452static u8
1453vcl_is_tx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1454{
1455 if (!is_ct)
1456 return (e->event_type == FIFO_EVENT_APP_TX
1457 && e->fifo->client_session_index == sid);
Dave Wallace543852a2017-08-03 02:11:34 -04001458 else
Florin Coras54693d22018-07-17 10:46:29 -07001459 return (e->event_type == SESSION_IO_EVT_CT_RX);
Dave Wallace543852a2017-08-03 02:11:34 -04001460}
1461
1462int
Dave Wallace048b1d62018-01-03 22:24:41 -05001463vppcom_session_write (uint32_t session_index, void *buf, size_t n)
Dave Wallace543852a2017-08-03 02:11:34 -04001464{
Florin Coras54693d22018-07-17 10:46:29 -07001465 int rv, n_write, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001466 vcl_session_t *s = 0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001467 svm_fifo_t *tx_fifo = 0;
Florin Coras460dce62018-07-27 05:45:06 -07001468 session_evt_type_t et;
Florin Coras54693d22018-07-17 10:46:29 -07001469 svm_msg_q_msg_t msg;
1470 session_event_t *e;
Florin Coras3c2fed52018-07-04 04:15:05 -07001471 svm_msg_q_t *mq;
Dave Wallace543852a2017-08-03 02:11:34 -04001472
Florin Coras070453d2018-08-24 17:04:27 -07001473 if (PREDICT_FALSE (!buf))
1474 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001475
Florin Coras070453d2018-08-24 17:04:27 -07001476 s = vcl_session_get (session_index);
1477 if (PREDICT_FALSE (!s))
1478 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001479
Florin Coras460dce62018-07-27 05:45:06 -07001480 tx_fifo = s->tx_fifo;
1481 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001482
Florin Coras460dce62018-07-27 05:45:06 -07001483 if (PREDICT_FALSE (s->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001484 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001485 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001486 "cannot write to an epoll session!",
Florin Coras460dce62018-07-27 05:45:06 -07001487 getpid (), s->vpp_handle, session_index);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001488
Florin Coras070453d2018-08-24 17:04:27 -07001489 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001490 }
1491
Florin Coras460dce62018-07-27 05:45:06 -07001492 if (!(s->session_state & STATE_OPEN))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001493 {
Florin Coras460dce62018-07-27 05:45:06 -07001494 session_state_t state = s->session_state;
Florin Coras54693d22018-07-17 10:46:29 -07001495 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Florin Coras0d427d82018-06-27 03:24:07 -07001496 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open! "
1497 "state 0x%x (%s)",
Florin Coras460dce62018-07-27 05:45:06 -07001498 getpid (), s->vpp_handle, session_index,
Florin Coras0d427d82018-06-27 03:24:07 -07001499 state, vppcom_session_state_str (state));
Florin Coras070453d2018-08-24 17:04:27 -07001500 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001501 }
1502
Florin Coras460dce62018-07-27 05:45:06 -07001503 mq = vcl_session_is_ct (s) ? s->our_evt_q : vcm->app_event_queue;
Florin Coras54693d22018-07-17 10:46:29 -07001504 if (svm_fifo_is_full (tx_fifo))
Dave Wallace543852a2017-08-03 02:11:34 -04001505 {
Florin Coras54693d22018-07-17 10:46:29 -07001506 if (is_nonblocking)
1507 {
Florin Coras070453d2018-08-24 17:04:27 -07001508 return VPPCOM_EWOULDBLOCK;
Florin Coras54693d22018-07-17 10:46:29 -07001509 }
Florin Coras60f1fc12018-08-16 14:57:31 -07001510 while (svm_fifo_is_full (tx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001511 {
Florin Coras99368312018-08-02 10:45:44 -07001512 svm_msg_q_lock (mq);
Florin Coras99368312018-08-02 10:45:44 -07001513 while (svm_msg_q_is_empty (mq) && svm_msg_q_timedwait (mq, 10e-6))
1514 ;
Florin Coras54693d22018-07-17 10:46:29 -07001515 svm_msg_q_sub_w_lock (mq, &msg);
1516 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001517 svm_msg_q_unlock (mq);
1518
Florin Coras54693d22018-07-17 10:46:29 -07001519 if (!vcl_is_tx_evt_for_session (e, session_index,
Florin Coras460dce62018-07-27 05:45:06 -07001520 s->our_evt_q != 0))
Florin Coras60f1fc12018-08-16 14:57:31 -07001521 vcl_handle_mq_ctrl_event (e);
Florin Coras54693d22018-07-17 10:46:29 -07001522 svm_msg_q_free_msg (mq, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001523 }
Dave Wallace543852a2017-08-03 02:11:34 -04001524 }
Dave Wallace543852a2017-08-03 02:11:34 -04001525
Florin Coras460dce62018-07-27 05:45:06 -07001526 ASSERT (FIFO_EVENT_APP_TX + 1 == SESSION_IO_EVT_CT_TX);
1527 et = FIFO_EVENT_APP_TX + vcl_session_is_ct (s);
1528 if (s->is_dgram)
1529 n_write = app_send_dgram_raw (tx_fifo, &s->transport,
1530 s->vpp_evt_q, buf, n, et, SVM_Q_WAIT);
1531 else
1532 n_write = app_send_stream_raw (tx_fifo, s->vpp_evt_q, buf, n, et,
1533 SVM_Q_WAIT);
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -07001534
Florin Coras460dce62018-07-27 05:45:06 -07001535 ASSERT (n_write > 0);
Dave Wallace543852a2017-08-03 02:11:34 -04001536
1537 if (VPPCOM_DEBUG > 2)
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001538 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05001539 if (n_write <= 0)
Dave Wallace048b1d62018-01-03 22:24:41 -05001540 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: "
Florin Coras460dce62018-07-27 05:45:06 -07001541 "FIFO-FULL (%p)", getpid (), s->vpp_handle,
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001542 session_index, tx_fifo);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001543 else
Dave Wallace048b1d62018-01-03 22:24:41 -05001544 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: "
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001545 "wrote %d bytes tx-fifo: (%p)", getpid (),
Florin Coras460dce62018-07-27 05:45:06 -07001546 s->vpp_handle, session_index, n_write, tx_fifo);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001547 }
Florin Coras54693d22018-07-17 10:46:29 -07001548 return n_write;
Dave Wallace543852a2017-08-03 02:11:34 -04001549}
1550
Florin Coras99368312018-08-02 10:45:44 -07001551static vcl_session_t *
1552vcl_ct_session_get_from_fifo (svm_fifo_t * f, u8 type)
1553{
1554 vcl_session_t *s;
1555 s = vcl_session_get (f->client_session_index);
1556 if (s)
1557 {
1558 /* rx fifo */
1559 if (type == 0 && s->rx_fifo == f)
1560 return s;
1561 /* tx fifo */
1562 if (type == 1 && s->tx_fifo == f)
1563 return s;
1564 }
1565 s = vcl_session_get (f->master_session_index);
1566 if (s)
1567 {
1568 if (type == 0 && s->rx_fifo == f)
1569 return s;
1570 if (type == 1 && s->tx_fifo == f)
1571 return s;
1572 }
1573 return 0;
1574}
1575
Dave Wallace543852a2017-08-03 02:11:34 -04001576static inline int
Florin Coras7e12d942018-06-27 14:32:43 -07001577vppcom_session_write_ready (vcl_session_t * session, u32 session_index)
Dave Wallace543852a2017-08-03 02:11:34 -04001578{
Dave Wallace543852a2017-08-03 02:11:34 -04001579 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05001580 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001581 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001582 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001583 "cannot write to an epoll session!",
1584 getpid (), session->vpp_handle, session_index);
Florin Coras54693d22018-07-17 10:46:29 -07001585 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001586 }
1587
Florin Coras7e12d942018-06-27 14:32:43 -07001588 if (PREDICT_FALSE (session->session_state & STATE_LISTEN))
Dave Wallace33e002b2017-09-06 01:20:02 -04001589 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001590 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001591 "cannot write to a listen session!",
1592 getpid (), session->vpp_handle, session_index);
Florin Coras54693d22018-07-17 10:46:29 -07001593 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001594 }
1595
Florin Coras54693d22018-07-17 10:46:29 -07001596 if (PREDICT_FALSE (!(session->session_state & STATE_OPEN)))
Dave Wallace4878cbe2017-11-21 03:45:09 -05001597 {
Florin Coras7e12d942018-06-27 14:32:43 -07001598 session_state_t state = session->session_state;
Florin Coras54693d22018-07-17 10:46:29 -07001599 int rv;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001600
Keith Burns (alagalah)56a0d062018-02-15 07:52:50 -08001601 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Dave Wallace048b1d62018-01-03 22:24:41 -05001602 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001603 "session is not open! state 0x%x (%s), "
Dave Wallaceee45d412017-11-24 21:44:06 -05001604 "returning %d (%s)", getpid (), session->vpp_handle,
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001605 session_index,
Dave Wallace4878cbe2017-11-21 03:45:09 -05001606 state, vppcom_session_state_str (state),
1607 rv, vppcom_retval_str (rv));
Florin Coras54693d22018-07-17 10:46:29 -07001608 return rv;
Dave Wallace33e002b2017-09-06 01:20:02 -04001609 }
1610
Florin Coras0d427d82018-06-27 03:24:07 -07001611 VDBG (3, "VCL<%d>: vpp handle 0x%llx, sid %u: peek %s (%p), ready = %d",
1612 getpid (), session->vpp_handle, session_index, session->tx_fifo,
Florin Coras54693d22018-07-17 10:46:29 -07001613 svm_fifo_max_enqueue (session->tx_fifo));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001614
Florin Coras54693d22018-07-17 10:46:29 -07001615 return svm_fifo_max_enqueue (session->tx_fifo);
1616}
1617
Florin Coras99368312018-08-02 10:45:44 -07001618static inline int
1619vcl_mq_dequeue_batch (svm_msg_q_t * mq)
1620{
1621 svm_msg_q_msg_t *msg;
1622 u32 n_msgs;
1623 int i;
1624
1625 n_msgs = svm_msg_q_size (mq);
1626 for (i = 0; i < n_msgs; i++)
1627 {
1628 vec_add2 (vcm->mq_msg_vector, msg, 1);
1629 svm_msg_q_sub_w_lock (mq, msg);
1630 }
1631 return n_msgs;
1632}
1633
Florin Coras54693d22018-07-17 10:46:29 -07001634static int
1635vcl_select_handle_mq (svm_msg_q_t * mq, unsigned long n_bits,
1636 unsigned long *read_map, unsigned long *write_map,
1637 unsigned long *except_map, double time_to_wait,
1638 u32 * bits_set)
1639{
1640 session_disconnected_msg_t *disconnected_msg;
Florin Coras99368312018-08-02 10:45:44 -07001641 session_connected_msg_t *connected_msg;
Florin Coras54693d22018-07-17 10:46:29 -07001642 session_accepted_msg_t *accepted_msg;
1643 vcl_session_msg_t *vcl_msg;
1644 vcl_session_t *session;
Florin Coras99368312018-08-02 10:45:44 -07001645 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07001646 session_event_t *e;
Florin Coras99368312018-08-02 10:45:44 -07001647 u32 i, sid;
Florin Coras54693d22018-07-17 10:46:29 -07001648 u64 handle;
1649
1650 svm_msg_q_lock (mq);
1651 if (svm_msg_q_is_empty (mq))
Dave Wallace4878cbe2017-11-21 03:45:09 -05001652 {
Florin Coras54693d22018-07-17 10:46:29 -07001653 if (*bits_set)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001654 {
Florin Coras54693d22018-07-17 10:46:29 -07001655 svm_msg_q_unlock (mq);
1656 return 0;
1657 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001658
Florin Coras54693d22018-07-17 10:46:29 -07001659 if (!time_to_wait)
1660 {
1661 svm_msg_q_unlock (mq);
1662 return 0;
1663 }
1664 else if (time_to_wait < 0)
1665 {
1666 svm_msg_q_wait (mq);
1667 }
1668 else
1669 {
1670 if (svm_msg_q_timedwait (mq, time_to_wait))
1671 {
1672 svm_msg_q_unlock (mq);
1673 return 0;
1674 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001675 }
1676 }
Florin Coras99368312018-08-02 10:45:44 -07001677 vcl_mq_dequeue_batch (mq);
Florin Coras54693d22018-07-17 10:46:29 -07001678 svm_msg_q_unlock (mq);
1679
Florin Coras99368312018-08-02 10:45:44 -07001680 for (i = 0; i < vec_len (vcm->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07001681 {
Florin Coras99368312018-08-02 10:45:44 -07001682 msg = vec_elt_at_index (vcm->mq_msg_vector, i);
1683 e = svm_msg_q_msg_data (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07001684 switch (e->event_type)
1685 {
1686 case FIFO_EVENT_APP_RX:
1687 sid = e->fifo->client_session_index;
1688 session = vcl_session_get (sid);
Florin Coras54693d22018-07-17 10:46:29 -07001689 if (sid < n_bits && read_map)
1690 {
1691 clib_bitmap_set_no_check (read_map, sid, 1);
1692 *bits_set += 1;
1693 }
1694 break;
1695 case FIFO_EVENT_APP_TX:
1696 sid = e->fifo->client_session_index;
1697 session = vcl_session_get (sid);
Florin Coras60f1fc12018-08-16 14:57:31 -07001698 if (!session)
Florin Coras54693d22018-07-17 10:46:29 -07001699 break;
1700 if (sid < n_bits && write_map)
1701 {
1702 clib_bitmap_set_no_check (write_map, sid, 1);
1703 *bits_set += 1;
1704 }
1705 break;
1706 case SESSION_IO_EVT_CT_TX:
1707 session = vcl_ct_session_get_from_fifo (e->fifo, 0);
1708 sid = vcl_session_index (session);
Florin Coras54693d22018-07-17 10:46:29 -07001709 if (sid < n_bits && read_map)
1710 {
1711 clib_bitmap_set_no_check (read_map, sid, 1);
1712 *bits_set += 1;
1713 }
1714 break;
1715 break;
1716 case SESSION_IO_EVT_CT_RX:
1717 session = vcl_ct_session_get_from_fifo (e->fifo, 1);
1718 sid = vcl_session_index (session);
Florin Coras60f1fc12018-08-16 14:57:31 -07001719 if (!session)
Florin Coras54693d22018-07-17 10:46:29 -07001720 break;
1721 if (sid < n_bits && write_map)
1722 {
1723 clib_bitmap_set_no_check (write_map, sid, 1);
1724 *bits_set += 1;
1725 }
1726 break;
1727 case SESSION_CTRL_EVT_ACCEPTED:
1728 accepted_msg = (session_accepted_msg_t *) e->data;
1729 handle = accepted_msg->listener_handle;
1730 session = vppcom_session_table_lookup_listener (handle);
1731 if (!session)
1732 {
1733 clib_warning ("VCL<%d>: ERROR: couldn't find listen session:"
1734 "listener handle %llx", getpid (), handle);
1735 break;
1736 }
1737
1738 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
1739 vcl_msg->accepted_msg = *accepted_msg;
1740 sid = session - vcm->sessions;
1741 if (sid < n_bits && read_map)
1742 {
1743 clib_bitmap_set_no_check (read_map, sid, 1);
1744 *bits_set += 1;
1745 }
1746 break;
Florin Coras99368312018-08-02 10:45:44 -07001747 case SESSION_CTRL_EVT_CONNECTED:
1748 connected_msg = (session_connected_msg_t *) e->data;
1749 vcl_session_connected_handler (connected_msg);
1750 break;
Florin Coras54693d22018-07-17 10:46:29 -07001751 case SESSION_CTRL_EVT_DISCONNECTED:
1752 disconnected_msg = (session_disconnected_msg_t *) e->data;
1753 sid = vcl_session_get_index_from_handle (disconnected_msg->handle);
1754 if (sid < n_bits && except_map)
1755 {
1756 clib_bitmap_set_no_check (except_map, sid, 1);
1757 *bits_set += 1;
1758 }
1759 break;
Florin Corasc9fbd662018-08-24 12:59:56 -07001760 case SESSION_CTRL_EVT_RESET:
Florin Coras60116992018-08-27 09:52:18 -07001761 sid = vcl_session_reset_handler ((session_reset_msg_t *) e->data);
Florin Corasc9fbd662018-08-24 12:59:56 -07001762 if (sid < n_bits && except_map)
1763 {
1764 clib_bitmap_set_no_check (except_map, sid, 1);
1765 *bits_set += 1;
1766 }
1767 break;
Florin Coras54693d22018-07-17 10:46:29 -07001768 default:
1769 clib_warning ("unhandled: %u", e->event_type);
1770 break;
1771 }
Florin Coras99368312018-08-02 10:45:44 -07001772 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07001773 }
1774
Florin Coras99368312018-08-02 10:45:44 -07001775 vec_reset_length (vcm->mq_msg_vector);
Florin Coras54693d22018-07-17 10:46:29 -07001776 return *bits_set;
Dave Wallace543852a2017-08-03 02:11:34 -04001777}
1778
Florin Coras99368312018-08-02 10:45:44 -07001779static int
1780vppcom_select_condvar (unsigned long n_bits, unsigned long *read_map,
1781 unsigned long *write_map, unsigned long *except_map,
1782 double time_to_wait, u32 * bits_set)
1783{
1784 double total_wait = 0, wait_slice;
1785 vcl_cut_through_registration_t *cr;
1786
1787 time_to_wait = (time_to_wait == -1) ? 10e9 : time_to_wait;
1788 wait_slice = vcm->cut_through_registrations ? 10e-6 : time_to_wait;
1789 do
1790 {
1791 /* *INDENT-OFF* */
1792 pool_foreach (cr, vcm->cut_through_registrations, ({
1793 vcl_select_handle_mq (cr->mq, n_bits, read_map, write_map, except_map,
1794 0, bits_set);
1795 }));
1796 /* *INDENT-ON* */
1797
1798 vcl_select_handle_mq (vcm->app_event_queue, n_bits, read_map, write_map,
1799 except_map, time_to_wait, bits_set);
1800 total_wait += wait_slice;
1801 if (*bits_set)
1802 return *bits_set;
1803 }
1804 while (total_wait < time_to_wait);
1805
1806 return 0;
1807}
1808
1809static int
1810vppcom_select_eventfd (unsigned long n_bits, unsigned long *read_map,
1811 unsigned long *write_map, unsigned long *except_map,
1812 double time_to_wait, u32 * bits_set)
1813{
1814 vcl_mq_evt_conn_t *mqc;
1815 int __clib_unused n_read;
1816 int n_mq_evts, i;
1817 u64 buf;
1818
1819 vec_validate (vcm->mq_events, pool_elts (vcm->mq_evt_conns));
1820 n_mq_evts = epoll_wait (vcm->mqs_epfd, vcm->mq_events,
1821 vec_len (vcm->mq_events), time_to_wait);
1822 for (i = 0; i < n_mq_evts; i++)
1823 {
1824 mqc = vcl_mq_evt_conn_get (vcm->mq_events[i].data.u32);
1825 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
1826 vcl_select_handle_mq (mqc->mq, n_bits, read_map, write_map,
1827 except_map, 0, bits_set);
1828 }
1829
1830 return (n_mq_evts > 0 ? (int) *bits_set : 0);
1831}
1832
Dave Wallace543852a2017-08-03 02:11:34 -04001833int
1834vppcom_select (unsigned long n_bits, unsigned long *read_map,
1835 unsigned long *write_map, unsigned long *except_map,
1836 double time_to_wait)
1837{
Florin Coras54693d22018-07-17 10:46:29 -07001838 u32 sid, minbits = clib_max (n_bits, BITS (uword)), bits_set = 0;
Florin Coras7e12d942018-06-27 14:32:43 -07001839 vcl_session_t *session = 0;
Florin Coras54693d22018-07-17 10:46:29 -07001840 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001841
1842 ASSERT (sizeof (clib_bitmap_t) == sizeof (long int));
1843
Dave Wallace7876d392017-10-19 03:53:57 -04001844 if (n_bits && read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04001845 {
1846 clib_bitmap_validate (vcm->rd_bitmap, minbits);
Dave Wallace048b1d62018-01-03 22:24:41 -05001847 clib_memcpy (vcm->rd_bitmap, read_map,
1848 vec_len (vcm->rd_bitmap) * sizeof (clib_bitmap_t));
1849 memset (read_map, 0, vec_len (vcm->rd_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace543852a2017-08-03 02:11:34 -04001850 }
Dave Wallace7876d392017-10-19 03:53:57 -04001851 if (n_bits && write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04001852 {
1853 clib_bitmap_validate (vcm->wr_bitmap, minbits);
Dave Wallace048b1d62018-01-03 22:24:41 -05001854 clib_memcpy (vcm->wr_bitmap, write_map,
1855 vec_len (vcm->wr_bitmap) * sizeof (clib_bitmap_t));
1856 memset (write_map, 0,
1857 vec_len (vcm->wr_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace543852a2017-08-03 02:11:34 -04001858 }
Dave Wallace7876d392017-10-19 03:53:57 -04001859 if (n_bits && except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04001860 {
1861 clib_bitmap_validate (vcm->ex_bitmap, minbits);
Dave Wallace048b1d62018-01-03 22:24:41 -05001862 clib_memcpy (vcm->ex_bitmap, except_map,
1863 vec_len (vcm->ex_bitmap) * sizeof (clib_bitmap_t));
1864 memset (except_map, 0,
1865 vec_len (vcm->ex_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace543852a2017-08-03 02:11:34 -04001866 }
1867
Florin Coras54693d22018-07-17 10:46:29 -07001868 if (!n_bits)
1869 return 0;
1870
1871 if (!write_map)
1872 goto check_rd;
1873
1874 /* *INDENT-OFF* */
1875 clib_bitmap_foreach (sid, vcm->wr_bitmap, ({
Florin Coras54693d22018-07-17 10:46:29 -07001876 if (!(session = vcl_session_get (sid)))
1877 {
Florin Coras54693d22018-07-17 10:46:29 -07001878 VDBG (0, "VCL<%d>: session %d specified in write_map is closed.",
1879 getpid (), sid);
1880 return VPPCOM_EBADFD;
1881 }
1882
1883 rv = svm_fifo_is_full (session->tx_fifo);
Florin Coras54693d22018-07-17 10:46:29 -07001884 if (!rv)
1885 {
1886 clib_bitmap_set_no_check (write_map, sid, 1);
1887 bits_set++;
1888 }
1889 }));
1890
1891check_rd:
1892 if (!read_map)
1893 goto check_mq;
Florin Coras99368312018-08-02 10:45:44 -07001894
Florin Coras54693d22018-07-17 10:46:29 -07001895 clib_bitmap_foreach (sid, vcm->rd_bitmap, ({
Florin Coras54693d22018-07-17 10:46:29 -07001896 if (!(session = vcl_session_get (sid)))
1897 {
Florin Coras54693d22018-07-17 10:46:29 -07001898 VDBG (0, "VCL<%d>: session %d specified in write_map is closed.",
1899 getpid (), sid);
1900 return VPPCOM_EBADFD;
1901 }
1902
1903 rv = vppcom_session_read_ready (session);
Florin Coras54693d22018-07-17 10:46:29 -07001904 if (rv)
1905 {
1906 clib_bitmap_set_no_check (read_map, sid, 1);
1907 bits_set++;
1908 }
1909 }));
1910 /* *INDENT-ON* */
1911
1912check_mq:
Dave Wallace543852a2017-08-03 02:11:34 -04001913
Florin Coras99368312018-08-02 10:45:44 -07001914 if (vcm->cfg.use_mq_eventfd)
1915 vppcom_select_eventfd (n_bits, read_map, write_map, except_map,
1916 time_to_wait, &bits_set);
1917 else
1918 vppcom_select_condvar (n_bits, read_map, write_map, except_map,
1919 time_to_wait, &bits_set);
Florin Coras54693d22018-07-17 10:46:29 -07001920
Dave Wallace543852a2017-08-03 02:11:34 -04001921 return (bits_set);
1922}
1923
Dave Wallacef7f809c2017-10-03 01:48:42 -04001924static inline void
1925vep_verify_epoll_chain (u32 vep_idx)
1926{
Florin Coras7e12d942018-06-27 14:32:43 -07001927 vcl_session_t *session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001928 vppcom_epoll_t *vep;
Dave Wallace498b3a52017-11-09 13:00:34 -05001929 u32 sid = vep_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001930
Dave Wallace498b3a52017-11-09 13:00:34 -05001931 if (VPPCOM_DEBUG <= 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001932 return;
1933
1934 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Florin Coras070453d2018-08-24 17:04:27 -07001935 session = vcl_session_get (vep_idx);
1936 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04001937 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001938 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!",
1939 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04001940 goto done;
1941 }
1942 if (PREDICT_FALSE (!session->is_vep))
1943 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001944 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
1945 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04001946 goto done;
1947 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001948 vep = &session->vep;
Dave Wallace048b1d62018-01-03 22:24:41 -05001949 clib_warning ("VCL<%d>: vep_idx (%u): Dumping epoll chain\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05001950 "{\n"
1951 " is_vep = %u\n"
1952 " is_vep_session = %u\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05001953 " next_sid = 0x%x (%u)\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05001954 " wait_cont_idx = 0x%x (%u)\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05001955 "}\n", getpid (), vep_idx,
1956 session->is_vep, session->is_vep_session,
1957 vep->next_sid, vep->next_sid,
Dave Wallace498b3a52017-11-09 13:00:34 -05001958 session->wait_cont_idx, session->wait_cont_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001959
1960 for (sid = vep->next_sid; sid != ~0; sid = vep->next_sid)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001961 {
Florin Coras070453d2018-08-24 17:04:27 -07001962 session = vcl_session_get (sid);
1963 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04001964 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001965 clib_warning ("VCL<%d>: ERROR: Invalid sid (%u)!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001966 goto done;
1967 }
1968 if (PREDICT_FALSE (session->is_vep))
Dave Wallace048b1d62018-01-03 22:24:41 -05001969 clib_warning ("VCL<%d>: ERROR: sid (%u) is a vep!",
1970 getpid (), vep_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001971 else if (PREDICT_FALSE (!session->is_vep_session))
1972 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001973 clib_warning ("VCL<%d>: ERROR: session (%u) "
1974 "is not a vep session!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001975 goto done;
1976 }
1977 vep = &session->vep;
1978 if (PREDICT_FALSE (vep->vep_idx != vep_idx))
Dave Wallace048b1d62018-01-03 22:24:41 -05001979 clib_warning ("VCL<%d>: ERROR: session (%u) vep_idx (%u) != "
Dave Wallace4878cbe2017-11-21 03:45:09 -05001980 "vep_idx (%u)!", getpid (),
1981 sid, session->vep.vep_idx, vep_idx);
1982 if (session->is_vep_session)
1983 {
1984 clib_warning ("vep_idx[%u]: sid 0x%x (%u)\n"
1985 "{\n"
1986 " next_sid = 0x%x (%u)\n"
1987 " prev_sid = 0x%x (%u)\n"
1988 " vep_idx = 0x%x (%u)\n"
1989 " ev.events = 0x%x\n"
1990 " ev.data.u64 = 0x%llx\n"
1991 " et_mask = 0x%x\n"
1992 "}\n",
1993 vep_idx, sid, sid,
1994 vep->next_sid, vep->next_sid,
1995 vep->prev_sid, vep->prev_sid,
1996 vep->vep_idx, vep->vep_idx,
1997 vep->ev.events, vep->ev.data.u64, vep->et_mask);
Dave Wallacef7f809c2017-10-03 01:48:42 -04001998 }
1999 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002000
2001done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002002 clib_warning ("VCL<%d>: vep_idx (%u): Dump complete!\n",
2003 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002004}
2005
2006int
2007vppcom_epoll_create (void)
2008{
Florin Coras7e12d942018-06-27 14:32:43 -07002009 vcl_session_t *vep_session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002010 u32 vep_idx;
2011
Dave Wallacef7f809c2017-10-03 01:48:42 -04002012 pool_get (vcm->sessions, vep_session);
2013 memset (vep_session, 0, sizeof (*vep_session));
2014 vep_idx = vep_session - vcm->sessions;
2015
2016 vep_session->is_vep = 1;
2017 vep_session->vep.vep_idx = ~0;
2018 vep_session->vep.next_sid = ~0;
2019 vep_session->vep.prev_sid = ~0;
2020 vep_session->wait_cont_idx = ~0;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002021 vep_session->vpp_handle = ~0;
Keith Burns (alagalah)12756512018-03-06 05:55:27 -08002022 vep_session->poll_reg = 0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002023
Florin Coras0d427d82018-06-27 03:24:07 -07002024 vcl_evt (VCL_EVT_EPOLL_CREATE, vep_session, vep_idx);
Florin Coras0d427d82018-06-27 03:24:07 -07002025 VDBG (0, "VCL<%d>: Created vep_idx %u / sid %u!",
2026 getpid (), vep_idx, vep_idx);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08002027
Dave Wallacef7f809c2017-10-03 01:48:42 -04002028 return (vep_idx);
2029}
2030
2031int
2032vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index,
2033 struct epoll_event *event)
2034{
Florin Coras7e12d942018-06-27 14:32:43 -07002035 vcl_session_t *vep_session;
2036 vcl_session_t *session;
Florin Coras070453d2018-08-24 17:04:27 -07002037 int rv = VPPCOM_OK;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002038
2039 if (vep_idx == session_index)
2040 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002041 clib_warning ("VCL<%d>: ERROR: vep_idx == session_index (%u)!",
Dave Wallace4878cbe2017-11-21 03:45:09 -05002042 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002043 return VPPCOM_EINVAL;
2044 }
2045
Florin Coras070453d2018-08-24 17:04:27 -07002046 vep_session = vcl_session_get (vep_idx);
2047 if (PREDICT_FALSE (!vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002048 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002049 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!", vep_idx);
Florin Coras070453d2018-08-24 17:04:27 -07002050 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002051 }
2052 if (PREDICT_FALSE (!vep_session->is_vep))
2053 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002054 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
Dave Wallace4878cbe2017-11-21 03:45:09 -05002055 getpid (), vep_idx);
Florin Coras070453d2018-08-24 17:04:27 -07002056 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002057 }
2058
2059 ASSERT (vep_session->vep.vep_idx == ~0);
2060 ASSERT (vep_session->vep.prev_sid == ~0);
2061
Florin Coras070453d2018-08-24 17:04:27 -07002062 session = vcl_session_get (session_index);
2063 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002064 {
Florin Coras0d427d82018-06-27 03:24:07 -07002065 VDBG (0, "VCL<%d>: ERROR: Invalid session_index (%u)!",
2066 getpid (), session_index);
Florin Coras070453d2018-08-24 17:04:27 -07002067 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002068 }
2069 if (PREDICT_FALSE (session->is_vep))
2070 {
Dave Wallace4878cbe2017-11-21 03:45:09 -05002071 clib_warning ("ERROR: session_index (%u) is a vep!", vep_idx);
Florin Coras070453d2018-08-24 17:04:27 -07002072 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002073 }
2074
2075 switch (op)
2076 {
2077 case EPOLL_CTL_ADD:
2078 if (PREDICT_FALSE (!event))
2079 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002080 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002081 "epoll_event structure!", getpid ());
Florin Coras070453d2018-08-24 17:04:27 -07002082 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002083 }
2084 if (vep_session->vep.next_sid != ~0)
2085 {
Florin Coras7e12d942018-06-27 14:32:43 -07002086 vcl_session_t *next_session;
Florin Coras070453d2018-08-24 17:04:27 -07002087 next_session = vcl_session_get (vep_session->vep.next_sid);
2088 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002089 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002090 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: Invalid "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002091 "vep.next_sid (%u) on vep_idx (%u)!",
2092 getpid (), vep_session->vep.next_sid, vep_idx);
Florin Coras070453d2018-08-24 17:04:27 -07002093 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002094 }
2095 ASSERT (next_session->vep.prev_sid == vep_idx);
2096 next_session->vep.prev_sid = session_index;
2097 }
2098 session->vep.next_sid = vep_session->vep.next_sid;
2099 session->vep.prev_sid = vep_idx;
2100 session->vep.vep_idx = vep_idx;
2101 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2102 session->vep.ev = *event;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002103 session->is_vep = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002104 session->is_vep_session = 1;
2105 vep_session->vep.next_sid = session_index;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08002106
Florin Coras070453d2018-08-24 17:04:27 -07002107 VDBG (1, "VCL<%d>: EPOLL_CTL_ADD: vep_idx %u, sid %u, events 0x%x, "
2108 "data 0x%llx!", getpid (), vep_idx, session_index, event->events,
2109 event->data.u64);
Florin Coras0d427d82018-06-27 03:24:07 -07002110 vcl_evt (VCL_EVT_EPOLL_CTLADD, session, event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002111 break;
2112
2113 case EPOLL_CTL_MOD:
2114 if (PREDICT_FALSE (!event))
2115 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002116 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_MOD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002117 "epoll_event structure!", getpid ());
Dave Wallacef7f809c2017-10-03 01:48:42 -04002118 rv = VPPCOM_EINVAL;
2119 goto done;
2120 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002121 else if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002122 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002123 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002124 "not a vep session!", getpid (), session_index);
2125 rv = VPPCOM_EINVAL;
2126 goto done;
2127 }
2128 else if (PREDICT_FALSE (session->vep.vep_idx != vep_idx))
2129 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002130 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002131 "vep_idx (%u) != vep_idx (%u)!",
2132 getpid (), session_index,
2133 session->vep.vep_idx, vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002134 rv = VPPCOM_EINVAL;
2135 goto done;
2136 }
2137 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2138 session->vep.ev = *event;
Florin Coras0d427d82018-06-27 03:24:07 -07002139 VDBG (1, "VCL<%d>: EPOLL_CTL_MOD: vep_idx %u, sid %u, events 0x%x,"
2140 " data 0x%llx!", getpid (), vep_idx, session_index, event->events,
2141 event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002142 break;
2143
2144 case EPOLL_CTL_DEL:
Dave Wallace4878cbe2017-11-21 03:45:09 -05002145 if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002146 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002147 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002148 "not a vep session!", getpid (), session_index);
2149 rv = VPPCOM_EINVAL;
2150 goto done;
2151 }
2152 else if (PREDICT_FALSE (session->vep.vep_idx != vep_idx))
2153 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002154 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002155 "vep_idx (%u) != vep_idx (%u)!",
2156 getpid (), session_index,
2157 session->vep.vep_idx, vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002158 rv = VPPCOM_EINVAL;
2159 goto done;
2160 }
2161
2162 vep_session->wait_cont_idx =
2163 (vep_session->wait_cont_idx == session_index) ?
2164 session->vep.next_sid : vep_session->wait_cont_idx;
2165
2166 if (session->vep.prev_sid == vep_idx)
2167 vep_session->vep.next_sid = session->vep.next_sid;
2168 else
2169 {
Florin Coras7e12d942018-06-27 14:32:43 -07002170 vcl_session_t *prev_session;
Florin Coras070453d2018-08-24 17:04:27 -07002171 prev_session = vcl_session_get (session->vep.prev_sid);
2172 if (PREDICT_FALSE (!prev_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002173 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002174 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002175 "vep.prev_sid (%u) on sid (%u)!",
2176 getpid (), session->vep.prev_sid, session_index);
Florin Coras070453d2018-08-24 17:04:27 -07002177 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002178 }
2179 ASSERT (prev_session->vep.next_sid == session_index);
2180 prev_session->vep.next_sid = session->vep.next_sid;
2181 }
2182 if (session->vep.next_sid != ~0)
2183 {
Florin Coras7e12d942018-06-27 14:32:43 -07002184 vcl_session_t *next_session;
Florin Coras070453d2018-08-24 17:04:27 -07002185 next_session = vcl_session_get (session->vep.next_sid);
2186 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002187 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002188 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002189 "vep.next_sid (%u) on sid (%u)!",
2190 getpid (), session->vep.next_sid, session_index);
Florin Coras070453d2018-08-24 17:04:27 -07002191 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002192 }
2193 ASSERT (next_session->vep.prev_sid == session_index);
2194 next_session->vep.prev_sid = session->vep.prev_sid;
2195 }
2196
2197 memset (&session->vep, 0, sizeof (session->vep));
2198 session->vep.next_sid = ~0;
2199 session->vep.prev_sid = ~0;
2200 session->vep.vep_idx = ~0;
2201 session->is_vep_session = 0;
Florin Coras0d427d82018-06-27 03:24:07 -07002202 VDBG (1, "VCL<%d>: EPOLL_CTL_DEL: vep_idx %u, sid %u!",
2203 getpid (), vep_idx, session_index);
2204 vcl_evt (VCL_EVT_EPOLL_CTLDEL, session, vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002205 break;
2206
2207 default:
Dave Wallace048b1d62018-01-03 22:24:41 -05002208 clib_warning ("VCL<%d>: ERROR: Invalid operation (%d)!", getpid (), op);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002209 rv = VPPCOM_EINVAL;
2210 }
2211
2212 vep_verify_epoll_chain (vep_idx);
2213
2214done:
Dave Wallacef7f809c2017-10-03 01:48:42 -04002215 return rv;
2216}
2217
Florin Coras54693d22018-07-17 10:46:29 -07002218static int
2219vcl_epoll_wait_handle_mq (svm_msg_q_t * mq, struct epoll_event *events,
2220 u32 maxevents, double wait_for_time, u32 * num_ev)
2221{
2222 session_disconnected_msg_t *disconnected_msg;
2223 session_connected_msg_t *connected_msg;
2224 session_accepted_msg_t *accepted_msg;
Florin Coras54693d22018-07-17 10:46:29 -07002225 u64 session_evt_data = ~0, handle;
Florin Coras99368312018-08-02 10:45:44 -07002226 u32 sid = ~0, session_events;
Florin Coras54693d22018-07-17 10:46:29 -07002227 vcl_session_msg_t *vcl_msg;
2228 vcl_session_t *session;
Florin Coras99368312018-08-02 10:45:44 -07002229 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07002230 session_event_t *e;
2231 u8 add_event;
2232 int i;
2233
2234 svm_msg_q_lock (mq);
2235 if (svm_msg_q_is_empty (mq))
2236 {
2237 if (!wait_for_time)
2238 {
2239 svm_msg_q_unlock (mq);
2240 return 0;
2241 }
2242 else if (wait_for_time < 0)
2243 {
2244 svm_msg_q_wait (mq);
2245 }
2246 else
2247 {
Florin Coras60f1fc12018-08-16 14:57:31 -07002248 if (svm_msg_q_timedwait (mq, wait_for_time / 1e3))
Florin Coras54693d22018-07-17 10:46:29 -07002249 {
2250 svm_msg_q_unlock (mq);
2251 return 0;
2252 }
2253 }
2254 }
Florin Coras99368312018-08-02 10:45:44 -07002255 vcl_mq_dequeue_batch (mq);
Florin Coras54693d22018-07-17 10:46:29 -07002256 svm_msg_q_unlock (mq);
2257
Florin Coras99368312018-08-02 10:45:44 -07002258 for (i = 0; i < vec_len (vcm->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07002259 {
Florin Coras99368312018-08-02 10:45:44 -07002260 msg = vec_elt_at_index (vcm->mq_msg_vector, i);
2261 e = svm_msg_q_msg_data (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002262 add_event = 0;
2263 switch (e->event_type)
2264 {
2265 case FIFO_EVENT_APP_RX:
2266 sid = e->fifo->client_session_index;
Florin Coras54693d22018-07-17 10:46:29 -07002267 session = vcl_session_get (sid);
2268 session_events = session->vep.ev.events;
Florin Coras99368312018-08-02 10:45:44 -07002269 if (!(EPOLLIN & session->vep.ev.events))
2270 break;
Florin Coras60f1fc12018-08-16 14:57:31 -07002271 add_event = 1;
2272 events[*num_ev].events |= EPOLLIN;
2273 session_evt_data = session->vep.ev.data.u64;
Florin Coras54693d22018-07-17 10:46:29 -07002274 break;
2275 case FIFO_EVENT_APP_TX:
2276 sid = e->fifo->client_session_index;
Florin Coras54693d22018-07-17 10:46:29 -07002277 session = vcl_session_get (sid);
2278 session_events = session->vep.ev.events;
Florin Coras99368312018-08-02 10:45:44 -07002279 if (!(EPOLLOUT & session_events))
2280 break;
Florin Coras60f1fc12018-08-16 14:57:31 -07002281 add_event = 1;
2282 events[*num_ev].events |= EPOLLOUT;
2283 session_evt_data = session->vep.ev.data.u64;
Florin Coras54693d22018-07-17 10:46:29 -07002284 break;
2285 case SESSION_IO_EVT_CT_TX:
2286 session = vcl_ct_session_get_from_fifo (e->fifo, 0);
2287 sid = vcl_session_index (session);
2288 session_events = session->vep.ev.events;
Florin Coras99368312018-08-02 10:45:44 -07002289 if (!(EPOLLIN & session->vep.ev.events))
2290 break;
Florin Coras60f1fc12018-08-16 14:57:31 -07002291 add_event = 1;
2292 events[*num_ev].events |= EPOLLIN;
2293 session_evt_data = session->vep.ev.data.u64;
Florin Coras54693d22018-07-17 10:46:29 -07002294 break;
2295 case SESSION_IO_EVT_CT_RX:
2296 session = vcl_ct_session_get_from_fifo (e->fifo, 1);
2297 sid = vcl_session_index (session);
2298 session_events = session->vep.ev.events;
Florin Coras99368312018-08-02 10:45:44 -07002299 if (!(EPOLLOUT & session_events))
2300 break;
Florin Coras60f1fc12018-08-16 14:57:31 -07002301 add_event = 1;
2302 events[*num_ev].events |= EPOLLOUT;
2303 session_evt_data = session->vep.ev.data.u64;
Florin Coras54693d22018-07-17 10:46:29 -07002304 break;
2305 case SESSION_CTRL_EVT_ACCEPTED:
2306 accepted_msg = (session_accepted_msg_t *) e->data;
2307 handle = accepted_msg->listener_handle;
2308 session = vppcom_session_table_lookup_listener (handle);
2309 if (!session)
2310 {
2311 clib_warning ("VCL<%d>: ERROR: couldn't find listen session:"
2312 "listener handle %llx", getpid (), handle);
2313 break;
2314 }
2315
2316 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
2317 vcl_msg->accepted_msg = *accepted_msg;
2318 session_events = session->vep.ev.events;
2319 if (!(EPOLLIN & session_events))
2320 break;
2321
2322 add_event = 1;
2323 events[*num_ev].events |= EPOLLIN;
2324 session_evt_data = session->vep.ev.data.u64;
2325 break;
2326 case SESSION_CTRL_EVT_CONNECTED:
2327 connected_msg = (session_connected_msg_t *) e->data;
2328 vcl_session_connected_handler (connected_msg);
2329 /* Generate EPOLLOUT because there's no connected event */
2330 sid = vcl_session_get_index_from_handle (connected_msg->handle);
Florin Coras54693d22018-07-17 10:46:29 -07002331 session = vcl_session_get (sid);
2332 session_events = session->vep.ev.events;
2333 if (EPOLLOUT & session_events)
2334 {
2335 add_event = 1;
2336 events[*num_ev].events |= EPOLLOUT;
2337 session_evt_data = session->vep.ev.data.u64;
2338 }
Florin Coras54693d22018-07-17 10:46:29 -07002339 break;
2340 case SESSION_CTRL_EVT_DISCONNECTED:
2341 disconnected_msg = (session_disconnected_msg_t *) e->data;
2342 sid = vcl_session_get_index_from_handle (disconnected_msg->handle);
Florin Corasc9fbd662018-08-24 12:59:56 -07002343 if (!(session = vcl_session_get (sid)))
2344 break;
Florin Coras54693d22018-07-17 10:46:29 -07002345 add_event = 1;
2346 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2347 session_evt_data = session->vep.ev.data.u64;
2348 session_events = session->vep.ev.events;
Florin Coras54693d22018-07-17 10:46:29 -07002349 break;
Florin Corasc9fbd662018-08-24 12:59:56 -07002350 case SESSION_CTRL_EVT_RESET:
Florin Coras60116992018-08-27 09:52:18 -07002351 sid = vcl_session_reset_handler ((session_reset_msg_t *) e->data);
Florin Corasc9fbd662018-08-24 12:59:56 -07002352 if (!(session = vcl_session_get (sid)))
2353 break;
2354 add_event = 1;
2355 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2356 session_evt_data = session->vep.ev.data.u64;
2357 session_events = session->vep.ev.events;
2358 break;
Florin Coras54693d22018-07-17 10:46:29 -07002359 default:
2360 clib_warning ("unhandled: %u", e->event_type);
Florin Coras99368312018-08-02 10:45:44 -07002361 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002362 continue;
2363 }
Florin Coras99368312018-08-02 10:45:44 -07002364 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002365
2366 if (add_event)
2367 {
2368 events[*num_ev].data.u64 = session_evt_data;
2369 if (EPOLLONESHOT & session_events)
2370 {
Florin Coras54693d22018-07-17 10:46:29 -07002371 session = vcl_session_get (sid);
2372 session->vep.ev.events = 0;
Florin Coras54693d22018-07-17 10:46:29 -07002373 }
2374 *num_ev += 1;
2375 if (*num_ev == maxevents)
2376 break;
2377 }
2378 }
Florin Coras99368312018-08-02 10:45:44 -07002379
2380 vec_reset_length (vcm->mq_msg_vector);
Florin Coras54693d22018-07-17 10:46:29 -07002381 return *num_ev;
2382}
2383
Florin Coras99368312018-08-02 10:45:44 -07002384static int
2385vppcom_epoll_wait_condvar (struct epoll_event *events, int maxevents,
2386 double wait_for_time)
2387{
2388 vcl_cut_through_registration_t *cr;
2389 double total_wait = 0, wait_slice;
2390 u32 num_ev = 0;
2391 int rv;
2392
2393 wait_for_time = (wait_for_time == -1) ? (double) 10e9 : wait_for_time;
2394 wait_slice = vcm->cut_through_registrations ? 10e-6 : wait_for_time;
2395
2396 do
2397 {
2398 /* *INDENT-OFF* */
2399 pool_foreach (cr, vcm->cut_through_registrations, ({
2400 vcl_epoll_wait_handle_mq (cr->mq, events, maxevents, 0, &num_ev);
2401 }));
2402 /* *INDENT-ON* */
2403
2404 rv = vcl_epoll_wait_handle_mq (vcm->app_event_queue, events, maxevents,
2405 num_ev ? 0 : wait_slice, &num_ev);
2406 if (rv)
2407 total_wait += wait_slice;
2408 if (num_ev)
2409 return num_ev;
2410 }
2411 while (total_wait < wait_for_time);
2412 return (int) num_ev;
2413}
2414
2415static int
2416vppcom_epoll_wait_eventfd (struct epoll_event *events, int maxevents,
2417 double wait_for_time)
2418{
2419 vcl_mq_evt_conn_t *mqc;
2420 int __clib_unused n_read;
2421 int n_mq_evts, i;
2422 u32 n_evts = 0;
2423 u64 buf;
2424
2425 vec_validate (vcm->mq_events, pool_elts (vcm->mq_evt_conns));
2426 n_mq_evts = epoll_wait (vcm->mqs_epfd, vcm->mq_events,
2427 vec_len (vcm->mq_events), wait_for_time);
2428 for (i = 0; i < n_mq_evts; i++)
2429 {
2430 mqc = vcl_mq_evt_conn_get (vcm->mq_events[i].data.u32);
2431 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
2432 vcl_epoll_wait_handle_mq (mqc->mq, events, maxevents, 0, &n_evts);
2433 }
2434
2435 return (int) n_evts;
2436}
2437
Dave Wallacef7f809c2017-10-03 01:48:42 -04002438int
2439vppcom_epoll_wait (uint32_t vep_idx, struct epoll_event *events,
2440 int maxevents, double wait_for_time)
2441{
Florin Coras7e12d942018-06-27 14:32:43 -07002442 vcl_session_t *vep_session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002443
2444 if (PREDICT_FALSE (maxevents <= 0))
2445 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002446 clib_warning ("VCL<%d>: ERROR: Invalid maxevents (%d)!",
Dave Wallace4878cbe2017-11-21 03:45:09 -05002447 getpid (), maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002448 return VPPCOM_EINVAL;
2449 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002450
Florin Coras54693d22018-07-17 10:46:29 -07002451 vep_session = vcl_session_get (vep_idx);
2452 if (PREDICT_FALSE (!vep_session->is_vep))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002453 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002454 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
Dave Wallace4878cbe2017-11-21 03:45:09 -05002455 getpid (), vep_idx);
Florin Coras54693d22018-07-17 10:46:29 -07002456 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002457 }
Florin Coras54693d22018-07-17 10:46:29 -07002458
2459 memset (events, 0, sizeof (*events) * maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002460
Florin Coras99368312018-08-02 10:45:44 -07002461 if (vcm->cfg.use_mq_eventfd)
2462 return vppcom_epoll_wait_eventfd (events, maxevents, wait_for_time);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002463
Florin Coras99368312018-08-02 10:45:44 -07002464 return vppcom_epoll_wait_condvar (events, maxevents, wait_for_time);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002465}
2466
Dave Wallace35830af2017-10-09 01:43:42 -04002467int
2468vppcom_session_attr (uint32_t session_index, uint32_t op,
2469 void *buffer, uint32_t * buflen)
2470{
Florin Coras7e12d942018-06-27 14:32:43 -07002471 vcl_session_t *session;
Dave Wallace35830af2017-10-09 01:43:42 -04002472 int rv = VPPCOM_OK;
2473 u32 *flags = buffer;
Steven2199aab2017-10-15 20:18:47 -07002474 vppcom_endpt_t *ep = buffer;
Dave Wallace35830af2017-10-09 01:43:42 -04002475
Florin Coras070453d2018-08-24 17:04:27 -07002476 session = vcl_session_get (session_index);
2477 if (!session)
2478 return VPPCOM_EBADFD;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002479
Dave Wallace35830af2017-10-09 01:43:42 -04002480 switch (op)
2481 {
2482 case VPPCOM_ATTR_GET_NREAD:
Florin Coras54693d22018-07-17 10:46:29 -07002483 rv = vppcom_session_read_ready (session);
Florin Coras0d427d82018-06-27 03:24:07 -07002484 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d",
2485 getpid (), rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002486 break;
2487
Dave Wallace227867f2017-11-13 21:21:53 -05002488 case VPPCOM_ATTR_GET_NWRITE:
2489 rv = vppcom_session_write_ready (session, session_index);
Florin Coras0d427d82018-06-27 03:24:07 -07002490 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d",
2491 getpid (), session_index, rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002492 break;
2493
2494 case VPPCOM_ATTR_GET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002495 if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002496 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002497 *flags = O_RDWR | (VCL_SESS_ATTR_TEST (session->attr,
2498 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002499 *buflen = sizeof (*flags);
Florin Coras0d427d82018-06-27 03:24:07 -07002500 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_FLAGS: sid %u, flags = 0x%08x, "
2501 "is_nonblocking = %u", getpid (),
2502 session_index, *flags,
2503 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002504 }
2505 else
2506 rv = VPPCOM_EINVAL;
2507 break;
2508
2509 case VPPCOM_ATTR_SET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002510 if (PREDICT_TRUE (buffer && buflen && (*buflen == sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002511 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002512 if (*flags & O_NONBLOCK)
2513 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
2514 else
2515 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_NONBLOCK);
2516
Florin Coras0d427d82018-06-27 03:24:07 -07002517 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_FLAGS: sid %u, flags = 0x%08x,"
2518 " is_nonblocking = %u",
2519 getpid (), session_index, *flags,
2520 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002521 }
2522 else
2523 rv = VPPCOM_EINVAL;
2524 break;
2525
2526 case VPPCOM_ATTR_GET_PEER_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002527 if (PREDICT_TRUE (buffer && buflen &&
2528 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002529 {
Florin Coras7e12d942018-06-27 14:32:43 -07002530 ep->is_ip4 = session->transport.is_ip4;
2531 ep->port = session->transport.rmt_port;
2532 if (session->transport.is_ip4)
2533 clib_memcpy (ep->ip, &session->transport.rmt_ip.ip4,
Steven2199aab2017-10-15 20:18:47 -07002534 sizeof (ip4_address_t));
2535 else
Florin Coras7e12d942018-06-27 14:32:43 -07002536 clib_memcpy (ep->ip, &session->transport.rmt_ip.ip6,
Steven2199aab2017-10-15 20:18:47 -07002537 sizeof (ip6_address_t));
2538 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07002539 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = %u, "
2540 "addr = %U, port %u", getpid (),
2541 session_index, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07002542 &session->transport.rmt_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002543 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2544 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002545 }
2546 else
2547 rv = VPPCOM_EINVAL;
2548 break;
2549
2550 case VPPCOM_ATTR_GET_LCL_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002551 if (PREDICT_TRUE (buffer && buflen &&
2552 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002553 {
Florin Coras7e12d942018-06-27 14:32:43 -07002554 ep->is_ip4 = session->transport.is_ip4;
2555 ep->port = session->transport.lcl_port;
2556 if (session->transport.is_ip4)
2557 clib_memcpy (ep->ip, &session->transport.lcl_ip.ip4,
Steven2199aab2017-10-15 20:18:47 -07002558 sizeof (ip4_address_t));
2559 else
Florin Coras7e12d942018-06-27 14:32:43 -07002560 clib_memcpy (ep->ip, &session->transport.lcl_ip.ip6,
Steven2199aab2017-10-15 20:18:47 -07002561 sizeof (ip6_address_t));
2562 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07002563 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = %u,"
2564 " addr = %U port %d", getpid (),
2565 session_index, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07002566 &session->transport.lcl_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002567 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2568 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002569 }
2570 else
2571 rv = VPPCOM_EINVAL;
2572 break;
Stevenb5a11602017-10-11 09:59:30 -07002573
Dave Wallace048b1d62018-01-03 22:24:41 -05002574 case VPPCOM_ATTR_GET_LIBC_EPFD:
2575 rv = session->libc_epfd;
Florin Coras0d427d82018-06-27 03:24:07 -07002576 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d",
2577 getpid (), rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002578 break;
2579
2580 case VPPCOM_ATTR_SET_LIBC_EPFD:
2581 if (PREDICT_TRUE (buffer && buflen &&
2582 (*buflen == sizeof (session->libc_epfd))))
2583 {
2584 session->libc_epfd = *(int *) buffer;
2585 *buflen = sizeof (session->libc_epfd);
2586
Florin Coras0d427d82018-06-27 03:24:07 -07002587 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_LIBC_EPFD: libc_epfd %d, "
2588 "buflen %d", getpid (), session->libc_epfd, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002589 }
2590 else
2591 rv = VPPCOM_EINVAL;
2592 break;
2593
2594 case VPPCOM_ATTR_GET_PROTOCOL:
2595 if (buffer && buflen && (*buflen >= sizeof (int)))
2596 {
Florin Coras7e12d942018-06-27 14:32:43 -07002597 *(int *) buffer = session->session_type;
Dave Wallace048b1d62018-01-03 22:24:41 -05002598 *buflen = sizeof (int);
2599
Florin Coras0d427d82018-06-27 03:24:07 -07002600 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_PROTOCOL: %d (%s), buflen %d",
2601 getpid (), *(int *) buffer, *(int *) buffer ? "UDP" : "TCP",
2602 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002603 }
2604 else
2605 rv = VPPCOM_EINVAL;
2606 break;
2607
2608 case VPPCOM_ATTR_GET_LISTEN:
2609 if (buffer && buflen && (*buflen >= sizeof (int)))
2610 {
2611 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2612 VCL_SESS_ATTR_LISTEN);
2613 *buflen = sizeof (int);
2614
Florin Coras0d427d82018-06-27 03:24:07 -07002615 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LISTEN: %d, buflen %d",
2616 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002617 }
2618 else
2619 rv = VPPCOM_EINVAL;
2620 break;
2621
2622 case VPPCOM_ATTR_GET_ERROR:
2623 if (buffer && buflen && (*buflen >= sizeof (int)))
2624 {
2625 *(int *) buffer = 0;
2626 *buflen = sizeof (int);
2627
Florin Coras0d427d82018-06-27 03:24:07 -07002628 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_ERROR: %d, buflen %d, #VPP-TBD#",
2629 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002630 }
2631 else
2632 rv = VPPCOM_EINVAL;
2633 break;
2634
2635 case VPPCOM_ATTR_GET_TX_FIFO_LEN:
2636 if (buffer && buflen && (*buflen >= sizeof (u32)))
2637 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002638
2639 /* VPP-TBD */
2640 *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002641 session->tx_fifo ? session->tx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05002642 vcm->cfg.tx_fifo_size);
2643 *buflen = sizeof (u32);
2644
Florin Coras0d427d82018-06-27 03:24:07 -07002645 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), "
2646 "buflen %d, #VPP-TBD#", getpid (),
2647 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002648 }
2649 else
2650 rv = VPPCOM_EINVAL;
2651 break;
2652
2653 case VPPCOM_ATTR_SET_TX_FIFO_LEN:
2654 if (buffer && buflen && (*buflen == sizeof (u32)))
2655 {
2656 /* VPP-TBD */
2657 session->sndbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07002658 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), "
2659 "buflen %d, #VPP-TBD#", getpid (),
2660 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002661 }
2662 else
2663 rv = VPPCOM_EINVAL;
2664 break;
2665
2666 case VPPCOM_ATTR_GET_RX_FIFO_LEN:
2667 if (buffer && buflen && (*buflen >= sizeof (u32)))
2668 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002669
2670 /* VPP-TBD */
2671 *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002672 session->rx_fifo ? session->rx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05002673 vcm->cfg.rx_fifo_size);
2674 *buflen = sizeof (u32);
2675
Florin Coras0d427d82018-06-27 03:24:07 -07002676 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_RX_FIFO_LEN: %u (0x%x), "
2677 "buflen %d, #VPP-TBD#", getpid (),
2678 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002679 }
2680 else
2681 rv = VPPCOM_EINVAL;
2682 break;
2683
2684 case VPPCOM_ATTR_SET_RX_FIFO_LEN:
2685 if (buffer && buflen && (*buflen == sizeof (u32)))
2686 {
2687 /* VPP-TBD */
2688 session->rcvbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07002689 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_RX_FIFO_LEN: %u (0x%x), "
2690 "buflen %d, #VPP-TBD#", getpid (),
2691 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002692 }
2693 else
2694 rv = VPPCOM_EINVAL;
2695 break;
2696
2697 case VPPCOM_ATTR_GET_REUSEADDR:
2698 if (buffer && buflen && (*buflen >= sizeof (int)))
2699 {
2700 /* VPP-TBD */
2701 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2702 VCL_SESS_ATTR_REUSEADDR);
2703 *buflen = sizeof (int);
2704
Florin Coras0d427d82018-06-27 03:24:07 -07002705 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEADDR: %d, "
2706 "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002707 }
2708 else
2709 rv = VPPCOM_EINVAL;
2710 break;
2711
Stevenb5a11602017-10-11 09:59:30 -07002712 case VPPCOM_ATTR_SET_REUSEADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002713 if (buffer && buflen && (*buflen == sizeof (int)) &&
2714 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
2715 {
2716 /* VPP-TBD */
2717 if (*(int *) buffer)
2718 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEADDR);
2719 else
2720 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEADDR);
2721
Florin Coras0d427d82018-06-27 03:24:07 -07002722 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEADDR: %d, buflen %d,"
2723 " #VPP-TBD#", getpid (),
2724 VCL_SESS_ATTR_TEST (session->attr,
2725 VCL_SESS_ATTR_REUSEADDR), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002726 }
2727 else
2728 rv = VPPCOM_EINVAL;
2729 break;
2730
2731 case VPPCOM_ATTR_GET_REUSEPORT:
2732 if (buffer && buflen && (*buflen >= sizeof (int)))
2733 {
2734 /* VPP-TBD */
2735 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2736 VCL_SESS_ATTR_REUSEPORT);
2737 *buflen = sizeof (int);
2738
Florin Coras0d427d82018-06-27 03:24:07 -07002739 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEPORT: %d, buflen %d,"
2740 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002741 }
2742 else
2743 rv = VPPCOM_EINVAL;
2744 break;
2745
2746 case VPPCOM_ATTR_SET_REUSEPORT:
2747 if (buffer && buflen && (*buflen == sizeof (int)) &&
2748 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
2749 {
2750 /* VPP-TBD */
2751 if (*(int *) buffer)
2752 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEPORT);
2753 else
2754 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEPORT);
2755
Florin Coras0d427d82018-06-27 03:24:07 -07002756 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEPORT: %d, buflen %d,"
2757 " #VPP-TBD#", getpid (),
2758 VCL_SESS_ATTR_TEST (session->attr,
2759 VCL_SESS_ATTR_REUSEPORT), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002760 }
2761 else
2762 rv = VPPCOM_EINVAL;
2763 break;
2764
2765 case VPPCOM_ATTR_GET_BROADCAST:
2766 if (buffer && buflen && (*buflen >= sizeof (int)))
2767 {
2768 /* VPP-TBD */
2769 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2770 VCL_SESS_ATTR_BROADCAST);
2771 *buflen = sizeof (int);
2772
Florin Coras0d427d82018-06-27 03:24:07 -07002773 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_BROADCAST: %d, buflen %d,"
2774 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002775 }
2776 else
2777 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07002778 break;
2779
2780 case VPPCOM_ATTR_SET_BROADCAST:
Dave Wallace048b1d62018-01-03 22:24:41 -05002781 if (buffer && buflen && (*buflen == sizeof (int)))
2782 {
2783 /* VPP-TBD */
2784 if (*(int *) buffer)
2785 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_BROADCAST);
2786 else
2787 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_BROADCAST);
2788
Florin Coras0d427d82018-06-27 03:24:07 -07002789 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_BROADCAST: %d, buflen %d, "
2790 "#VPP-TBD#", getpid (),
2791 VCL_SESS_ATTR_TEST (session->attr,
2792 VCL_SESS_ATTR_BROADCAST), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002793 }
2794 else
2795 rv = VPPCOM_EINVAL;
2796 break;
2797
2798 case VPPCOM_ATTR_GET_V6ONLY:
2799 if (buffer && buflen && (*buflen >= sizeof (int)))
2800 {
2801 /* VPP-TBD */
2802 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2803 VCL_SESS_ATTR_V6ONLY);
2804 *buflen = sizeof (int);
2805
Florin Coras0d427d82018-06-27 03:24:07 -07002806 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_V6ONLY: %d, buflen %d, "
2807 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002808 }
2809 else
2810 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07002811 break;
2812
2813 case VPPCOM_ATTR_SET_V6ONLY:
Dave Wallace048b1d62018-01-03 22:24:41 -05002814 if (buffer && buflen && (*buflen == sizeof (int)))
2815 {
2816 /* VPP-TBD */
2817 if (*(int *) buffer)
2818 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_V6ONLY);
2819 else
2820 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_V6ONLY);
2821
Florin Coras0d427d82018-06-27 03:24:07 -07002822 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_V6ONLY: %d, buflen %d, "
2823 "#VPP-TBD#", getpid (),
2824 VCL_SESS_ATTR_TEST (session->attr,
2825 VCL_SESS_ATTR_V6ONLY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002826 }
2827 else
2828 rv = VPPCOM_EINVAL;
2829 break;
2830
2831 case VPPCOM_ATTR_GET_KEEPALIVE:
2832 if (buffer && buflen && (*buflen >= sizeof (int)))
2833 {
2834 /* VPP-TBD */
2835 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2836 VCL_SESS_ATTR_KEEPALIVE);
2837 *buflen = sizeof (int);
2838
Florin Coras0d427d82018-06-27 03:24:07 -07002839 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_KEEPALIVE: %d, buflen %d, "
2840 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002841 }
2842 else
2843 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07002844 break;
Stevenbccd3392017-10-12 20:42:21 -07002845
2846 case VPPCOM_ATTR_SET_KEEPALIVE:
Dave Wallace048b1d62018-01-03 22:24:41 -05002847 if (buffer && buflen && (*buflen == sizeof (int)))
2848 {
2849 /* VPP-TBD */
2850 if (*(int *) buffer)
2851 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_KEEPALIVE);
2852 else
2853 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_KEEPALIVE);
2854
Florin Coras0d427d82018-06-27 03:24:07 -07002855 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_KEEPALIVE: %d, buflen %d, "
2856 "#VPP-TBD#", getpid (),
2857 VCL_SESS_ATTR_TEST (session->attr,
2858 VCL_SESS_ATTR_KEEPALIVE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002859 }
2860 else
2861 rv = VPPCOM_EINVAL;
2862 break;
2863
2864 case VPPCOM_ATTR_GET_TCP_NODELAY:
2865 if (buffer && buflen && (*buflen >= sizeof (int)))
2866 {
2867 /* VPP-TBD */
2868 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2869 VCL_SESS_ATTR_TCP_NODELAY);
2870 *buflen = sizeof (int);
2871
Florin Coras0d427d82018-06-27 03:24:07 -07002872 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_NODELAY: %d, buflen %d, "
2873 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002874 }
2875 else
2876 rv = VPPCOM_EINVAL;
2877 break;
2878
2879 case VPPCOM_ATTR_SET_TCP_NODELAY:
2880 if (buffer && buflen && (*buflen == sizeof (int)))
2881 {
2882 /* VPP-TBD */
2883 if (*(int *) buffer)
2884 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
2885 else
2886 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
2887
Florin Coras0d427d82018-06-27 03:24:07 -07002888 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_NODELAY: %d, buflen %d, "
2889 "#VPP-TBD#", getpid (),
2890 VCL_SESS_ATTR_TEST (session->attr,
2891 VCL_SESS_ATTR_TCP_NODELAY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002892 }
2893 else
2894 rv = VPPCOM_EINVAL;
2895 break;
2896
2897 case VPPCOM_ATTR_GET_TCP_KEEPIDLE:
2898 if (buffer && buflen && (*buflen >= sizeof (int)))
2899 {
2900 /* VPP-TBD */
2901 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2902 VCL_SESS_ATTR_TCP_KEEPIDLE);
2903 *buflen = sizeof (int);
2904
Florin Coras0d427d82018-06-27 03:24:07 -07002905 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPIDLE: %d, buflen %d, "
2906 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002907 }
2908 else
2909 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07002910 break;
2911
2912 case VPPCOM_ATTR_SET_TCP_KEEPIDLE:
Dave Wallace048b1d62018-01-03 22:24:41 -05002913 if (buffer && buflen && (*buflen == sizeof (int)))
2914 {
2915 /* VPP-TBD */
2916 if (*(int *) buffer)
2917 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
2918 else
2919 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
2920
Florin Coras0d427d82018-06-27 03:24:07 -07002921 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPIDLE: %d, buflen %d, "
2922 "#VPP-TBD#", getpid (),
2923 VCL_SESS_ATTR_TEST (session->attr,
2924 VCL_SESS_ATTR_TCP_KEEPIDLE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002925 }
2926 else
2927 rv = VPPCOM_EINVAL;
2928 break;
2929
2930 case VPPCOM_ATTR_GET_TCP_KEEPINTVL:
2931 if (buffer && buflen && (*buflen >= sizeof (int)))
2932 {
2933 /* VPP-TBD */
2934 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2935 VCL_SESS_ATTR_TCP_KEEPINTVL);
2936 *buflen = sizeof (int);
2937
Florin Coras0d427d82018-06-27 03:24:07 -07002938 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPINTVL: %d, buflen %d, "
2939 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002940 }
2941 else
2942 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07002943 break;
2944
2945 case VPPCOM_ATTR_SET_TCP_KEEPINTVL:
Dave Wallace048b1d62018-01-03 22:24:41 -05002946 if (buffer && buflen && (*buflen == sizeof (int)))
2947 {
2948 /* VPP-TBD */
2949 if (*(int *) buffer)
2950 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
2951 else
2952 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
2953
Florin Coras0d427d82018-06-27 03:24:07 -07002954 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPINTVL: %d, buflen %d, "
2955 "#VPP-TBD#", getpid (),
2956 VCL_SESS_ATTR_TEST (session->attr,
2957 VCL_SESS_ATTR_TCP_KEEPINTVL), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002958 }
2959 else
2960 rv = VPPCOM_EINVAL;
2961 break;
2962
2963 case VPPCOM_ATTR_GET_TCP_USER_MSS:
2964 if (buffer && buflen && (*buflen >= sizeof (u32)))
2965 {
2966 /* VPP-TBD */
2967 *(u32 *) buffer = session->user_mss;
2968 *buflen = sizeof (int);
2969
Florin Coras0d427d82018-06-27 03:24:07 -07002970 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d,"
2971 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002972 }
2973 else
2974 rv = VPPCOM_EINVAL;
2975 break;
2976
2977 case VPPCOM_ATTR_SET_TCP_USER_MSS:
2978 if (buffer && buflen && (*buflen == sizeof (u32)))
2979 {
2980 /* VPP-TBD */
2981 session->user_mss = *(u32 *) buffer;
2982
Florin Coras0d427d82018-06-27 03:24:07 -07002983 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_USER_MSS: %u, buflen %d, "
2984 "#VPP-TBD#", getpid (), session->user_mss, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002985 }
2986 else
2987 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07002988 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04002989
2990 default:
2991 rv = VPPCOM_EINVAL;
2992 break;
Dave Wallace35830af2017-10-09 01:43:42 -04002993 }
2994
Dave Wallace35830af2017-10-09 01:43:42 -04002995 return rv;
2996}
2997
Stevenac1f96d2017-10-24 16:03:58 -07002998int
2999vppcom_session_recvfrom (uint32_t session_index, void *buffer,
3000 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3001{
Stevenac1f96d2017-10-24 16:03:58 -07003002 int rv = VPPCOM_OK;
Florin Coras7e12d942018-06-27 14:32:43 -07003003 vcl_session_t *session = 0;
Stevenac1f96d2017-10-24 16:03:58 -07003004
3005 if (ep)
3006 {
Florin Coras070453d2018-08-24 17:04:27 -07003007 session = vcl_session_get (session_index);
3008 if (PREDICT_FALSE (!session))
Stevenac1f96d2017-10-24 16:03:58 -07003009 {
Florin Coras0d427d82018-06-27 03:24:07 -07003010 VDBG (0, "VCL<%d>: invalid session, sid (%u) has been closed!",
3011 getpid (), session_index);
Florin Coras460dce62018-07-27 05:45:06 -07003012 return VPPCOM_EBADFD;
Stevenac1f96d2017-10-24 16:03:58 -07003013 }
Florin Coras7e12d942018-06-27 14:32:43 -07003014 ep->is_ip4 = session->transport.is_ip4;
3015 ep->port = session->transport.rmt_port;
Stevenac1f96d2017-10-24 16:03:58 -07003016 }
Steven58f464e2017-10-25 12:33:12 -07003017
3018 if (flags == 0)
Stevenac1f96d2017-10-24 16:03:58 -07003019 rv = vppcom_session_read (session_index, buffer, buflen);
3020 else if (flags & MSG_PEEK)
Steven58f464e2017-10-25 12:33:12 -07003021 rv = vppcom_session_peek (session_index, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003022 else
3023 {
Dave Wallace048b1d62018-01-03 22:24:41 -05003024 clib_warning ("VCL<%d>: Unsupport flags for recvfrom %d",
3025 getpid (), flags);
Florin Coras460dce62018-07-27 05:45:06 -07003026 return VPPCOM_EAFNOSUPPORT;
Stevenac1f96d2017-10-24 16:03:58 -07003027 }
3028
Florin Coras99368312018-08-02 10:45:44 -07003029 if (ep)
3030 {
3031 if (session->transport.is_ip4)
3032 clib_memcpy (ep->ip, &session->transport.rmt_ip.ip4,
3033 sizeof (ip4_address_t));
3034 else
3035 clib_memcpy (ep->ip, &session->transport.rmt_ip.ip6,
3036 sizeof (ip6_address_t));
3037 }
Florin Coras460dce62018-07-27 05:45:06 -07003038
Stevenac1f96d2017-10-24 16:03:58 -07003039 return rv;
3040}
3041
3042int
3043vppcom_session_sendto (uint32_t session_index, void *buffer,
3044 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3045{
Dave Wallace617dffa2017-10-26 14:47:06 -04003046 if (!buffer)
3047 return VPPCOM_EINVAL;
3048
3049 if (ep)
3050 {
3051 // TBD
3052 return VPPCOM_EINVAL;
3053 }
3054
3055 if (flags)
3056 {
3057 // TBD check the flags and do the right thing
Florin Coras0d427d82018-06-27 03:24:07 -07003058 VDBG (2, "VCL<%d>: handling flags 0x%u (%d) not implemented yet.",
3059 getpid (), flags, flags);
Dave Wallace617dffa2017-10-26 14:47:06 -04003060 }
3061
3062 return (vppcom_session_write (session_index, buffer, buflen));
Stevenac1f96d2017-10-24 16:03:58 -07003063}
3064
Dave Wallace048b1d62018-01-03 22:24:41 -05003065int
3066vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time)
3067{
3068 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
3069 u32 i, keep_trying = 1;
3070 int rv, num_ev = 0;
3071
Florin Coras0d427d82018-06-27 03:24:07 -07003072 VDBG (3, "VCL<%d>: vp %p, nsids %u, wait_for_time %f",
3073 getpid (), vp, n_sids, wait_for_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05003074
3075 if (!vp)
3076 return VPPCOM_EFAULT;
3077
3078 do
3079 {
Florin Coras7e12d942018-06-27 14:32:43 -07003080 vcl_session_t *session;
Dave Wallace048b1d62018-01-03 22:24:41 -05003081
3082 for (i = 0; i < n_sids; i++)
3083 {
3084 ASSERT (vp[i].revents);
3085
Florin Coras070453d2018-08-24 17:04:27 -07003086 session = vcl_session_get (vp[i].sid);
3087 if (!session)
3088 continue;
Dave Wallace048b1d62018-01-03 22:24:41 -05003089
3090 if (*vp[i].revents)
3091 *vp[i].revents = 0;
3092
3093 if (POLLIN & vp[i].events)
3094 {
Florin Coras54693d22018-07-17 10:46:29 -07003095 rv = vppcom_session_read_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003096 if (rv > 0)
3097 {
3098 *vp[i].revents |= POLLIN;
3099 num_ev++;
3100 }
3101 else if (rv < 0)
3102 {
3103 switch (rv)
3104 {
3105 case VPPCOM_ECONNRESET:
3106 *vp[i].revents = POLLHUP;
3107 break;
3108
3109 default:
3110 *vp[i].revents = POLLERR;
3111 break;
3112 }
3113 num_ev++;
3114 }
3115 }
3116
3117 if (POLLOUT & vp[i].events)
3118 {
Dave Wallace048b1d62018-01-03 22:24:41 -05003119 rv = vppcom_session_write_ready (session, vp[i].sid);
Dave Wallace048b1d62018-01-03 22:24:41 -05003120 if (rv > 0)
3121 {
3122 *vp[i].revents |= POLLOUT;
3123 num_ev++;
3124 }
3125 else if (rv < 0)
3126 {
3127 switch (rv)
3128 {
3129 case VPPCOM_ECONNRESET:
3130 *vp[i].revents = POLLHUP;
3131 break;
3132
3133 default:
3134 *vp[i].revents = POLLERR;
3135 break;
3136 }
3137 num_ev++;
3138 }
3139 }
3140
Dave Wallace7e607a72018-06-18 18:41:32 -04003141 if (0) // Note "done:" label used by VCL_SESSION_LOCK_AND_GET()
Dave Wallace048b1d62018-01-03 22:24:41 -05003142 {
Dave Wallace048b1d62018-01-03 22:24:41 -05003143 *vp[i].revents = POLLNVAL;
3144 num_ev++;
3145 }
3146 }
3147 if (wait_for_time != -1)
3148 keep_trying = (clib_time_now (&vcm->clib_time) <= timeout) ? 1 : 0;
3149 }
3150 while ((num_ev == 0) && keep_trying);
3151
3152 if (VPPCOM_DEBUG > 3)
3153 {
3154 clib_warning ("VCL<%d>: returning %d", getpid (), num_ev);
3155 for (i = 0; i < n_sids; i++)
3156 {
3157 clib_warning ("VCL<%d>: vp[%d].sid %d (0x%x), .events 0x%x, "
3158 ".revents 0x%x", getpid (), i, vp[i].sid, vp[i].sid,
3159 vp[i].events, *vp[i].revents);
3160 }
3161 }
3162 return num_ev;
3163}
3164
Florin Coras99368312018-08-02 10:45:44 -07003165int
3166vppcom_mq_epoll_fd (void)
3167{
3168 return vcm->mqs_epfd;
3169}
3170
Dave Wallacee22aa742017-10-20 12:30:38 -04003171/*
3172 * fd.io coding-style-patch-verification: ON
3173 *
3174 * Local Variables:
3175 * eval: (c-set-style "gnu")
3176 * End:
3177 */