blob: 263fa91623171a35eb57294b3b81a73ae49d448a [file] [log] [blame]
Dave Wallace543852a2017-08-03 02:11:34 -04001/*
Florin Coras5e062572019-03-14 19:07:51 -07002 * Copyright (c) 2017-2019 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 Wallace5c7cf1c2017-10-24 04:12:18 -040018#include <vcl/vppcom.h>
Florin Coras0d427d82018-06-27 03:24:07 -070019#include <vcl/vcl_debug.h>
Florin Coras697faea2018-06-27 17:10:49 -070020#include <vcl/vcl_private.h>
Florin Coras88001c62019-04-24 14:44:46 -070021#include <svm/fifo_segment.h>
Dave Wallace7e607a72018-06-18 18:41:32 -040022
Florin Coras134a9962018-08-28 11:32:04 -070023__thread uword __vcl_worker_index = ~0;
24
Florin Corasd85de682018-11-29 17:02:29 -080025static int
26vcl_wait_for_segment (u64 segment_handle)
Florin Coras54693d22018-07-17 10:46:29 -070027{
Florin Corasd85de682018-11-29 17:02:29 -080028 vcl_worker_t *wrk = vcl_worker_get_current ();
29 u32 wait_for_seconds = 10, segment_index;
30 f64 timeout;
Florin Coras54693d22018-07-17 10:46:29 -070031
Florin Corasd85de682018-11-29 17:02:29 -080032 if (segment_handle == VCL_INVALID_SEGMENT_HANDLE)
Florin Coras5f45e012019-01-23 09:21:30 -080033 return 0;
Florin Coras54693d22018-07-17 10:46:29 -070034
Florin Corasd85de682018-11-29 17:02:29 -080035 timeout = clib_time_now (&wrk->clib_time) + wait_for_seconds;
36 while (clib_time_now (&wrk->clib_time) < timeout)
Florin Coras54693d22018-07-17 10:46:29 -070037 {
Florin Corasd85de682018-11-29 17:02:29 -080038 segment_index = vcl_segment_table_lookup (segment_handle);
39 if (segment_index != VCL_INVALID_SEGMENT_INDEX)
40 return 0;
41 usleep (10);
Florin Coras54693d22018-07-17 10:46:29 -070042 }
Florin Corasd85de682018-11-29 17:02:29 -080043 return 1;
Florin Coras54693d22018-07-17 10:46:29 -070044}
45
Florin Coras30e79c22019-01-02 19:31:22 -080046static inline int
Florin Corase003a1b2019-06-05 10:47:16 -070047vcl_mq_dequeue_batch (vcl_worker_t * wrk, svm_msg_q_t * mq, u32 n_max_msg)
Florin Coras30e79c22019-01-02 19:31:22 -080048{
49 svm_msg_q_msg_t *msg;
50 u32 n_msgs;
51 int i;
52
Florin Corase003a1b2019-06-05 10:47:16 -070053 n_msgs = clib_min (svm_msg_q_size (mq), n_max_msg);
Florin Coras30e79c22019-01-02 19:31:22 -080054 for (i = 0; i < n_msgs; i++)
55 {
56 vec_add2 (wrk->mq_msg_vector, msg, 1);
57 svm_msg_q_sub_w_lock (mq, msg);
58 }
59 return n_msgs;
60}
61
Florin Coras697faea2018-06-27 17:10:49 -070062const char *
Florin Coras288eaab2019-02-03 15:26:14 -080063vppcom_session_state_str (vcl_session_state_t state)
Dave Wallace543852a2017-08-03 02:11:34 -040064{
65 char *st;
66
67 switch (state)
68 {
69 case STATE_START:
70 st = "STATE_START";
71 break;
72
73 case STATE_CONNECT:
74 st = "STATE_CONNECT";
75 break;
76
77 case STATE_LISTEN:
78 st = "STATE_LISTEN";
79 break;
80
81 case STATE_ACCEPT:
82 st = "STATE_ACCEPT";
83 break;
84
Florin Coras3c7d4f92018-12-14 11:28:43 -080085 case STATE_VPP_CLOSING:
86 st = "STATE_VPP_CLOSING";
Dave Wallace4878cbe2017-11-21 03:45:09 -050087 break;
88
Dave Wallace543852a2017-08-03 02:11:34 -040089 case STATE_DISCONNECT:
90 st = "STATE_DISCONNECT";
91 break;
92
93 case STATE_FAILED:
94 st = "STATE_FAILED";
95 break;
96
Florin Coras2d675d72019-01-28 15:54:27 -080097 case STATE_UPDATED:
98 st = "STATE_UPDATED";
99 break;
100
101 case STATE_LISTEN_NO_MQ:
102 st = "STATE_LISTEN_NO_MQ";
103 break;
104
Dave Wallace543852a2017-08-03 02:11:34 -0400105 default:
106 st = "UNKNOWN_STATE";
107 break;
108 }
109
110 return st;
111}
112
Dave Wallace543852a2017-08-03 02:11:34 -0400113u8 *
114format_ip4_address (u8 * s, va_list * args)
115{
116 u8 *a = va_arg (*args, u8 *);
117 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
118}
119
120u8 *
121format_ip6_address (u8 * s, va_list * args)
122{
123 ip6_address_t *a = va_arg (*args, ip6_address_t *);
124 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
125
126 i_max_n_zero = ARRAY_LEN (a->as_u16);
127 max_n_zeros = 0;
128 i_first_zero = i_max_n_zero;
129 n_zeros = 0;
130 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
131 {
132 u32 is_zero = a->as_u16[i] == 0;
133 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
134 {
135 i_first_zero = i;
136 n_zeros = 0;
137 }
138 n_zeros += is_zero;
139 if ((!is_zero && n_zeros > max_n_zeros)
140 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
141 {
142 i_max_n_zero = i_first_zero;
143 max_n_zeros = n_zeros;
144 i_first_zero = ARRAY_LEN (a->as_u16);
145 n_zeros = 0;
146 }
147 }
148
149 last_double_colon = 0;
150 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
151 {
152 if (i == i_max_n_zero && max_n_zeros > 1)
153 {
154 s = format (s, "::");
155 i += max_n_zeros - 1;
156 last_double_colon = 1;
157 }
158 else
159 {
160 s = format (s, "%s%x",
161 (last_double_colon || i == 0) ? "" : ":",
162 clib_net_to_host_u16 (a->as_u16[i]));
163 last_double_colon = 0;
164 }
165 }
166
167 return s;
168}
169
170/* Format an IP46 address. */
171u8 *
172format_ip46_address (u8 * s, va_list * args)
173{
174 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
175 ip46_type_t type = va_arg (*args, ip46_type_t);
176 int is_ip4 = 1;
177
178 switch (type)
179 {
180 case IP46_TYPE_ANY:
181 is_ip4 = ip46_address_is_ip4 (ip46);
182 break;
183 case IP46_TYPE_IP4:
184 is_ip4 = 1;
185 break;
186 case IP46_TYPE_IP6:
187 is_ip4 = 0;
188 break;
189 }
190
191 return is_ip4 ?
192 format (s, "%U", format_ip4_address, &ip46->ip4) :
193 format (s, "%U", format_ip6_address, &ip46->ip6);
194}
195
Florin Coras697faea2018-06-27 17:10:49 -0700196/*
197 * VPPCOM Utility Functions
198 */
199
Florin Coras458089b2019-08-21 16:20:44 -0700200static void
201vcl_send_session_listen (vcl_worker_t * wrk, vcl_session_t * s)
202{
203 app_session_evt_t _app_evt, *app_evt = &_app_evt;
204 session_listen_msg_t *mp;
205 svm_msg_q_t *mq;
206
207 mq = vcl_worker_ctrl_mq (wrk);
208 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_LISTEN);
209 mp = (session_listen_msg_t *) app_evt->evt->data;
210 memset (mp, 0, sizeof (*mp));
211 mp->client_index = wrk->my_client_index;
212 mp->context = s->session_index;
213 mp->wrk_index = wrk->vpp_wrk_index;
214 mp->is_ip4 = s->transport.is_ip4;
215 clib_memcpy_fast (&mp->ip, &s->transport.lcl_ip, sizeof (mp->ip));
216 mp->port = s->transport.lcl_port;
217 mp->proto = s->session_type;
218 app_send_ctrl_evt_to_vpp (mq, app_evt);
219}
220
221static void
222vcl_send_session_connect (vcl_worker_t * wrk, vcl_session_t * s)
223{
224 app_session_evt_t _app_evt, *app_evt = &_app_evt;
225 session_connect_msg_t *mp;
226 svm_msg_q_t *mq;
227
228 mq = vcl_worker_ctrl_mq (wrk);
229 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_CONNECT);
230 mp = (session_connect_msg_t *) app_evt->evt->data;
231 memset (mp, 0, sizeof (*mp));
232 mp->client_index = wrk->my_client_index;
233 mp->context = s->session_index;
234 mp->wrk_index = wrk->vpp_wrk_index;
235 mp->is_ip4 = s->transport.is_ip4;
236 mp->parent_handle = s->parent_handle;
237 clib_memcpy_fast (&mp->ip, &s->transport.rmt_ip, sizeof (mp->ip));
Florin Corasef7cbf62019-10-17 09:56:27 -0700238 clib_memcpy_fast (&mp->lcl_ip, &s->transport.lcl_ip, sizeof (mp->lcl_ip));
Florin Coras458089b2019-08-21 16:20:44 -0700239 mp->port = s->transport.rmt_port;
240 mp->proto = s->session_type;
241 app_send_ctrl_evt_to_vpp (mq, app_evt);
242}
243
244void
245vcl_send_session_unlisten (vcl_worker_t * wrk, vcl_session_t * s)
246{
247 app_session_evt_t _app_evt, *app_evt = &_app_evt;
248 session_unlisten_msg_t *mp;
249 svm_msg_q_t *mq;
250
251 mq = vcl_worker_ctrl_mq (wrk);
252 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_UNLISTEN);
253 mp = (session_unlisten_msg_t *) app_evt->evt->data;
254 memset (mp, 0, sizeof (*mp));
255 mp->client_index = wrk->my_client_index;
256 mp->wrk_index = wrk->vpp_wrk_index;
257 mp->handle = s->vpp_handle;
258 mp->context = wrk->wrk_index;
259 app_send_ctrl_evt_to_vpp (mq, app_evt);
260}
261
262static void
263vcl_send_session_disconnect (vcl_worker_t * wrk, vcl_session_t * s)
264{
265 app_session_evt_t _app_evt, *app_evt = &_app_evt;
266 session_disconnect_msg_t *mp;
267 svm_msg_q_t *mq;
268
269 /* Send to thread that owns the session */
270 mq = s->vpp_evt_q;
271 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_DISCONNECT);
272 mp = (session_disconnect_msg_t *) app_evt->evt->data;
273 memset (mp, 0, sizeof (*mp));
274 mp->client_index = wrk->my_client_index;
275 mp->handle = s->vpp_handle;
276 app_send_ctrl_evt_to_vpp (mq, app_evt);
277}
278
279static void
280vcl_send_app_detach (vcl_worker_t * wrk)
281{
282 app_session_evt_t _app_evt, *app_evt = &_app_evt;
283 session_app_detach_msg_t *mp;
284 svm_msg_q_t *mq;
285
286 mq = vcl_worker_ctrl_mq (wrk);
287 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_APP_DETACH);
288 mp = (session_app_detach_msg_t *) app_evt->evt->data;
289 memset (mp, 0, sizeof (*mp));
290 mp->client_index = wrk->my_client_index;
291 app_send_ctrl_evt_to_vpp (mq, app_evt);
292}
Florin Coras697faea2018-06-27 17:10:49 -0700293
Florin Coras54693d22018-07-17 10:46:29 -0700294static void
295vcl_send_session_accepted_reply (svm_msg_q_t * mq, u32 context,
296 session_handle_t handle, int retval)
297{
298 app_session_evt_t _app_evt, *app_evt = &_app_evt;
299 session_accepted_reply_msg_t *rmp;
300 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_ACCEPTED_REPLY);
301 rmp = (session_accepted_reply_msg_t *) app_evt->evt->data;
302 rmp->handle = handle;
303 rmp->context = context;
304 rmp->retval = retval;
305 app_send_ctrl_evt_to_vpp (mq, app_evt);
306}
307
Florin Coras99368312018-08-02 10:45:44 -0700308static void
309vcl_send_session_disconnected_reply (svm_msg_q_t * mq, u32 context,
310 session_handle_t handle, int retval)
311{
312 app_session_evt_t _app_evt, *app_evt = &_app_evt;
313 session_disconnected_reply_msg_t *rmp;
314 app_alloc_ctrl_evt_to_vpp (mq, app_evt,
315 SESSION_CTRL_EVT_DISCONNECTED_REPLY);
316 rmp = (session_disconnected_reply_msg_t *) app_evt->evt->data;
317 rmp->handle = handle;
318 rmp->context = context;
319 rmp->retval = retval;
320 app_send_ctrl_evt_to_vpp (mq, app_evt);
321}
322
Florin Corasc9fbd662018-08-24 12:59:56 -0700323static void
324vcl_send_session_reset_reply (svm_msg_q_t * mq, u32 context,
325 session_handle_t handle, int retval)
326{
327 app_session_evt_t _app_evt, *app_evt = &_app_evt;
328 session_reset_reply_msg_t *rmp;
329 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_RESET_REPLY);
330 rmp = (session_reset_reply_msg_t *) app_evt->evt->data;
331 rmp->handle = handle;
332 rmp->context = context;
333 rmp->retval = retval;
334 app_send_ctrl_evt_to_vpp (mq, app_evt);
335}
336
Florin Coras30e79c22019-01-02 19:31:22 -0800337void
338vcl_send_session_worker_update (vcl_worker_t * wrk, vcl_session_t * s,
339 u32 wrk_index)
340{
341 app_session_evt_t _app_evt, *app_evt = &_app_evt;
342 session_worker_update_msg_t *mp;
343 svm_msg_q_t *mq;
344
345 mq = vcl_session_vpp_evt_q (wrk, s);
346 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_WORKER_UPDATE);
347 mp = (session_worker_update_msg_t *) app_evt->evt->data;
348 mp->client_index = wrk->my_client_index;
349 mp->handle = s->vpp_handle;
350 mp->req_wrk_index = wrk->vpp_wrk_index;
351 mp->wrk_index = wrk_index;
352 app_send_ctrl_evt_to_vpp (mq, app_evt);
353}
354
Florin Coras54693d22018-07-17 10:46:29 -0700355static u32
Florin Coras00cca802019-06-06 09:38:44 -0700356vcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp,
357 u32 ls_index)
Florin Coras54693d22018-07-17 10:46:29 -0700358{
359 vcl_session_t *session, *listen_session;
360 svm_fifo_t *rx_fifo, *tx_fifo;
Florin Coras134a9962018-08-28 11:32:04 -0700361 u32 vpp_wrk_index;
Florin Coras99368312018-08-02 10:45:44 -0700362 svm_msg_q_t *evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700363
Florin Coras134a9962018-08-28 11:32:04 -0700364 session = vcl_session_alloc (wrk);
Florin Coras99368312018-08-02 10:45:44 -0700365
Florin Coras00cca802019-06-06 09:38:44 -0700366 listen_session = vcl_session_get (wrk, ls_index);
367 if (listen_session->vpp_handle != mp->listener_handle)
Florin Coras54693d22018-07-17 10:46:29 -0700368 {
Florin Coras00cca802019-06-06 09:38:44 -0700369 VDBG (0, "ERROR: listener handle %lu does not match session %u",
370 mp->listener_handle, ls_index);
371 goto error;
372 }
373
374 if (vcl_wait_for_segment (mp->segment_handle))
375 {
376 VDBG (0, "ERROR: segment for session %u couldn't be mounted!",
377 session->session_index);
378 goto error;
Florin Coras54693d22018-07-17 10:46:29 -0700379 }
380
Florin Coras54693d22018-07-17 10:46:29 -0700381 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
382 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
Florin Coras653e43f2019-03-04 10:56:23 -0800383 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
384 svm_msg_q_t *);
385 rx_fifo->client_session_index = session->session_index;
386 tx_fifo->client_session_index = session->session_index;
387 rx_fifo->client_thread_index = vcl_get_worker_index ();
388 tx_fifo->client_thread_index = vcl_get_worker_index ();
389 vpp_wrk_index = tx_fifo->master_thread_index;
390 vec_validate (wrk->vpp_event_queues, vpp_wrk_index);
391 wrk->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700392
393 session->vpp_handle = mp->handle;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800394 session->vpp_thread_index = rx_fifo->master_thread_index;
Florin Coras54693d22018-07-17 10:46:29 -0700395 session->rx_fifo = rx_fifo;
396 session->tx_fifo = tx_fifo;
397
398 session->session_state = STATE_ACCEPT;
Florin Coras09d18c22019-04-24 11:10:02 -0700399 session->transport.rmt_port = mp->rmt.port;
400 session->transport.is_ip4 = mp->rmt.is_ip4;
401 clib_memcpy_fast (&session->transport.rmt_ip, &mp->rmt.ip,
Dave Barach178cf492018-11-13 16:34:13 -0500402 sizeof (ip46_address_t));
Florin Coras54693d22018-07-17 10:46:29 -0700403
Florin Coras134a9962018-08-28 11:32:04 -0700404 vcl_session_table_add_vpp_handle (wrk, mp->handle, session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -0700405 session->transport.lcl_port = listen_session->transport.lcl_port;
406 session->transport.lcl_ip = listen_session->transport.lcl_ip;
Florin Coras460dce62018-07-27 05:45:06 -0700407 session->session_type = listen_session->session_type;
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +0200408 session->is_dgram = vcl_proto_is_dgram (session->session_type);
409 session->listener_index = listen_session->session_index;
410 listen_session->n_accepted_sessions++;
Florin Coras54693d22018-07-17 10:46:29 -0700411
Florin Coras5e062572019-03-14 19:07:51 -0700412 VDBG (1, "session %u [0x%llx]: client accept request from %s address %U"
413 " port %d queue %p!", session->session_index, mp->handle,
Florin Coras09d18c22019-04-24 11:10:02 -0700414 mp->rmt.is_ip4 ? "IPv4" : "IPv6", format_ip46_address, &mp->rmt.ip,
415 mp->rmt.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
416 clib_net_to_host_u16 (mp->rmt.port), session->vpp_evt_q);
Florin Coras54693d22018-07-17 10:46:29 -0700417 vcl_evt (VCL_EVT_ACCEPT, session, listen_session, session_index);
418
Florin Coras00cca802019-06-06 09:38:44 -0700419 vcl_send_session_accepted_reply (session->vpp_evt_q, mp->context,
420 session->vpp_handle, 0);
421
Florin Coras134a9962018-08-28 11:32:04 -0700422 return session->session_index;
Florin Coras00cca802019-06-06 09:38:44 -0700423
424error:
425 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
426 vcl_send_session_accepted_reply (evt_q, mp->context, mp->handle,
427 VNET_API_ERROR_INVALID_ARGUMENT);
428 vcl_session_free (wrk, session);
429 return VCL_INVALID_SESSION_INDEX;
Florin Coras54693d22018-07-17 10:46:29 -0700430}
431
432static u32
Florin Coras134a9962018-08-28 11:32:04 -0700433vcl_session_connected_handler (vcl_worker_t * wrk,
434 session_connected_msg_t * mp)
Florin Coras54693d22018-07-17 10:46:29 -0700435{
Florin Coras99368312018-08-02 10:45:44 -0700436 u32 session_index, vpp_wrk_index;
Florin Coras54693d22018-07-17 10:46:29 -0700437 svm_fifo_t *rx_fifo, *tx_fifo;
Florin Coras99368312018-08-02 10:45:44 -0700438 vcl_session_t *session = 0;
Florin Coras54693d22018-07-17 10:46:29 -0700439
440 session_index = mp->context;
Florin Coras134a9962018-08-28 11:32:04 -0700441 session = vcl_session_get (wrk, session_index);
Florin Coras070453d2018-08-24 17:04:27 -0700442 if (!session)
443 {
Florin Coras5e062572019-03-14 19:07:51 -0700444 VDBG (0, "ERROR: vpp handle 0x%llx has no session index (%u)!",
445 mp->handle, session_index);
Florin Coras070453d2018-08-24 17:04:27 -0700446 return VCL_INVALID_SESSION_INDEX;
447 }
Florin Coras54693d22018-07-17 10:46:29 -0700448 if (mp->retval)
449 {
Florin Coras5e062572019-03-14 19:07:51 -0700450 VDBG (0, "ERROR: session index %u: connect failed! %U",
451 session_index, format_api_error, ntohl (mp->retval));
Florin Corasdbc9c592019-09-25 16:37:43 -0700452 session->session_state = STATE_FAILED | STATE_DISCONNECT;
Florin Coras070453d2018-08-24 17:04:27 -0700453 session->vpp_handle = mp->handle;
454 return session_index;
Florin Coras54693d22018-07-17 10:46:29 -0700455 }
456
Florin Corasdbc9c592019-09-25 16:37:43 -0700457 session->vpp_handle = mp->handle;
458 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
459 svm_msg_q_t *);
Florin Coras460dce62018-07-27 05:45:06 -0700460 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
461 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
Florin Corasd85de682018-11-29 17:02:29 -0800462 if (vcl_wait_for_segment (mp->segment_handle))
463 {
Florin Coras653e43f2019-03-04 10:56:23 -0800464 VDBG (0, "segment for session %u couldn't be mounted!",
465 session->session_index);
Florin Corasdbc9c592019-09-25 16:37:43 -0700466 session->session_state = STATE_FAILED | STATE_DISCONNECT;
467 vcl_send_session_disconnect (wrk, session);
468 return session_index;
Florin Corasd85de682018-11-29 17:02:29 -0800469 }
470
Florin Coras460dce62018-07-27 05:45:06 -0700471 rx_fifo->client_session_index = session_index;
472 tx_fifo->client_session_index = session_index;
Florin Coras21795132018-09-09 09:40:51 -0700473 rx_fifo->client_thread_index = vcl_get_worker_index ();
474 tx_fifo->client_thread_index = vcl_get_worker_index ();
Florin Coras460dce62018-07-27 05:45:06 -0700475
Florin Coras653e43f2019-03-04 10:56:23 -0800476 vpp_wrk_index = tx_fifo->master_thread_index;
477 vec_validate (wrk->vpp_event_queues, vpp_wrk_index);
478 wrk->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
Florin Coras99368312018-08-02 10:45:44 -0700479
Florin Coras653e43f2019-03-04 10:56:23 -0800480 if (mp->ct_rx_fifo)
Florin Coras99368312018-08-02 10:45:44 -0700481 {
Florin Coras653e43f2019-03-04 10:56:23 -0800482 session->ct_rx_fifo = uword_to_pointer (mp->ct_rx_fifo, svm_fifo_t *);
483 session->ct_tx_fifo = uword_to_pointer (mp->ct_tx_fifo, svm_fifo_t *);
484 if (vcl_wait_for_segment (mp->ct_segment_handle))
485 {
486 VDBG (0, "ct segment for session %u couldn't be mounted!",
487 session->session_index);
Florin Corasdbc9c592019-09-25 16:37:43 -0700488 session->session_state = STATE_FAILED | STATE_DISCONNECT;
489 vcl_send_session_disconnect (wrk, session);
490 return session_index;
Florin Coras653e43f2019-03-04 10:56:23 -0800491 }
Florin Coras99368312018-08-02 10:45:44 -0700492 }
Florin Coras54693d22018-07-17 10:46:29 -0700493
Florin Coras54693d22018-07-17 10:46:29 -0700494 session->rx_fifo = rx_fifo;
495 session->tx_fifo = tx_fifo;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800496 session->vpp_thread_index = rx_fifo->master_thread_index;
Florin Coras09d18c22019-04-24 11:10:02 -0700497 session->transport.is_ip4 = mp->lcl.is_ip4;
498 clib_memcpy_fast (&session->transport.lcl_ip, &mp->lcl.ip,
Dave Barach178cf492018-11-13 16:34:13 -0500499 sizeof (session->transport.lcl_ip));
Florin Coras09d18c22019-04-24 11:10:02 -0700500 session->transport.lcl_port = mp->lcl.port;
Florin Coras54693d22018-07-17 10:46:29 -0700501 session->session_state = STATE_CONNECT;
502
503 /* Add it to lookup table */
Florin Coras3c7d4f92018-12-14 11:28:43 -0800504 vcl_session_table_add_vpp_handle (wrk, mp->handle, session_index);
Florin Coras54693d22018-07-17 10:46:29 -0700505
Florin Coras5e062572019-03-14 19:07:51 -0700506 VDBG (1, "session %u [0x%llx] connected! rx_fifo %p, refcnt %d, tx_fifo %p,"
507 " refcnt %d", session_index, mp->handle, session->rx_fifo,
Florin Coras54693d22018-07-17 10:46:29 -0700508 session->rx_fifo->refcnt, session->tx_fifo, session->tx_fifo->refcnt);
Florin Coras070453d2018-08-24 17:04:27 -0700509
Florin Coras54693d22018-07-17 10:46:29 -0700510 return session_index;
511}
512
Florin Coras3c7d4f92018-12-14 11:28:43 -0800513static int
514vcl_flag_accepted_session (vcl_session_t * session, u64 handle, u32 flags)
515{
516 vcl_session_msg_t *accepted_msg;
517 int i;
518
519 for (i = 0; i < vec_len (session->accept_evts_fifo); i++)
520 {
521 accepted_msg = &session->accept_evts_fifo[i];
522 if (accepted_msg->accepted_msg.handle == handle)
523 {
Florin Corasb0f662f2018-12-27 14:51:46 -0800524 accepted_msg->flags |= flags;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800525 return 1;
526 }
527 }
528 return 0;
529}
530
Florin Corasc9fbd662018-08-24 12:59:56 -0700531static u32
Florin Coras134a9962018-08-28 11:32:04 -0700532vcl_session_reset_handler (vcl_worker_t * wrk,
533 session_reset_msg_t * reset_msg)
Florin Corasc9fbd662018-08-24 12:59:56 -0700534{
535 vcl_session_t *session;
536 u32 sid;
537
Florin Coras134a9962018-08-28 11:32:04 -0700538 sid = vcl_session_index_from_vpp_handle (wrk, reset_msg->handle);
539 session = vcl_session_get (wrk, sid);
Florin Corasc9fbd662018-08-24 12:59:56 -0700540 if (!session)
541 {
542 VDBG (0, "request to reset unknown handle 0x%llx", reset_msg->handle);
543 return VCL_INVALID_SESSION_INDEX;
544 }
Florin Coras3c7d4f92018-12-14 11:28:43 -0800545
546 /* Caught a reset before actually accepting the session */
547 if (session->session_state == STATE_LISTEN)
548 {
549
550 if (!vcl_flag_accepted_session (session, reset_msg->handle,
551 VCL_ACCEPTED_F_RESET))
552 VDBG (0, "session was not accepted!");
553 return VCL_INVALID_SESSION_INDEX;
554 }
555
556 session->session_state = STATE_DISCONNECT;
557 VDBG (0, "reset session %u [0x%llx]", sid, reset_msg->handle);
Florin Corasc9fbd662018-08-24 12:59:56 -0700558 return sid;
559}
560
Florin Coras60116992018-08-27 09:52:18 -0700561static u32
Florin Coras134a9962018-08-28 11:32:04 -0700562vcl_session_bound_handler (vcl_worker_t * wrk, session_bound_msg_t * mp)
Florin Coras60116992018-08-27 09:52:18 -0700563{
564 vcl_session_t *session;
565 u32 sid = mp->context;
566
Florin Coras134a9962018-08-28 11:32:04 -0700567 session = vcl_session_get (wrk, sid);
Florin Coras60116992018-08-27 09:52:18 -0700568 if (mp->retval)
569 {
Florin Coras5e062572019-03-14 19:07:51 -0700570 VERR ("session %u [0x%llx]: bind failed: %U", sid, mp->handle,
Florin Corasd85de682018-11-29 17:02:29 -0800571 format_api_error, mp->retval);
Florin Coras60116992018-08-27 09:52:18 -0700572 if (session)
573 {
574 session->session_state = STATE_FAILED;
575 session->vpp_handle = mp->handle;
576 return sid;
577 }
578 else
579 {
Florin Coras5e062572019-03-14 19:07:51 -0700580 VDBG (0, "ERROR: session %u [0x%llx]: Invalid session index!",
581 sid, mp->handle);
Florin Coras60116992018-08-27 09:52:18 -0700582 return VCL_INVALID_SESSION_INDEX;
583 }
584 }
585
586 session->vpp_handle = mp->handle;
587 session->transport.is_ip4 = mp->lcl_is_ip4;
Dave Barach178cf492018-11-13 16:34:13 -0500588 clib_memcpy_fast (&session->transport.lcl_ip, mp->lcl_ip,
589 sizeof (ip46_address_t));
Florin Coras60116992018-08-27 09:52:18 -0700590 session->transport.lcl_port = mp->lcl_port;
Florin Coras134a9962018-08-28 11:32:04 -0700591 vcl_session_table_add_listener (wrk, mp->handle, sid);
Florin Coras60116992018-08-27 09:52:18 -0700592 session->session_state = STATE_LISTEN;
593
Florin Coras5f45e012019-01-23 09:21:30 -0800594 session->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
595 vec_validate (wrk->vpp_event_queues, 0);
596 wrk->vpp_event_queues[0] = session->vpp_evt_q;
597
Florin Coras60116992018-08-27 09:52:18 -0700598 if (session->is_dgram)
599 {
600 svm_fifo_t *rx_fifo, *tx_fifo;
601 session->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
602 rx_fifo = uword_to_pointer (mp->rx_fifo, svm_fifo_t *);
603 rx_fifo->client_session_index = sid;
604 tx_fifo = uword_to_pointer (mp->tx_fifo, svm_fifo_t *);
605 tx_fifo->client_session_index = sid;
606 session->rx_fifo = rx_fifo;
607 session->tx_fifo = tx_fifo;
608 }
609
Florin Coras05ecfcc2018-12-12 18:19:39 -0800610 VDBG (0, "session %u [0x%llx]: listen succeeded!", sid, mp->handle);
Florin Coras60116992018-08-27 09:52:18 -0700611 return sid;
612}
613
Florin Corasdfae9f92019-02-20 19:48:31 -0800614static void
615vcl_session_unlisten_reply_handler (vcl_worker_t * wrk, void *data)
616{
617 session_unlisten_reply_msg_t *mp = (session_unlisten_reply_msg_t *) data;
618 vcl_session_t *s;
619
620 s = vcl_session_get_w_vpp_handle (wrk, mp->handle);
621 if (!s || s->session_state != STATE_DISCONNECT)
622 {
623 VDBG (0, "Unlisten reply with wrong handle %llx", mp->handle);
624 return;
625 }
626
627 if (mp->retval)
628 VDBG (0, "ERROR: session %u [0xllx]: unlisten failed: %U",
629 s->session_index, mp->handle, format_api_error, ntohl (mp->retval));
630
631 if (mp->context != wrk->wrk_index)
632 VDBG (0, "wrong context");
633
634 vcl_session_table_del_vpp_handle (wrk, mp->handle);
635 vcl_session_free (wrk, s);
636}
637
Florin Coras3c7d4f92018-12-14 11:28:43 -0800638static vcl_session_t *
639vcl_session_accepted (vcl_worker_t * wrk, session_accepted_msg_t * msg)
640{
641 vcl_session_msg_t *vcl_msg;
642 vcl_session_t *session;
643
644 session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
645 if (PREDICT_FALSE (session != 0))
Florin Corasb0f662f2018-12-27 14:51:46 -0800646 VWRN ("session overlap handle %lu state %u!", msg->handle,
647 session->session_state);
Florin Coras3c7d4f92018-12-14 11:28:43 -0800648
649 session = vcl_session_table_lookup_listener (wrk, msg->listener_handle);
650 if (!session)
651 {
652 VERR ("couldn't find listen session: listener handle %llx",
653 msg->listener_handle);
654 return 0;
655 }
656
657 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
658 vcl_msg->accepted_msg = *msg;
659 /* Session handle points to listener until fully accepted by app */
660 vcl_session_table_add_vpp_handle (wrk, msg->handle, session->session_index);
661
662 return session;
663}
664
665static vcl_session_t *
666vcl_session_disconnected_handler (vcl_worker_t * wrk,
667 session_disconnected_msg_t * msg)
668{
669 vcl_session_t *session;
670
671 session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
672 if (!session)
673 {
674 VDBG (0, "request to disconnect unknown handle 0x%llx", msg->handle);
675 return 0;
676 }
677
678 /* Caught a disconnect before actually accepting the session */
679 if (session->session_state == STATE_LISTEN)
680 {
Florin Coras3c7d4f92018-12-14 11:28:43 -0800681 if (!vcl_flag_accepted_session (session, msg->handle,
682 VCL_ACCEPTED_F_CLOSED))
683 VDBG (0, "session was not accepted!");
684 return 0;
685 }
686
687 session->session_state = STATE_VPP_CLOSING;
688 return session;
689}
690
Florin Coras30e79c22019-01-02 19:31:22 -0800691static void
692vcl_session_req_worker_update_handler (vcl_worker_t * wrk, void *data)
693{
694 session_req_worker_update_msg_t *msg;
695 vcl_session_t *s;
696
697 msg = (session_req_worker_update_msg_t *) data;
698 s = vcl_session_get_w_vpp_handle (wrk, msg->session_handle);
699 if (!s)
700 return;
701
702 vec_add1 (wrk->pending_session_wrk_updates, s->session_index);
703}
704
705static void
706vcl_session_worker_update_reply_handler (vcl_worker_t * wrk, void *data)
707{
708 session_worker_update_reply_msg_t *msg;
709 vcl_session_t *s;
710
711 msg = (session_worker_update_reply_msg_t *) data;
712 s = vcl_session_get_w_vpp_handle (wrk, msg->handle);
713 if (!s)
714 {
715 VDBG (0, "unknown handle 0x%llx", msg->handle);
716 return;
717 }
718 if (vcl_wait_for_segment (msg->segment_handle))
719 {
720 clib_warning ("segment for session %u couldn't be mounted!",
721 s->session_index);
722 return;
723 }
Florin Coras30e79c22019-01-02 19:31:22 -0800724
Florin Coras5f45e012019-01-23 09:21:30 -0800725 if (s->rx_fifo)
726 {
727 s->rx_fifo = uword_to_pointer (msg->rx_fifo, svm_fifo_t *);
728 s->tx_fifo = uword_to_pointer (msg->tx_fifo, svm_fifo_t *);
729 s->rx_fifo->client_session_index = s->session_index;
730 s->tx_fifo->client_session_index = s->session_index;
731 s->rx_fifo->client_thread_index = wrk->wrk_index;
732 s->tx_fifo->client_thread_index = wrk->wrk_index;
733 }
Florin Coras30e79c22019-01-02 19:31:22 -0800734 s->session_state = STATE_UPDATED;
735
Florin Coras30e79c22019-01-02 19:31:22 -0800736 VDBG (0, "session %u[0x%llx] moved to worker %u", s->session_index,
737 s->vpp_handle, wrk->wrk_index);
738}
739
Florin Coras86f04502018-09-12 16:08:01 -0700740static int
741vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e)
Florin Coras54693d22018-07-17 10:46:29 -0700742{
Florin Coras54693d22018-07-17 10:46:29 -0700743 session_disconnected_msg_t *disconnected_msg;
Florin Coras54693d22018-07-17 10:46:29 -0700744 vcl_session_t *session;
Florin Coras54693d22018-07-17 10:46:29 -0700745
746 switch (e->event_type)
747 {
Florin Coras653e43f2019-03-04 10:56:23 -0800748 case SESSION_IO_EVT_RX:
749 case SESSION_IO_EVT_TX:
Florin Corasc0737e92019-03-04 14:19:39 -0800750 session = vcl_session_get (wrk, e->session_index);
Florin Coras653e43f2019-03-04 10:56:23 -0800751 if (!session || !(session->session_state & STATE_OPEN))
752 break;
Florin Coras86f04502018-09-12 16:08:01 -0700753 vec_add1 (wrk->unhandled_evts_vector, *e);
Florin Coras54693d22018-07-17 10:46:29 -0700754 break;
755 case SESSION_CTRL_EVT_ACCEPTED:
Florin Coras3c7d4f92018-12-14 11:28:43 -0800756 vcl_session_accepted (wrk, (session_accepted_msg_t *) e->data);
Florin Coras54693d22018-07-17 10:46:29 -0700757 break;
758 case SESSION_CTRL_EVT_CONNECTED:
Florin Coras134a9962018-08-28 11:32:04 -0700759 vcl_session_connected_handler (wrk,
760 (session_connected_msg_t *) e->data);
Florin Coras54693d22018-07-17 10:46:29 -0700761 break;
762 case SESSION_CTRL_EVT_DISCONNECTED:
763 disconnected_msg = (session_disconnected_msg_t *) e->data;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800764 session = vcl_session_disconnected_handler (wrk, disconnected_msg);
Florin Corasc9fbd662018-08-24 12:59:56 -0700765 if (!session)
Florin Coras3c7d4f92018-12-14 11:28:43 -0800766 break;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800767 VDBG (0, "disconnected session %u [0x%llx]", session->session_index,
768 session->vpp_handle);
Florin Corasc9fbd662018-08-24 12:59:56 -0700769 break;
770 case SESSION_CTRL_EVT_RESET:
Florin Coras134a9962018-08-28 11:32:04 -0700771 vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
Florin Coras60116992018-08-27 09:52:18 -0700772 break;
773 case SESSION_CTRL_EVT_BOUND:
Florin Coras134a9962018-08-28 11:32:04 -0700774 vcl_session_bound_handler (wrk, (session_bound_msg_t *) e->data);
Florin Coras54693d22018-07-17 10:46:29 -0700775 break;
Florin Corasdfae9f92019-02-20 19:48:31 -0800776 case SESSION_CTRL_EVT_UNLISTEN_REPLY:
777 vcl_session_unlisten_reply_handler (wrk, e->data);
778 break;
Florin Coras30e79c22019-01-02 19:31:22 -0800779 case SESSION_CTRL_EVT_REQ_WORKER_UPDATE:
780 vcl_session_req_worker_update_handler (wrk, e->data);
781 break;
782 case SESSION_CTRL_EVT_WORKER_UPDATE_REPLY:
783 vcl_session_worker_update_reply_handler (wrk, e->data);
784 break;
Florin Coras54693d22018-07-17 10:46:29 -0700785 default:
786 clib_warning ("unhandled %u", e->event_type);
787 }
788 return VPPCOM_OK;
789}
790
Florin Coras30e79c22019-01-02 19:31:22 -0800791static int
Florin Coras697faea2018-06-27 17:10:49 -0700792vppcom_wait_for_session_state_change (u32 session_index,
Florin Coras288eaab2019-02-03 15:26:14 -0800793 vcl_session_state_t state,
Florin Coras697faea2018-06-27 17:10:49 -0700794 f64 wait_for_time)
795{
Florin Coras134a9962018-08-28 11:32:04 -0700796 vcl_worker_t *wrk = vcl_worker_get_current ();
797 f64 timeout = clib_time_now (&wrk->clib_time) + wait_for_time;
Florin Coras697faea2018-06-27 17:10:49 -0700798 vcl_session_t *volatile session;
Florin Coras54693d22018-07-17 10:46:29 -0700799 svm_msg_q_msg_t msg;
800 session_event_t *e;
Dave Wallace543852a2017-08-03 02:11:34 -0400801
Florin Coras697faea2018-06-27 17:10:49 -0700802 do
Dave Wallace543852a2017-08-03 02:11:34 -0400803 {
Florin Coras134a9962018-08-28 11:32:04 -0700804 session = vcl_session_get (wrk, session_index);
Florin Coras070453d2018-08-24 17:04:27 -0700805 if (PREDICT_FALSE (!session))
Florin Coras697faea2018-06-27 17:10:49 -0700806 {
Florin Coras070453d2018-08-24 17:04:27 -0700807 return VPPCOM_EBADFD;
Florin Coras697faea2018-06-27 17:10:49 -0700808 }
809 if (session->session_state & state)
810 {
Florin Coras697faea2018-06-27 17:10:49 -0700811 return VPPCOM_OK;
812 }
813 if (session->session_state & STATE_FAILED)
814 {
Florin Coras697faea2018-06-27 17:10:49 -0700815 return VPPCOM_ECONNREFUSED;
816 }
Florin Coras54693d22018-07-17 10:46:29 -0700817
Florin Coras134a9962018-08-28 11:32:04 -0700818 if (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0))
Florin Corasdc2e2512018-12-03 17:47:26 -0800819 {
820 usleep (100);
821 continue;
822 }
Florin Coras134a9962018-08-28 11:32:04 -0700823 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
Florin Coras86f04502018-09-12 16:08:01 -0700824 vcl_handle_mq_event (wrk, e);
Florin Coras134a9962018-08-28 11:32:04 -0700825 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Corasdcf55ce2017-11-16 15:32:50 -0800826 }
Florin Coras134a9962018-08-28 11:32:04 -0700827 while (clib_time_now (&wrk->clib_time) < timeout);
Florin Corasdcf55ce2017-11-16 15:32:50 -0800828
Florin Coras05ecfcc2018-12-12 18:19:39 -0800829 VDBG (0, "timeout waiting for state 0x%x (%s)", state,
Florin Coras697faea2018-06-27 17:10:49 -0700830 vppcom_session_state_str (state));
831 vcl_evt (VCL_EVT_SESSION_TIMEOUT, session, session_state);
Dave Wallace543852a2017-08-03 02:11:34 -0400832
Florin Coras697faea2018-06-27 17:10:49 -0700833 return VPPCOM_ETIMEDOUT;
Dave Wallace60caa062017-11-10 17:07:13 -0500834}
835
Florin Coras30e79c22019-01-02 19:31:22 -0800836static void
837vcl_handle_pending_wrk_updates (vcl_worker_t * wrk)
838{
Florin Coras288eaab2019-02-03 15:26:14 -0800839 vcl_session_state_t state;
Florin Coras30e79c22019-01-02 19:31:22 -0800840 vcl_session_t *s;
841 u32 *sip;
842
843 if (PREDICT_TRUE (vec_len (wrk->pending_session_wrk_updates) == 0))
844 return;
845
846 vec_foreach (sip, wrk->pending_session_wrk_updates)
847 {
848 s = vcl_session_get (wrk, *sip);
849 vcl_send_session_worker_update (wrk, s, wrk->wrk_index);
850 state = s->session_state;
851 vppcom_wait_for_session_state_change (s->session_index, STATE_UPDATED, 5);
852 s->session_state = state;
853 }
854 vec_reset_length (wrk->pending_session_wrk_updates);
855}
856
Florin Corasf9240dc2019-01-15 08:03:17 -0800857void
Florin Coras30e79c22019-01-02 19:31:22 -0800858vcl_flush_mq_events (void)
859{
860 vcl_worker_t *wrk = vcl_worker_get_current ();
861 svm_msg_q_msg_t *msg;
862 session_event_t *e;
863 svm_msg_q_t *mq;
864 int i;
865
866 mq = wrk->app_event_queue;
867 svm_msg_q_lock (mq);
Florin Corase003a1b2019-06-05 10:47:16 -0700868 vcl_mq_dequeue_batch (wrk, mq, ~0);
Florin Coras30e79c22019-01-02 19:31:22 -0800869 svm_msg_q_unlock (mq);
870
871 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
872 {
873 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
874 e = svm_msg_q_msg_data (mq, msg);
875 vcl_handle_mq_event (wrk, e);
876 svm_msg_q_free_msg (mq, msg);
877 }
878 vec_reset_length (wrk->mq_msg_vector);
879 vcl_handle_pending_wrk_updates (wrk);
880}
881
Florin Coras697faea2018-06-27 17:10:49 -0700882static int
883vppcom_app_session_enable (void)
Dave Wallace543852a2017-08-03 02:11:34 -0400884{
Florin Coras697faea2018-06-27 17:10:49 -0700885 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -0400886
Florin Coras697faea2018-06-27 17:10:49 -0700887 if (vcm->app_state != STATE_APP_ENABLED)
888 {
889 vppcom_send_session_enable_disable (1 /* is_enabled == TRUE */ );
Florin Coras134a9962018-08-28 11:32:04 -0700890 rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
Florin Coras697faea2018-06-27 17:10:49 -0700891 if (PREDICT_FALSE (rv))
892 {
Florin Coras5e062572019-03-14 19:07:51 -0700893 VDBG (0, "application session enable timed out! returning %d (%s)",
894 rv, vppcom_retval_str (rv));
Florin Coras697faea2018-06-27 17:10:49 -0700895 return rv;
896 }
897 }
898 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400899}
900
Florin Coras697faea2018-06-27 17:10:49 -0700901static int
902vppcom_app_attach (void)
Dave Wallace543852a2017-08-03 02:11:34 -0400903{
Florin Coras697faea2018-06-27 17:10:49 -0700904 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -0400905
Florin Coras697faea2018-06-27 17:10:49 -0700906 vppcom_app_send_attach ();
Florin Coras134a9962018-08-28 11:32:04 -0700907 rv = vcl_wait_for_app_state_change (STATE_APP_ATTACHED);
Florin Coras697faea2018-06-27 17:10:49 -0700908 if (PREDICT_FALSE (rv))
909 {
Florin Coras5e062572019-03-14 19:07:51 -0700910 VDBG (0, "application attach timed out! returning %d (%s)", rv,
911 vppcom_retval_str (rv));
Florin Coras697faea2018-06-27 17:10:49 -0700912 return rv;
913 }
Dave Wallace543852a2017-08-03 02:11:34 -0400914
Florin Coras697faea2018-06-27 17:10:49 -0700915 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400916}
917
918static int
Florin Corasab2f6db2018-08-31 14:31:41 -0700919vppcom_session_unbind (u32 session_handle)
Dave Wallace543852a2017-08-03 02:11:34 -0400920{
Florin Coras134a9962018-08-28 11:32:04 -0700921 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Corasaaff5ee2019-07-08 13:00:00 -0700922 session_accepted_msg_t *accepted_msg;
Florin Coras7e12d942018-06-27 14:32:43 -0700923 vcl_session_t *session = 0;
Florin Corasaaff5ee2019-07-08 13:00:00 -0700924 vcl_session_msg_t *evt;
Dave Wallace543852a2017-08-03 02:11:34 -0400925
Florin Corasab2f6db2018-08-31 14:31:41 -0700926 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -0700927 if (!session)
928 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500929
Florin Corasaaff5ee2019-07-08 13:00:00 -0700930 /* Flush pending accept events, if any */
931 while (clib_fifo_elts (session->accept_evts_fifo))
932 {
933 clib_fifo_sub2 (session->accept_evts_fifo, evt);
934 accepted_msg = &evt->accepted_msg;
935 vcl_session_table_del_vpp_handle (wrk, accepted_msg->handle);
936 vcl_send_session_accepted_reply (session->vpp_evt_q,
937 accepted_msg->context,
938 session->vpp_handle, -1);
939 }
940 clib_fifo_free (session->accept_evts_fifo);
941
Florin Coras458089b2019-08-21 16:20:44 -0700942 vcl_send_session_unlisten (wrk, session);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500943
Florin Coras5e062572019-03-14 19:07:51 -0700944 VDBG (1, "session %u [0x%llx]: sending unbind!", session->session_index,
Florin Coras458089b2019-08-21 16:20:44 -0700945 session->vpp_handle);
Florin Coras0d427d82018-06-27 03:24:07 -0700946 vcl_evt (VCL_EVT_UNBIND, session);
Florin Coras458089b2019-08-21 16:20:44 -0700947
948 session->vpp_handle = ~0;
949 session->session_state = STATE_DISCONNECT;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500950
Florin Coras070453d2018-08-24 17:04:27 -0700951 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400952}
953
Florin Coras697faea2018-06-27 17:10:49 -0700954static int
Florin Corasab2f6db2018-08-31 14:31:41 -0700955vppcom_session_disconnect (u32 session_handle)
Dave Wallace543852a2017-08-03 02:11:34 -0400956{
Florin Coras134a9962018-08-28 11:32:04 -0700957 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras99368312018-08-02 10:45:44 -0700958 svm_msg_q_t *vpp_evt_q;
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +0200959 vcl_session_t *session, *listen_session;
Florin Coras288eaab2019-02-03 15:26:14 -0800960 vcl_session_state_t state;
Florin Coras99368312018-08-02 10:45:44 -0700961 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400962
Florin Corasab2f6db2018-08-31 14:31:41 -0700963 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras21795132018-09-09 09:40:51 -0700964 if (!session)
965 return VPPCOM_EBADFD;
966
Dave Wallace4878cbe2017-11-21 03:45:09 -0500967 vpp_handle = session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -0700968 state = session->session_state;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500969
Florin Coras5e062572019-03-14 19:07:51 -0700970 VDBG (1, "session %u [0x%llx] state 0x%x (%s)", session->session_index,
971 vpp_handle, state, vppcom_session_state_str (state));
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400972
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800973 if (PREDICT_FALSE (state & STATE_LISTEN))
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400974 {
Florin Coras5e062572019-03-14 19:07:51 -0700975 VDBG (0, "ERROR: Cannot disconnect a listen socket!");
Florin Coras070453d2018-08-24 17:04:27 -0700976 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500977 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400978
Florin Coras3c7d4f92018-12-14 11:28:43 -0800979 if (state & STATE_VPP_CLOSING)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500980 {
Florin Coras134a9962018-08-28 11:32:04 -0700981 vpp_evt_q = vcl_session_vpp_evt_q (wrk, session);
Florin Coras47c40e22018-11-26 17:01:36 -0800982 vcl_send_session_disconnected_reply (vpp_evt_q, wrk->my_client_index,
Florin Coras99368312018-08-02 10:45:44 -0700983 vpp_handle, 0);
Florin Coras5e062572019-03-14 19:07:51 -0700984 VDBG (1, "session %u [0x%llx]: sending disconnect REPLY...",
985 session->session_index, vpp_handle);
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400986 }
987 else
Dave Wallace227867f2017-11-13 21:21:53 -0500988 {
Florin Coras5e062572019-03-14 19:07:51 -0700989 VDBG (1, "session %u [0x%llx]: sending disconnect...",
990 session->session_index, vpp_handle);
Florin Coras458089b2019-08-21 16:20:44 -0700991 vcl_send_session_disconnect (wrk, session);
Dave Wallace227867f2017-11-13 21:21:53 -0500992 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400993
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +0200994 if (session->listener_index != VCL_INVALID_SESSION_INDEX)
995 {
996 listen_session = vcl_session_get (wrk, session->listener_index);
997 listen_session->n_accepted_sessions--;
998 }
999
Florin Coras070453d2018-08-24 17:04:27 -07001000 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001001}
1002
Florin Coras940f78f2018-11-30 12:11:20 -08001003/**
1004 * Handle app exit
1005 *
1006 * Notify vpp of the disconnect and mark the worker as free. If we're the
1007 * last worker, do a full cleanup otherwise, since we're probably a forked
1008 * child, avoid syscalls as much as possible. We might've lost privileges.
1009 */
1010void
1011vppcom_app_exit (void)
1012{
1013 if (!pool_elts (vcm->workers))
1014 return;
Florin Coras01f3f892018-12-02 12:45:53 -08001015 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
1016 vcl_set_worker_index (~0);
Florin Coras940f78f2018-11-30 12:11:20 -08001017 vcl_elog_stop (vcm);
1018 if (vec_len (vcm->workers) == 1)
Florin Coras470b2a62019-08-03 18:53:48 -07001019 vppcom_disconnect_from_vpp ();
Florin Coras940f78f2018-11-30 12:11:20 -08001020 else
Florin Coraseaec2a62018-12-04 16:34:05 -08001021 vl_client_send_disconnect (1 /* vpp should cleanup */ );
Florin Coras940f78f2018-11-30 12:11:20 -08001022}
1023
Dave Wallace543852a2017-08-03 02:11:34 -04001024/*
1025 * VPPCOM Public API functions
1026 */
1027int
1028vppcom_app_create (char *app_name)
1029{
Dave Wallace543852a2017-08-03 02:11:34 -04001030 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
Dave Wallace543852a2017-08-03 02:11:34 -04001031 int rv;
1032
Florin Coras47c40e22018-11-26 17:01:36 -08001033 if (vcm->is_init)
Dave Wallace543852a2017-08-03 02:11:34 -04001034 {
Florin Coras955bfbb2018-12-04 13:43:45 -08001035 VDBG (1, "already initialized");
1036 return VPPCOM_EEXIST;
Dave Wallace543852a2017-08-03 02:11:34 -04001037 }
1038
Florin Coras47c40e22018-11-26 17:01:36 -08001039 vcm->is_init = 1;
1040 vppcom_cfg (&vcm->cfg);
1041 vcl_cfg = &vcm->cfg;
1042
1043 vcm->main_cpu = pthread_self ();
1044 vcm->main_pid = getpid ();
1045 vcm->app_name = format (0, "%s", app_name);
1046 vppcom_init_error_string_table ();
Florin Coras88001c62019-04-24 14:44:46 -07001047 fifo_segment_main_init (&vcm->segment_main, vcl_cfg->segment_baseva,
1048 20 /* timeout in secs */ );
Florin Coras47c40e22018-11-26 17:01:36 -08001049 pool_alloc (vcm->workers, vcl_cfg->max_workers);
1050 clib_spinlock_init (&vcm->workers_lock);
Florin Corasd85de682018-11-29 17:02:29 -08001051 clib_rwlock_init (&vcm->segment_table_lock);
Florin Coras940f78f2018-11-30 12:11:20 -08001052 atexit (vppcom_app_exit);
Florin Coras47c40e22018-11-26 17:01:36 -08001053
1054 /* Allocate default worker */
1055 vcl_worker_alloc_and_init ();
1056
1057 /* API hookup and connect to VPP */
1058 vppcom_api_hookup ();
1059 vcl_elog_init (vcm);
1060 vcm->app_state = STATE_APP_START;
1061 rv = vppcom_connect_to_vpp (app_name);
1062 if (rv)
Dave Wallace543852a2017-08-03 02:11:34 -04001063 {
Florin Coras47c40e22018-11-26 17:01:36 -08001064 VERR ("couldn't connect to VPP!");
1065 return rv;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001066 }
Florin Coras47c40e22018-11-26 17:01:36 -08001067 VDBG (0, "sending session enable");
1068 rv = vppcom_app_session_enable ();
1069 if (rv)
1070 {
1071 VERR ("vppcom_app_session_enable() failed!");
1072 return rv;
1073 }
1074
1075 VDBG (0, "sending app attach");
1076 rv = vppcom_app_attach ();
1077 if (rv)
1078 {
1079 VERR ("vppcom_app_attach() failed!");
1080 return rv;
1081 }
1082
1083 VDBG (0, "app_name '%s', my_client_index %d (0x%x)", app_name,
1084 vcm->workers[0].my_client_index, vcm->workers[0].my_client_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001085
1086 return VPPCOM_OK;
1087}
1088
1089void
1090vppcom_app_destroy (void)
1091{
Dave Wallace543852a2017-08-03 02:11:34 -04001092 int rv;
Dave Wallacede910062018-03-20 09:22:13 -04001093 f64 orig_app_timeout;
Dave Wallace543852a2017-08-03 02:11:34 -04001094
Florin Coras940f78f2018-11-30 12:11:20 -08001095 if (!pool_elts (vcm->workers))
1096 return;
1097
Florin Coras0d427d82018-06-27 03:24:07 -07001098 vcl_evt (VCL_EVT_DETACH, vcm);
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -08001099
Florin Coras940f78f2018-11-30 12:11:20 -08001100 if (pool_elts (vcm->workers) == 1)
Florin Coras47c40e22018-11-26 17:01:36 -08001101 {
Florin Coras458089b2019-08-21 16:20:44 -07001102 vcl_send_app_detach (vcl_worker_get_current ());
Florin Coras47c40e22018-11-26 17:01:36 -08001103 orig_app_timeout = vcm->cfg.app_timeout;
1104 vcm->cfg.app_timeout = 2.0;
1105 rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
1106 vcm->cfg.app_timeout = orig_app_timeout;
1107 if (PREDICT_FALSE (rv))
1108 VDBG (0, "application detach timed out! returning %d (%s)", rv,
1109 vppcom_retval_str (rv));
Florin Coras940f78f2018-11-30 12:11:20 -08001110 vec_free (vcm->app_name);
Florin Coras01f3f892018-12-02 12:45:53 -08001111 vcl_worker_cleanup (vcl_worker_get_current (), 0 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -08001112 }
1113 else
1114 {
Florin Coras01f3f892018-12-02 12:45:53 -08001115 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -08001116 }
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -08001117
Florin Coras01f3f892018-12-02 12:45:53 -08001118 vcl_set_worker_index (~0);
Florin Coras0d427d82018-06-27 03:24:07 -07001119 vcl_elog_stop (vcm);
Dave Wallace543852a2017-08-03 02:11:34 -04001120 vl_client_disconnect_from_vlib ();
Dave Wallace543852a2017-08-03 02:11:34 -04001121}
1122
1123int
Dave Wallacec04cbf12018-02-07 18:14:02 -05001124vppcom_session_create (u8 proto, u8 is_nonblocking)
Dave Wallace543852a2017-08-03 02:11:34 -04001125{
Florin Coras134a9962018-08-28 11:32:04 -07001126 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001127 vcl_session_t *session;
Dave Wallace543852a2017-08-03 02:11:34 -04001128
Florin Coras134a9962018-08-28 11:32:04 -07001129 session = vcl_session_alloc (wrk);
Dave Wallace543852a2017-08-03 02:11:34 -04001130
Florin Coras7e12d942018-06-27 14:32:43 -07001131 session->session_type = proto;
1132 session->session_state = STATE_START;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001133 session->vpp_handle = ~0;
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001134 session->is_dgram = vcl_proto_is_dgram (proto);
Dave Wallace543852a2017-08-03 02:11:34 -04001135
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001136 if (is_nonblocking)
1137 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
Dave Wallace543852a2017-08-03 02:11:34 -04001138
Florin Coras7e12d942018-06-27 14:32:43 -07001139 vcl_evt (VCL_EVT_CREATE, session, session_type, session->session_state,
1140 is_nonblocking, session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001141
Florin Coras5e062572019-03-14 19:07:51 -07001142 VDBG (0, "created session %u", session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001143
Florin Coras134a9962018-08-28 11:32:04 -07001144 return vcl_session_handle (session);
Dave Wallace543852a2017-08-03 02:11:34 -04001145}
1146
1147int
Florin Corasf9240dc2019-01-15 08:03:17 -08001148vcl_session_cleanup (vcl_worker_t * wrk, vcl_session_t * session,
1149 vcl_session_handle_t sh, u8 do_disconnect)
Dave Wallace543852a2017-08-03 02:11:34 -04001150{
Florin Coras288eaab2019-02-03 15:26:14 -08001151 vcl_session_state_t state;
Florin Coras134a9962018-08-28 11:32:04 -07001152 u32 next_sh, vep_sh;
1153 int rv = VPPCOM_OK;
1154 u64 vpp_handle;
Florin Corasf9240dc2019-01-15 08:03:17 -08001155 u8 is_vep;
Florin Coras47c40e22018-11-26 17:01:36 -08001156
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001157 is_vep = session->is_vep;
Florin Coras134a9962018-08-28 11:32:04 -07001158 next_sh = session->vep.next_sh;
1159 vep_sh = session->vep.vep_sh;
Florin Coras7e12d942018-06-27 14:32:43 -07001160 state = session->session_state;
Dave Wallaceee45d412017-11-24 21:44:06 -05001161 vpp_handle = session->vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -04001162
Florin Corasf9240dc2019-01-15 08:03:17 -08001163 VDBG (1, "session %u [0x%llx] closing", session->session_index, vpp_handle);
Dave Wallace543852a2017-08-03 02:11:34 -04001164
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001165 if (is_vep)
Dave Wallace543852a2017-08-03 02:11:34 -04001166 {
Florin Coras134a9962018-08-28 11:32:04 -07001167 while (next_sh != ~0)
Dave Wallace19481612017-09-15 18:47:44 -04001168 {
Florin Corasf9240dc2019-01-15 08:03:17 -08001169 rv = vppcom_epoll_ctl (sh, EPOLL_CTL_DEL, next_sh, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001170 if (PREDICT_FALSE (rv < 0))
Florin Coras5e062572019-03-14 19:07:51 -07001171 VDBG (0, "vpp handle 0x%llx, sh %u: EPOLL_CTL_DEL vep_idx %u"
Florin Coras47c40e22018-11-26 17:01:36 -08001172 " failed! rv %d (%s)", vpp_handle, next_sh, vep_sh, rv,
1173 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001174
Florin Coras134a9962018-08-28 11:32:04 -07001175 next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001176 }
1177 }
1178 else
1179 {
Florin Coras47c40e22018-11-26 17:01:36 -08001180 if (session->is_vep_session)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001181 {
Florin Corasf9240dc2019-01-15 08:03:17 -08001182 rv = vppcom_epoll_ctl (vep_sh, EPOLL_CTL_DEL, sh, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001183 if (rv < 0)
Florin Corasf9240dc2019-01-15 08:03:17 -08001184 VDBG (0, "session %u [0x%llx]: EPOLL_CTL_DEL vep_idx %u "
1185 "failed! rv %d (%s)", session->session_index, vpp_handle,
1186 vep_sh, rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001187 }
1188
Florin Coras47c40e22018-11-26 17:01:36 -08001189 if (!do_disconnect)
Florin Coras30e79c22019-01-02 19:31:22 -08001190 {
Florin Coras0ef8ef22019-01-18 08:37:13 -08001191 VDBG (1, "session %u [0x%llx] disconnect skipped",
Florin Corasf9240dc2019-01-15 08:03:17 -08001192 session->session_index, vpp_handle);
Florin Coras30e79c22019-01-02 19:31:22 -08001193 goto cleanup;
1194 }
Florin Coras47c40e22018-11-26 17:01:36 -08001195
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001196 if (state & STATE_LISTEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001197 {
Florin Corasf9240dc2019-01-15 08:03:17 -08001198 rv = vppcom_session_unbind (sh);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001199 if (PREDICT_FALSE (rv < 0))
Florin Corasf9240dc2019-01-15 08:03:17 -08001200 VDBG (0, "session %u [0x%llx]: listener unbind failed! "
1201 "rv %d (%s)", session->session_index, vpp_handle, rv,
Florin Coras47c40e22018-11-26 17:01:36 -08001202 vppcom_retval_str (rv));
Florin Corasdfae9f92019-02-20 19:48:31 -08001203 return rv;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001204 }
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001205 else if ((state & STATE_OPEN)
1206 || (vcl_session_is_connectable_listener (wrk, session)))
Dave Wallacef7f809c2017-10-03 01:48:42 -04001207 {
Florin Corasf9240dc2019-01-15 08:03:17 -08001208 rv = vppcom_session_disconnect (sh);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001209 if (PREDICT_FALSE (rv < 0))
Florin Corasf9240dc2019-01-15 08:03:17 -08001210 VDBG (0, "ERROR: session %u [0x%llx]: disconnect failed!"
1211 " rv %d (%s)", session->session_index, vpp_handle,
1212 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001213 }
Florin Corasb0f662f2018-12-27 14:51:46 -08001214 else if (state == STATE_DISCONNECT)
1215 {
1216 svm_msg_q_t *mq = vcl_session_vpp_evt_q (wrk, session);
1217 vcl_send_session_reset_reply (mq, wrk->my_client_index,
1218 session->vpp_handle, 0);
1219 }
Dave Wallace19481612017-09-15 18:47:44 -04001220 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001221
Florin Coras0ef8ef22019-01-18 08:37:13 -08001222 VDBG (0, "session %u [0x%llx] removed", session->session_index, vpp_handle);
1223
Florin Corasf9240dc2019-01-15 08:03:17 -08001224cleanup:
Florin Coras30e79c22019-01-02 19:31:22 -08001225 vcl_session_table_del_vpp_handle (wrk, vpp_handle);
Florin Coras134a9962018-08-28 11:32:04 -07001226 vcl_session_free (wrk, session);
Florin Coras0d427d82018-06-27 03:24:07 -07001227 vcl_evt (VCL_EVT_CLOSE, session, rv);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001228
Dave Wallace543852a2017-08-03 02:11:34 -04001229 return rv;
1230}
1231
1232int
Florin Corasf9240dc2019-01-15 08:03:17 -08001233vppcom_session_close (uint32_t session_handle)
1234{
1235 vcl_worker_t *wrk = vcl_worker_get_current ();
1236 vcl_session_t *session;
1237
1238 session = vcl_session_get_w_handle (wrk, session_handle);
1239 if (!session)
1240 return VPPCOM_EBADFD;
1241 return vcl_session_cleanup (wrk, session, session_handle,
1242 1 /* do_disconnect */ );
1243}
1244
1245int
Florin Coras134a9962018-08-28 11:32:04 -07001246vppcom_session_bind (uint32_t session_handle, vppcom_endpt_t * ep)
Dave Wallace543852a2017-08-03 02:11:34 -04001247{
Florin Coras134a9962018-08-28 11:32:04 -07001248 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001249 vcl_session_t *session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001250
1251 if (!ep || !ep->ip)
1252 return VPPCOM_EINVAL;
1253
Florin Coras134a9962018-08-28 11:32:04 -07001254 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001255 if (!session)
1256 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001257
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001258 if (session->is_vep)
1259 {
Florin Coras5e062572019-03-14 19:07:51 -07001260 VDBG (0, "ERROR: cannot bind to epoll session %u!",
1261 session->session_index);
Florin Coras070453d2018-08-24 17:04:27 -07001262 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001263 }
1264
Florin Coras7e12d942018-06-27 14:32:43 -07001265 session->transport.is_ip4 = ep->is_ip4;
Florin Coras54693d22018-07-17 10:46:29 -07001266 if (ep->is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001267 clib_memcpy_fast (&session->transport.lcl_ip.ip4, ep->ip,
1268 sizeof (ip4_address_t));
Florin Coras54693d22018-07-17 10:46:29 -07001269 else
Dave Barach178cf492018-11-13 16:34:13 -05001270 clib_memcpy_fast (&session->transport.lcl_ip.ip6, ep->ip,
1271 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001272 session->transport.lcl_port = ep->port;
Stevenac1f96d2017-10-24 16:03:58 -07001273
Florin Coras5e062572019-03-14 19:07:51 -07001274 VDBG (0, "session %u handle %u: binding to local %s address %U port %u, "
1275 "proto %s", session->session_index, session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001276 session->transport.is_ip4 ? "IPv4" : "IPv6",
1277 format_ip46_address, &session->transport.lcl_ip,
1278 session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
1279 clib_net_to_host_u16 (session->transport.lcl_port),
Ping Yu34a3a082018-11-30 19:16:17 -05001280 vppcom_proto_str (session->session_type));
Florin Coras0d427d82018-06-27 03:24:07 -07001281 vcl_evt (VCL_EVT_BIND, session);
Florin Coras460dce62018-07-27 05:45:06 -07001282
1283 if (session->session_type == VPPCOM_PROTO_UDP)
Florin Coras134a9962018-08-28 11:32:04 -07001284 vppcom_session_listen (session_handle, 10);
Florin Coras460dce62018-07-27 05:45:06 -07001285
Florin Coras070453d2018-08-24 17:04:27 -07001286 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001287}
1288
1289int
Florin Coras134a9962018-08-28 11:32:04 -07001290vppcom_session_listen (uint32_t listen_sh, uint32_t q_len)
Dave Wallace543852a2017-08-03 02:11:34 -04001291{
Florin Coras134a9962018-08-28 11:32:04 -07001292 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001293 vcl_session_t *listen_session = 0;
Dave Wallaceee45d412017-11-24 21:44:06 -05001294 u64 listen_vpp_handle;
Florin Coras070453d2018-08-24 17:04:27 -07001295 int rv;
1296
Florin Coras134a9962018-08-28 11:32:04 -07001297 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001298 if (!listen_session || listen_session->is_vep)
Florin Coras070453d2018-08-24 17:04:27 -07001299 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001300
Keith Burns (alagalah)aba98de2018-02-22 03:23:40 -08001301 if (q_len == 0 || q_len == ~0)
1302 q_len = vcm->cfg.listen_queue_size;
1303
Dave Wallaceee45d412017-11-24 21:44:06 -05001304 listen_vpp_handle = listen_session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -07001305 if (listen_session->session_state & STATE_LISTEN)
Dave Wallacee695cb42017-11-02 22:04:42 -04001306 {
Florin Coras05ecfcc2018-12-12 18:19:39 -08001307 VDBG (0, "session %u [0x%llx]: already in listen state!",
1308 listen_sh, listen_vpp_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001309 return VPPCOM_OK;
Dave Wallacee695cb42017-11-02 22:04:42 -04001310 }
1311
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001312 VDBG (0, "session %u: sending vpp listen request...", listen_sh);
Dave Wallace543852a2017-08-03 02:11:34 -04001313
Florin Coras070453d2018-08-24 17:04:27 -07001314 /*
1315 * Send listen request to vpp and wait for reply
1316 */
Florin Coras458089b2019-08-21 16:20:44 -07001317 vcl_send_session_listen (wrk, listen_session);
Florin Coras134a9962018-08-28 11:32:04 -07001318 rv = vppcom_wait_for_session_state_change (listen_session->session_index,
1319 STATE_LISTEN,
1320 vcm->cfg.session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001321
Florin Coras070453d2018-08-24 17:04:27 -07001322 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001323 {
Florin Coras134a9962018-08-28 11:32:04 -07001324 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001325 VDBG (0, "session %u [0x%llx]: listen failed! returning %d (%s)",
1326 listen_sh, listen_session->vpp_handle, rv,
1327 vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001328 return rv;
Dave Wallaceee45d412017-11-24 21:44:06 -05001329 }
1330
Florin Coras070453d2018-08-24 17:04:27 -07001331 return VPPCOM_OK;
Keith Burns (alagalah)0d2b0d52018-03-06 15:55:22 -08001332}
1333
Ping Yu34a3a082018-11-30 19:16:17 -05001334int
1335vppcom_session_tls_add_cert (uint32_t session_handle, char *cert,
1336 uint32_t cert_len)
1337{
1338
1339 vcl_worker_t *wrk = vcl_worker_get_current ();
1340 vcl_session_t *session = 0;
1341
1342 session = vcl_session_get_w_handle (wrk, session_handle);
1343 if (!session)
1344 return VPPCOM_EBADFD;
1345
1346 if (cert_len == 0 || cert_len == ~0)
1347 return VPPCOM_EBADFD;
1348
1349 /*
1350 * Send listen request to vpp and wait for reply
1351 */
1352 vppcom_send_application_tls_cert_add (session, cert, cert_len);
Florin Coras458089b2019-08-21 16:20:44 -07001353 vcm->app_state = STATE_APP_ADDING_TLS_DATA;
1354 vcl_wait_for_app_state_change (STATE_APP_READY);
Ping Yu34a3a082018-11-30 19:16:17 -05001355 return VPPCOM_OK;
1356
1357}
1358
1359int
1360vppcom_session_tls_add_key (uint32_t session_handle, char *key,
1361 uint32_t key_len)
1362{
1363
1364 vcl_worker_t *wrk = vcl_worker_get_current ();
1365 vcl_session_t *session = 0;
1366
1367 session = vcl_session_get_w_handle (wrk, session_handle);
1368 if (!session)
1369 return VPPCOM_EBADFD;
1370
1371 if (key_len == 0 || key_len == ~0)
1372 return VPPCOM_EBADFD;
1373
Ping Yu34a3a082018-11-30 19:16:17 -05001374 vppcom_send_application_tls_key_add (session, key, key_len);
Florin Coras458089b2019-08-21 16:20:44 -07001375 vcm->app_state = STATE_APP_ADDING_TLS_DATA;
1376 vcl_wait_for_app_state_change (STATE_APP_READY);
Ping Yu34a3a082018-11-30 19:16:17 -05001377 return VPPCOM_OK;
Ping Yu34a3a082018-11-30 19:16:17 -05001378}
1379
Florin Coras134a9962018-08-28 11:32:04 -07001380static int
Florin Coras5e062572019-03-14 19:07:51 -07001381validate_args_session_accept_ (vcl_worker_t * wrk, vcl_session_t * ls)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001382{
Florin Coras5e062572019-03-14 19:07:51 -07001383 if (ls->is_vep)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001384 {
Florin Coras5e062572019-03-14 19:07:51 -07001385 VDBG (0, "ERROR: cannot accept on epoll session %u!",
1386 ls->session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001387 return VPPCOM_EBADFD;
1388 }
1389
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001390 if ((ls->session_state != STATE_LISTEN)
1391 && (!vcl_session_is_connectable_listener (wrk, ls)))
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001392 {
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001393 VDBG (0,
1394 "ERROR: session [0x%llx]: not in listen state! state 0x%x"
1395 " (%s)", ls->vpp_handle, ls->session_state,
Florin Coras5e062572019-03-14 19:07:51 -07001396 vppcom_session_state_str (ls->session_state));
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001397 return VPPCOM_EBADFD;
1398 }
1399 return VPPCOM_OK;
1400}
1401
1402int
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001403vppcom_unformat_proto (uint8_t * proto, char *proto_str)
1404{
1405 if (!strcmp (proto_str, "TCP"))
1406 *proto = VPPCOM_PROTO_TCP;
1407 else if (!strcmp (proto_str, "tcp"))
1408 *proto = VPPCOM_PROTO_TCP;
1409 else if (!strcmp (proto_str, "UDP"))
1410 *proto = VPPCOM_PROTO_UDP;
1411 else if (!strcmp (proto_str, "udp"))
1412 *proto = VPPCOM_PROTO_UDP;
1413 else if (!strcmp (proto_str, "UDPC"))
1414 *proto = VPPCOM_PROTO_UDPC;
1415 else if (!strcmp (proto_str, "udpc"))
1416 *proto = VPPCOM_PROTO_UDPC;
1417 else if (!strcmp (proto_str, "SCTP"))
1418 *proto = VPPCOM_PROTO_SCTP;
1419 else if (!strcmp (proto_str, "sctp"))
1420 *proto = VPPCOM_PROTO_SCTP;
1421 else if (!strcmp (proto_str, "TLS"))
1422 *proto = VPPCOM_PROTO_TLS;
1423 else if (!strcmp (proto_str, "tls"))
1424 *proto = VPPCOM_PROTO_TLS;
1425 else if (!strcmp (proto_str, "QUIC"))
1426 *proto = VPPCOM_PROTO_QUIC;
1427 else if (!strcmp (proto_str, "quic"))
1428 *proto = VPPCOM_PROTO_QUIC;
1429 else
1430 return 1;
1431 return 0;
1432}
1433
1434int
Florin Coras134a9962018-08-28 11:32:04 -07001435vppcom_session_accept (uint32_t listen_session_handle, vppcom_endpt_t * ep,
Dave Wallace048b1d62018-01-03 22:24:41 -05001436 uint32_t flags)
Dave Wallace543852a2017-08-03 02:11:34 -04001437{
Florin Coras3c7d4f92018-12-14 11:28:43 -08001438 u32 client_session_index = ~0, listen_session_index, accept_flags = 0;
Florin Coras134a9962018-08-28 11:32:04 -07001439 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001440 session_accepted_msg_t accepted_msg;
Florin Coras7e12d942018-06-27 14:32:43 -07001441 vcl_session_t *listen_session = 0;
1442 vcl_session_t *client_session = 0;
Florin Coras54693d22018-07-17 10:46:29 -07001443 vcl_session_msg_t *evt;
Florin Coras54693d22018-07-17 10:46:29 -07001444 svm_msg_q_msg_t msg;
1445 session_event_t *e;
1446 u8 is_nonblocking;
1447 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001448
Florin Coras134a9962018-08-28 11:32:04 -07001449 listen_session = vcl_session_get_w_handle (wrk, listen_session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001450 if (!listen_session)
1451 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001452
Florin Coras134a9962018-08-28 11:32:04 -07001453 listen_session_index = listen_session->session_index;
1454 if ((rv = validate_args_session_accept_ (wrk, listen_session)))
Florin Coras070453d2018-08-24 17:04:27 -07001455 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001456
Florin Coras54693d22018-07-17 10:46:29 -07001457 if (clib_fifo_elts (listen_session->accept_evts_fifo))
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001458 {
Florin Coras54693d22018-07-17 10:46:29 -07001459 clib_fifo_sub2 (listen_session->accept_evts_fifo, evt);
Florin Coras3c7d4f92018-12-14 11:28:43 -08001460 accept_flags = evt->flags;
Florin Coras54693d22018-07-17 10:46:29 -07001461 accepted_msg = evt->accepted_msg;
1462 goto handle;
1463 }
1464
1465 is_nonblocking = VCL_SESS_ATTR_TEST (listen_session->attr,
1466 VCL_SESS_ATTR_NONBLOCK);
Florin Coras54693d22018-07-17 10:46:29 -07001467 while (1)
1468 {
Carl Smith592a9092019-11-12 14:57:37 +13001469 if (svm_msg_q_is_empty (wrk->app_event_queue) && is_nonblocking)
1470 return VPPCOM_EAGAIN;
1471
Florin Coras134a9962018-08-28 11:32:04 -07001472 if (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_WAIT, 0))
Florin Coras54693d22018-07-17 10:46:29 -07001473 return VPPCOM_EAGAIN;
1474
Florin Coras134a9962018-08-28 11:32:04 -07001475 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001476 if (e->event_type != SESSION_CTRL_EVT_ACCEPTED)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001477 {
Florin Coras00cca802019-06-06 09:38:44 -07001478 VDBG (0, "discarded event: %u", e->event_type);
Florin Coras134a9962018-08-28 11:32:04 -07001479 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001480 continue;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001481 }
Dave Barach178cf492018-11-13 16:34:13 -05001482 clib_memcpy_fast (&accepted_msg, e->data, sizeof (accepted_msg));
Florin Coras134a9962018-08-28 11:32:04 -07001483 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001484 break;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001485 }
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001486
Florin Coras54693d22018-07-17 10:46:29 -07001487handle:
Keith Burns (alagalah)00f44cc2018-03-07 09:26:38 -08001488
Florin Coras00cca802019-06-06 09:38:44 -07001489 client_session_index = vcl_session_accepted_handler (wrk, &accepted_msg,
1490 listen_session_index);
1491 if (client_session_index == VCL_INVALID_SESSION_INDEX)
1492 return VPPCOM_ECONNABORTED;
1493
Florin Coras134a9962018-08-28 11:32:04 -07001494 listen_session = vcl_session_get (wrk, listen_session_index);
1495 client_session = vcl_session_get (wrk, client_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001496
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001497 if (flags & O_NONBLOCK)
1498 VCL_SESS_ATTR_SET (client_session->attr, VCL_SESS_ATTR_NONBLOCK);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001499
Florin Coras5e062572019-03-14 19:07:51 -07001500 VDBG (1, "listener %u [0x%llx]: Got a connect request! session %u [0x%llx],"
1501 " flags %d, is_nonblocking %u", listen_session->session_index,
1502 listen_session->vpp_handle, client_session_index,
1503 client_session->vpp_handle, flags,
1504 VCL_SESS_ATTR_TEST (client_session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace543852a2017-08-03 02:11:34 -04001505
Dave Wallace048b1d62018-01-03 22:24:41 -05001506 if (ep)
1507 {
Florin Coras7e12d942018-06-27 14:32:43 -07001508 ep->is_ip4 = client_session->transport.is_ip4;
1509 ep->port = client_session->transport.rmt_port;
1510 if (client_session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001511 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip4,
1512 sizeof (ip4_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001513 else
Dave Barach178cf492018-11-13 16:34:13 -05001514 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip6,
1515 sizeof (ip6_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001516 }
Dave Wallace60caa062017-11-10 17:07:13 -05001517
Florin Coras05ecfcc2018-12-12 18:19:39 -08001518 VDBG (0, "listener %u [0x%llx] accepted %u [0x%llx] peer: %U:%u "
Florin Coras5e062572019-03-14 19:07:51 -07001519 "local: %U:%u", listen_session_handle, listen_session->vpp_handle,
Florin Coras05ecfcc2018-12-12 18:19:39 -08001520 client_session_index, client_session->vpp_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001521 format_ip46_address, &client_session->transport.rmt_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001522 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001523 clib_net_to_host_u16 (client_session->transport.rmt_port),
Florin Coras7e12d942018-06-27 14:32:43 -07001524 format_ip46_address, &client_session->transport.lcl_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001525 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001526 clib_net_to_host_u16 (client_session->transport.lcl_port));
Florin Coras0d427d82018-06-27 03:24:07 -07001527 vcl_evt (VCL_EVT_ACCEPT, client_session, listen_session,
1528 client_session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001529
Florin Coras3c7d4f92018-12-14 11:28:43 -08001530 /*
1531 * Session might have been closed already
1532 */
1533 if (accept_flags)
1534 {
Florin Coras3c7d4f92018-12-14 11:28:43 -08001535 if (accept_flags & VCL_ACCEPTED_F_CLOSED)
Florin Corasb0f662f2018-12-27 14:51:46 -08001536 client_session->session_state = STATE_VPP_CLOSING;
Florin Coras3c7d4f92018-12-14 11:28:43 -08001537 else if (accept_flags & VCL_ACCEPTED_F_RESET)
Florin Corasb0f662f2018-12-27 14:51:46 -08001538 client_session->session_state = STATE_DISCONNECT;
Florin Coras3c7d4f92018-12-14 11:28:43 -08001539 }
Florin Corasab2f6db2018-08-31 14:31:41 -07001540 return vcl_session_handle (client_session);
Dave Wallace543852a2017-08-03 02:11:34 -04001541}
1542
Florin Corasef7cbf62019-10-17 09:56:27 -07001543static void
1544vcl_ip_copy_from_ep (ip46_address_t * ip, vppcom_endpt_t * ep)
1545{
1546 if (ep->is_ip4)
1547 clib_memcpy_fast (&ip->ip4, ep->ip, sizeof (ip4_address_t));
1548 else
1549 clib_memcpy_fast (&ip->ip6, ep->ip, sizeof (ip6_address_t));
1550}
1551
1552void
1553vcl_ip_copy_to_ep (ip46_address_t * ip, vppcom_endpt_t * ep, u8 is_ip4)
1554{
1555 ep->is_ip4 = is_ip4;
1556 if (is_ip4)
1557 clib_memcpy_fast (ep->ip, &ip->ip4, sizeof (ip4_address_t));
1558 else
1559 clib_memcpy_fast (ep->ip, &ip->ip6, sizeof (ip6_address_t));
1560}
1561
Dave Wallace543852a2017-08-03 02:11:34 -04001562int
Florin Coras134a9962018-08-28 11:32:04 -07001563vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep)
Dave Wallace543852a2017-08-03 02:11:34 -04001564{
Florin Coras134a9962018-08-28 11:32:04 -07001565 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001566 vcl_session_t *session = 0;
Florin Coras134a9962018-08-28 11:32:04 -07001567 u32 session_index;
Florin Coras070453d2018-08-24 17:04:27 -07001568 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001569
Florin Coras134a9962018-08-28 11:32:04 -07001570 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001571 if (!session)
1572 return VPPCOM_EBADFD;
Florin Coras134a9962018-08-28 11:32:04 -07001573 session_index = session->session_index;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001574
1575 if (PREDICT_FALSE (session->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001576 {
Florin Coras5e062572019-03-14 19:07:51 -07001577 VDBG (0, "ERROR: cannot connect epoll session %u!",
1578 session->session_index);
Florin Coras070453d2018-08-24 17:04:27 -07001579 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001580 }
1581
Florin Coras7e12d942018-06-27 14:32:43 -07001582 if (PREDICT_FALSE (session->session_state & CLIENT_STATE_OPEN))
Dave Wallace543852a2017-08-03 02:11:34 -04001583 {
Florin Coras7baeb712019-01-04 17:05:43 -08001584 VDBG (0, "session handle %u [0x%llx]: session already "
Florin Coras0d427d82018-06-27 03:24:07 -07001585 "connected to %s %U port %d proto %s, state 0x%x (%s)",
Florin Coras7baeb712019-01-04 17:05:43 -08001586 session_handle, session->vpp_handle,
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001587 session->transport.is_ip4 ? "IPv4" : "IPv6", format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001588 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001589 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001590 clib_net_to_host_u16 (session->transport.rmt_port),
Ping Yu34a3a082018-11-30 19:16:17 -05001591 vppcom_proto_str (session->session_type), session->session_state,
Florin Coras7e12d942018-06-27 14:32:43 -07001592 vppcom_session_state_str (session->session_state));
Florin Coras070453d2018-08-24 17:04:27 -07001593 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001594 }
1595
Florin Coras7e12d942018-06-27 14:32:43 -07001596 session->transport.is_ip4 = server_ep->is_ip4;
Florin Corasef7cbf62019-10-17 09:56:27 -07001597 vcl_ip_copy_from_ep (&session->transport.rmt_ip, server_ep);
Florin Coras7e12d942018-06-27 14:32:43 -07001598 session->transport.rmt_port = server_ep->port;
Nathan Skrzypczak8ac1d6d2019-07-17 11:02:20 +02001599 session->parent_handle = VCL_INVALID_SESSION_HANDLE;
Dave Wallace543852a2017-08-03 02:11:34 -04001600
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001601 VDBG (0, "session handle %u: connecting to server %s %U "
1602 "port %d proto %s", session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001603 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001604 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001605 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001606 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001607 clib_net_to_host_u16 (session->transport.rmt_port),
Ping Yu34a3a082018-11-30 19:16:17 -05001608 vppcom_proto_str (session->session_type));
Dave Wallace543852a2017-08-03 02:11:34 -04001609
Florin Coras458089b2019-08-21 16:20:44 -07001610 vcl_send_session_connect (wrk, session);
Florin Coras57c88932019-08-29 12:03:17 -07001611
1612 if (VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK))
1613 return VPPCOM_EINPROGRESS;
1614
1615 /*
1616 * Wait for reply from vpp if blocking
1617 */
Florin Coras070453d2018-08-24 17:04:27 -07001618 rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
1619 vcm->cfg.session_timeout);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001620
Florin Coras134a9962018-08-28 11:32:04 -07001621 session = vcl_session_get (wrk, session_index);
Florin Coras5e062572019-03-14 19:07:51 -07001622 VDBG (0, "session %u [0x%llx]: connect %s!", session->session_index,
1623 session->vpp_handle, rv ? "failed" : "succeeded");
Dave Wallaceee45d412017-11-24 21:44:06 -05001624
Dave Wallace4878cbe2017-11-21 03:45:09 -05001625 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001626}
1627
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001628int
1629vppcom_session_stream_connect (uint32_t session_handle,
1630 uint32_t parent_session_handle)
1631{
1632 vcl_worker_t *wrk = vcl_worker_get_current ();
1633 vcl_session_t *session, *parent_session;
1634 u32 session_index, parent_session_index;
1635 int rv;
1636
1637 session = vcl_session_get_w_handle (wrk, session_handle);
1638 if (!session)
1639 return VPPCOM_EBADFD;
1640 parent_session = vcl_session_get_w_handle (wrk, parent_session_handle);
1641 if (!parent_session)
1642 return VPPCOM_EBADFD;
1643
1644 session_index = session->session_index;
1645 parent_session_index = parent_session->session_index;
1646 if (PREDICT_FALSE (session->is_vep))
1647 {
1648 VDBG (0, "ERROR: cannot connect epoll session %u!",
1649 session->session_index);
1650 return VPPCOM_EBADFD;
1651 }
1652
1653 if (PREDICT_FALSE (session->session_state & CLIENT_STATE_OPEN))
1654 {
1655 VDBG (0, "session handle %u [0x%llx]: session already "
1656 "connected to session %u [0x%llx] proto %s, state 0x%x (%s)",
1657 session_handle, session->vpp_handle,
1658 parent_session_handle, parent_session->vpp_handle,
1659 vppcom_proto_str (session->session_type), session->session_state,
1660 vppcom_session_state_str (session->session_state));
1661 return VPPCOM_OK;
1662 }
1663
1664 /* Connect to quic session specifics */
1665 session->transport.is_ip4 = parent_session->transport.is_ip4;
1666 session->transport.rmt_ip.ip4.as_u32 = (uint32_t) 1;
1667 session->transport.rmt_port = 0;
Nathan Skrzypczak8ac1d6d2019-07-17 11:02:20 +02001668 session->parent_handle = parent_session->vpp_handle;
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001669
1670 VDBG (0, "session handle %u: connecting to session %u [0x%llx]",
1671 session_handle, parent_session_handle, parent_session->vpp_handle);
1672
1673 /*
1674 * Send connect request and wait for reply from vpp
1675 */
Florin Coras458089b2019-08-21 16:20:44 -07001676 vcl_send_session_connect (wrk, session);
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001677 rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
1678 vcm->cfg.session_timeout);
1679
1680 session->listener_index = parent_session_index;
1681 parent_session = vcl_session_get_w_handle (wrk, parent_session_handle);
Florin Coras028eaf02019-07-19 12:15:52 -07001682 if (parent_session)
1683 parent_session->n_accepted_sessions++;
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02001684
1685 session = vcl_session_get (wrk, session_index);
1686 VDBG (0, "session %u [0x%llx]: connect %s!", session->session_index,
1687 session->vpp_handle, rv ? "failed" : "succeeded");
1688
1689 return rv;
1690}
1691
Florin Coras54693d22018-07-17 10:46:29 -07001692static u8
1693vcl_is_rx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1694{
Florin Corasc0737e92019-03-04 14:19:39 -08001695 return (e->event_type == SESSION_IO_EVT_RX && e->session_index == sid);
Florin Coras54693d22018-07-17 10:46:29 -07001696}
1697
Steven58f464e2017-10-25 12:33:12 -07001698static inline int
Florin Coras134a9962018-08-28 11:32:04 -07001699vppcom_session_read_internal (uint32_t session_handle, void *buf, int n,
Steven58f464e2017-10-25 12:33:12 -07001700 u8 peek)
Dave Wallace543852a2017-08-03 02:11:34 -04001701{
Florin Coras134a9962018-08-28 11:32:04 -07001702 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras6d0106e2019-01-29 20:11:58 -08001703 int n_read = 0, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001704 vcl_session_t *s = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001705 svm_fifo_t *rx_fifo;
Florin Coras54693d22018-07-17 10:46:29 -07001706 svm_msg_q_msg_t msg;
1707 session_event_t *e;
1708 svm_msg_q_t *mq;
Florin Coras41c9e042018-09-11 00:10:41 -07001709 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001710
Florin Coras070453d2018-08-24 17:04:27 -07001711 if (PREDICT_FALSE (!buf))
1712 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001713
Florin Coras134a9962018-08-28 11:32:04 -07001714 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras2cba8532018-09-11 16:33:36 -07001715 if (PREDICT_FALSE (!s || s->is_vep))
Florin Coras070453d2018-08-24 17:04:27 -07001716 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001717
Florin Coras6d0106e2019-01-29 20:11:58 -08001718 if (PREDICT_FALSE (!vcl_session_is_open (s)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001719 {
Florin Coras5e062572019-03-14 19:07:51 -07001720 VDBG (0, "session %u[0x%llx] is not open! state 0x%x (%s)",
Florin Coras6d0106e2019-01-29 20:11:58 -08001721 s->session_index, s->vpp_handle, s->session_state,
1722 vppcom_session_state_str (s->session_state));
1723 return vcl_session_closed_error (s);
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001724 }
1725
Florin Coras2cba8532018-09-11 16:33:36 -07001726 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
Florin Coras41c9e042018-09-11 00:10:41 -07001727 is_ct = vcl_session_is_ct (s);
Florin Coras653e43f2019-03-04 10:56:23 -08001728 mq = wrk->app_event_queue;
1729 rx_fifo = is_ct ? s->ct_rx_fifo : s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001730 s->has_rx_evt = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001731
Sirshak Das28aa5392019-02-05 01:33:33 -06001732 if (svm_fifo_is_empty_cons (rx_fifo))
Dave Wallacef7f809c2017-10-03 01:48:42 -04001733 {
Florin Coras54693d22018-07-17 10:46:29 -07001734 if (is_nonblocking)
Florin Corasc0737e92019-03-04 14:19:39 -08001735 {
1736 svm_fifo_unset_event (s->rx_fifo);
1737 return VPPCOM_EWOULDBLOCK;
1738 }
Sirshak Das28aa5392019-02-05 01:33:33 -06001739 while (svm_fifo_is_empty_cons (rx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001740 {
Florin Coras6d0106e2019-01-29 20:11:58 -08001741 if (vcl_session_is_closing (s))
1742 return vcl_session_closing_error (s);
1743
Florin Corasc0737e92019-03-04 14:19:39 -08001744 svm_fifo_unset_event (s->rx_fifo);
Florin Coras99368312018-08-02 10:45:44 -07001745 svm_msg_q_lock (mq);
Florin Coras54693d22018-07-17 10:46:29 -07001746 if (svm_msg_q_is_empty (mq))
1747 svm_msg_q_wait (mq);
Florin Coras99368312018-08-02 10:45:44 -07001748
Florin Coras54693d22018-07-17 10:46:29 -07001749 svm_msg_q_sub_w_lock (mq, &msg);
1750 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001751 svm_msg_q_unlock (mq);
Florin Coras41c9e042018-09-11 00:10:41 -07001752 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
Florin Corasc0737e92019-03-04 14:19:39 -08001753 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001754 svm_msg_q_free_msg (mq, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001755 }
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001756 }
Florin Coras54693d22018-07-17 10:46:29 -07001757
Florin Coras460dce62018-07-27 05:45:06 -07001758 if (s->is_dgram)
Florin Coras99368312018-08-02 10:45:44 -07001759 n_read = app_recv_dgram_raw (rx_fifo, buf, n, &s->transport, 0, peek);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001760 else
Florin Coras99368312018-08-02 10:45:44 -07001761 n_read = app_recv_stream_raw (rx_fifo, buf, n, 0, peek);
Florin Coras54693d22018-07-17 10:46:29 -07001762
Sirshak Das28aa5392019-02-05 01:33:33 -06001763 if (svm_fifo_is_empty_cons (rx_fifo))
Florin Corasc0737e92019-03-04 14:19:39 -08001764 svm_fifo_unset_event (s->rx_fifo);
Florin Coras41c9e042018-09-11 00:10:41 -07001765
Florin Coras317b8e02019-04-17 09:57:46 -07001766 /* Cut-through sessions might request tx notifications on rx fifos */
Florin Coras2d379d82019-06-28 12:45:12 -07001767 if (PREDICT_FALSE (rx_fifo->want_deq_ntf))
Florin Coras317b8e02019-04-17 09:57:46 -07001768 {
1769 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo->master_session_index,
1770 SESSION_IO_EVT_RX, SVM_Q_WAIT);
Florin Coras2d379d82019-06-28 12:45:12 -07001771 svm_fifo_reset_has_deq_ntf (s->rx_fifo);
Florin Coras317b8e02019-04-17 09:57:46 -07001772 }
1773
Florin Coras5e062572019-03-14 19:07:51 -07001774 VDBG (2, "session %u[0x%llx]: read %d bytes from (%p)", s->session_index,
1775 s->vpp_handle, n_read, rx_fifo);
Florin Coras2cba8532018-09-11 16:33:36 -07001776
Florin Coras54693d22018-07-17 10:46:29 -07001777 return n_read;
Dave Wallace543852a2017-08-03 02:11:34 -04001778}
1779
Steven58f464e2017-10-25 12:33:12 -07001780int
Florin Coras134a9962018-08-28 11:32:04 -07001781vppcom_session_read (uint32_t session_handle, void *buf, size_t n)
Steven58f464e2017-10-25 12:33:12 -07001782{
Florin Coras134a9962018-08-28 11:32:04 -07001783 return (vppcom_session_read_internal (session_handle, buf, n, 0));
Steven58f464e2017-10-25 12:33:12 -07001784}
1785
1786static int
Florin Coras134a9962018-08-28 11:32:04 -07001787vppcom_session_peek (uint32_t session_handle, void *buf, int n)
Steven58f464e2017-10-25 12:33:12 -07001788{
Florin Coras134a9962018-08-28 11:32:04 -07001789 return (vppcom_session_read_internal (session_handle, buf, n, 1));
Steven58f464e2017-10-25 12:33:12 -07001790}
1791
Florin Coras2cba8532018-09-11 16:33:36 -07001792int
1793vppcom_session_read_segments (uint32_t session_handle,
1794 vppcom_data_segments_t ds)
1795{
1796 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras6d0106e2019-01-29 20:11:58 -08001797 int n_read = 0, is_nonblocking;
Florin Coras2cba8532018-09-11 16:33:36 -07001798 vcl_session_t *s = 0;
1799 svm_fifo_t *rx_fifo;
1800 svm_msg_q_msg_t msg;
1801 session_event_t *e;
1802 svm_msg_q_t *mq;
1803 u8 is_ct;
1804
1805 s = vcl_session_get_w_handle (wrk, session_handle);
1806 if (PREDICT_FALSE (!s || s->is_vep))
1807 return VPPCOM_EBADFD;
1808
Florin Coras6d0106e2019-01-29 20:11:58 -08001809 if (PREDICT_FALSE (!vcl_session_is_open (s)))
1810 return vcl_session_closed_error (s);
Florin Coras2cba8532018-09-11 16:33:36 -07001811
1812 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1813 is_ct = vcl_session_is_ct (s);
1814 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
1815 rx_fifo = s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001816 s->has_rx_evt = 0;
Florin Coras2cba8532018-09-11 16:33:36 -07001817
Florin Coras653e43f2019-03-04 10:56:23 -08001818 if (is_ct)
1819 svm_fifo_unset_event (s->rx_fifo);
1820
Sirshak Das28aa5392019-02-05 01:33:33 -06001821 if (svm_fifo_is_empty_cons (rx_fifo))
Florin Coras2cba8532018-09-11 16:33:36 -07001822 {
1823 if (is_nonblocking)
1824 {
1825 svm_fifo_unset_event (rx_fifo);
Florin Corasaa27eb92018-10-13 12:20:01 -07001826 return VPPCOM_EWOULDBLOCK;
Florin Coras2cba8532018-09-11 16:33:36 -07001827 }
Sirshak Das28aa5392019-02-05 01:33:33 -06001828 while (svm_fifo_is_empty_cons (rx_fifo))
Florin Coras2cba8532018-09-11 16:33:36 -07001829 {
Florin Coras6d0106e2019-01-29 20:11:58 -08001830 if (vcl_session_is_closing (s))
1831 return vcl_session_closing_error (s);
1832
Florin Coras2cba8532018-09-11 16:33:36 -07001833 svm_fifo_unset_event (rx_fifo);
1834 svm_msg_q_lock (mq);
1835 if (svm_msg_q_is_empty (mq))
1836 svm_msg_q_wait (mq);
1837
1838 svm_msg_q_sub_w_lock (mq, &msg);
1839 e = svm_msg_q_msg_data (mq, &msg);
1840 svm_msg_q_unlock (mq);
1841 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
Florin Coras05ce4b82018-12-15 18:30:43 -08001842 vcl_handle_mq_event (wrk, e);
Florin Coras2cba8532018-09-11 16:33:36 -07001843 svm_msg_q_free_msg (mq, &msg);
Florin Coras2cba8532018-09-11 16:33:36 -07001844 }
1845 }
1846
Florin Coras88001c62019-04-24 14:44:46 -07001847 n_read = svm_fifo_segments (rx_fifo, (svm_fifo_seg_t *) ds);
Florin Coras2cba8532018-09-11 16:33:36 -07001848 svm_fifo_unset_event (rx_fifo);
1849
Florin Coras2cba8532018-09-11 16:33:36 -07001850 return n_read;
1851}
1852
1853void
1854vppcom_session_free_segments (uint32_t session_handle,
1855 vppcom_data_segments_t ds)
1856{
1857 vcl_worker_t *wrk = vcl_worker_get_current ();
1858 vcl_session_t *s;
1859
1860 s = vcl_session_get_w_handle (wrk, session_handle);
1861 if (PREDICT_FALSE (!s || s->is_vep))
1862 return;
1863
Florin Coras88001c62019-04-24 14:44:46 -07001864 svm_fifo_segments_free (s->rx_fifo, (svm_fifo_seg_t *) ds);
Florin Coras2cba8532018-09-11 16:33:36 -07001865}
1866
Florin Coras2cba8532018-09-11 16:33:36 -07001867int
1868vppcom_data_segment_copy (void *buf, vppcom_data_segments_t ds, u32 max_bytes)
1869{
1870 u32 first_copy = clib_min (ds[0].len, max_bytes);
Dave Barach178cf492018-11-13 16:34:13 -05001871 clib_memcpy_fast (buf, ds[0].data, first_copy);
Florin Coras2cba8532018-09-11 16:33:36 -07001872 if (first_copy < max_bytes)
1873 {
Dave Barach178cf492018-11-13 16:34:13 -05001874 clib_memcpy_fast (buf + first_copy, ds[1].data,
1875 clib_min (ds[1].len, max_bytes - first_copy));
Florin Coras2cba8532018-09-11 16:33:36 -07001876 }
1877 return 0;
1878}
1879
Florin Coras54693d22018-07-17 10:46:29 -07001880static u8
1881vcl_is_tx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1882{
Florin Corasc0737e92019-03-04 14:19:39 -08001883 return (e->event_type == SESSION_IO_EVT_TX && e->session_index == sid);
Dave Wallace543852a2017-08-03 02:11:34 -04001884}
1885
Florin Coras42ceddb2018-12-12 10:56:01 -08001886static inline int
1887vppcom_session_write_inline (uint32_t session_handle, void *buf, size_t n,
1888 u8 is_flush)
Dave Wallace543852a2017-08-03 02:11:34 -04001889{
Florin Coras134a9962018-08-28 11:32:04 -07001890 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras6d0106e2019-01-29 20:11:58 -08001891 int n_write, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001892 vcl_session_t *s = 0;
Florin Coras460dce62018-07-27 05:45:06 -07001893 session_evt_type_t et;
Florin Coras54693d22018-07-17 10:46:29 -07001894 svm_msg_q_msg_t msg;
Florin Coras14ed6df2019-03-06 21:13:42 -08001895 svm_fifo_t *tx_fifo;
Florin Coras54693d22018-07-17 10:46:29 -07001896 session_event_t *e;
Florin Coras3c2fed52018-07-04 04:15:05 -07001897 svm_msg_q_t *mq;
Florin Coras0e88e852018-09-17 22:09:02 -07001898 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001899
Florin Coras070453d2018-08-24 17:04:27 -07001900 if (PREDICT_FALSE (!buf))
1901 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001902
Florin Coras134a9962018-08-28 11:32:04 -07001903 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001904 if (PREDICT_FALSE (!s))
1905 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001906
Florin Coras460dce62018-07-27 05:45:06 -07001907 if (PREDICT_FALSE (s->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001908 {
Florin Coras6d0106e2019-01-29 20:11:58 -08001909 VDBG (0, "ERROR: session %u [0x%llx]: cannot write to an epoll"
1910 " session!", s->session_index, s->vpp_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001911 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001912 }
1913
Florin Coras6d0106e2019-01-29 20:11:58 -08001914 if (PREDICT_FALSE (!vcl_session_is_open (s)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001915 {
Florin Coras6d0106e2019-01-29 20:11:58 -08001916 VDBG (1, "session %u [0x%llx]: is not open! state 0x%x (%s)",
1917 s->session_index, s->vpp_handle, s->session_state,
1918 vppcom_session_state_str (s->session_state));
1919 return vcl_session_closed_error (s);;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001920 }
1921
Florin Coras0e88e852018-09-17 22:09:02 -07001922 is_ct = vcl_session_is_ct (s);
Florin Coras653e43f2019-03-04 10:56:23 -08001923 tx_fifo = is_ct ? s->ct_tx_fifo : s->tx_fifo;
Florin Coras0e88e852018-09-17 22:09:02 -07001924 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
Sirshak Das28aa5392019-02-05 01:33:33 -06001925
Florin Coras653e43f2019-03-04 10:56:23 -08001926 mq = wrk->app_event_queue;
Sirshak Das28aa5392019-02-05 01:33:33 -06001927 if (svm_fifo_is_full_prod (tx_fifo))
Dave Wallace543852a2017-08-03 02:11:34 -04001928 {
Florin Coras54693d22018-07-17 10:46:29 -07001929 if (is_nonblocking)
1930 {
Florin Coras070453d2018-08-24 17:04:27 -07001931 return VPPCOM_EWOULDBLOCK;
Florin Coras54693d22018-07-17 10:46:29 -07001932 }
Sirshak Das28aa5392019-02-05 01:33:33 -06001933 while (svm_fifo_is_full_prod (tx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001934 {
Florin Coras2d379d82019-06-28 12:45:12 -07001935 svm_fifo_add_want_deq_ntf (tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
Florin Coras6d0106e2019-01-29 20:11:58 -08001936 if (vcl_session_is_closing (s))
1937 return vcl_session_closing_error (s);
Florin Coras99368312018-08-02 10:45:44 -07001938 svm_msg_q_lock (mq);
Florin Corasaa27eb92018-10-13 12:20:01 -07001939 if (svm_msg_q_is_empty (mq))
1940 svm_msg_q_wait (mq);
Florin Coras0e88e852018-09-17 22:09:02 -07001941
Florin Coras54693d22018-07-17 10:46:29 -07001942 svm_msg_q_sub_w_lock (mq, &msg);
1943 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001944 svm_msg_q_unlock (mq);
1945
Florin Coras0e88e852018-09-17 22:09:02 -07001946 if (!vcl_is_tx_evt_for_session (e, s->session_index, is_ct))
Florin Coras86f04502018-09-12 16:08:01 -07001947 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001948 svm_msg_q_free_msg (mq, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001949 }
Dave Wallace543852a2017-08-03 02:11:34 -04001950 }
Dave Wallace543852a2017-08-03 02:11:34 -04001951
Florin Coras653e43f2019-03-04 10:56:23 -08001952 et = SESSION_IO_EVT_TX;
1953 if (is_flush && !is_ct)
Florin Coras42ceddb2018-12-12 10:56:01 -08001954 et = SESSION_IO_EVT_TX_FLUSH;
1955
Florin Coras460dce62018-07-27 05:45:06 -07001956 if (s->is_dgram)
1957 n_write = app_send_dgram_raw (tx_fifo, &s->transport,
Florin Coras653e43f2019-03-04 10:56:23 -08001958 s->vpp_evt_q, buf, n, et,
Florin Coras14ed6df2019-03-06 21:13:42 -08001959 0 /* do_evt */ , SVM_Q_WAIT);
Florin Coras460dce62018-07-27 05:45:06 -07001960 else
1961 n_write = app_send_stream_raw (tx_fifo, s->vpp_evt_q, buf, n, et,
Florin Coras14ed6df2019-03-06 21:13:42 -08001962 0 /* do_evt */ , SVM_Q_WAIT);
Florin Coras653e43f2019-03-04 10:56:23 -08001963
Florin Coras14ed6df2019-03-06 21:13:42 -08001964 if (svm_fifo_set_event (s->tx_fifo))
Florin Corasc0737e92019-03-04 14:19:39 -08001965 app_send_io_evt_to_vpp (s->vpp_evt_q, s->tx_fifo->master_session_index,
1966 et, SVM_Q_WAIT);
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -07001967
Florin Coras460dce62018-07-27 05:45:06 -07001968 ASSERT (n_write > 0);
Dave Wallace543852a2017-08-03 02:11:34 -04001969
Florin Coras6d0106e2019-01-29 20:11:58 -08001970 VDBG (2, "session %u [0x%llx]: wrote %d bytes", s->session_index,
1971 s->vpp_handle, n_write);
Florin Coras0e88e852018-09-17 22:09:02 -07001972
Florin Coras54693d22018-07-17 10:46:29 -07001973 return n_write;
Dave Wallace543852a2017-08-03 02:11:34 -04001974}
1975
Florin Coras42ceddb2018-12-12 10:56:01 -08001976int
1977vppcom_session_write (uint32_t session_handle, void *buf, size_t n)
1978{
1979 return vppcom_session_write_inline (session_handle, buf, n,
1980 0 /* is_flush */ );
1981}
1982
Florin Corasb0f662f2018-12-27 14:51:46 -08001983int
1984vppcom_session_write_msg (uint32_t session_handle, void *buf, size_t n)
1985{
1986 return vppcom_session_write_inline (session_handle, buf, n,
1987 1 /* is_flush */ );
1988}
1989
Florin Corasc0737e92019-03-04 14:19:39 -08001990#define vcl_fifo_rx_evt_valid_or_break(_s) \
Florin Corasbd52e462019-10-28 13:22:37 -07001991if (PREDICT_FALSE (!_s->rx_fifo)) \
1992 break; \
Florin Corasc0737e92019-03-04 14:19:39 -08001993if (PREDICT_FALSE (svm_fifo_is_empty (_s->rx_fifo))) \
1994 { \
1995 if (!vcl_session_is_ct (_s)) \
1996 { \
1997 svm_fifo_unset_event (_s->rx_fifo); \
1998 if (svm_fifo_is_empty (_s->rx_fifo)) \
1999 break; \
2000 } \
2001 else if (svm_fifo_is_empty (_s->ct_rx_fifo)) \
2002 { \
2003 svm_fifo_unset_event (_s->ct_rx_fifo); \
2004 if (svm_fifo_is_empty (_s->ct_rx_fifo)) \
2005 break; \
2006 } \
2007 } \
Florin Coras6d4bb422018-09-04 22:07:27 -07002008
Florin Coras86f04502018-09-12 16:08:01 -07002009static void
2010vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
2011 unsigned long n_bits, unsigned long *read_map,
2012 unsigned long *write_map,
2013 unsigned long *except_map, u32 * bits_set)
Florin Coras54693d22018-07-17 10:46:29 -07002014{
2015 session_disconnected_msg_t *disconnected_msg;
Florin Coras99368312018-08-02 10:45:44 -07002016 session_connected_msg_t *connected_msg;
Florin Coras54693d22018-07-17 10:46:29 -07002017 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07002018 u32 sid;
2019
2020 switch (e->event_type)
2021 {
Florin Corasc0737e92019-03-04 14:19:39 -08002022 case SESSION_IO_EVT_RX:
2023 sid = e->session_index;
Florin Coras86f04502018-09-12 16:08:01 -07002024 session = vcl_session_get (wrk, sid);
2025 if (!session)
2026 break;
Florin Corasfff68f72019-03-13 16:01:38 -07002027 vcl_fifo_rx_evt_valid_or_break (session);
Florin Coras86f04502018-09-12 16:08:01 -07002028 if (sid < n_bits && read_map)
2029 {
David Johnsond9818dd2018-12-14 14:53:41 -05002030 clib_bitmap_set_no_check ((uword *) read_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002031 *bits_set += 1;
2032 }
2033 break;
Florin Corasfe97da32019-03-06 10:09:04 -08002034 case SESSION_IO_EVT_TX:
Florin Corasc0737e92019-03-04 14:19:39 -08002035 sid = e->session_index;
Florin Coras86f04502018-09-12 16:08:01 -07002036 session = vcl_session_get (wrk, sid);
2037 if (!session)
2038 break;
2039 if (sid < n_bits && write_map)
2040 {
David Johnsond9818dd2018-12-14 14:53:41 -05002041 clib_bitmap_set_no_check ((uword *) write_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002042 *bits_set += 1;
2043 }
2044 break;
Florin Coras86f04502018-09-12 16:08:01 -07002045 case SESSION_CTRL_EVT_ACCEPTED:
Florin Coras3c7d4f92018-12-14 11:28:43 -08002046 session = vcl_session_accepted (wrk,
2047 (session_accepted_msg_t *) e->data);
Florin Coras86f04502018-09-12 16:08:01 -07002048 if (!session)
Florin Coras3c7d4f92018-12-14 11:28:43 -08002049 break;
Florin Coras86f04502018-09-12 16:08:01 -07002050 sid = session->session_index;
2051 if (sid < n_bits && read_map)
2052 {
David Johnsond9818dd2018-12-14 14:53:41 -05002053 clib_bitmap_set_no_check ((uword *) read_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002054 *bits_set += 1;
2055 }
2056 break;
2057 case SESSION_CTRL_EVT_CONNECTED:
2058 connected_msg = (session_connected_msg_t *) e->data;
Florin Coras57c88932019-08-29 12:03:17 -07002059 sid = vcl_session_connected_handler (wrk, connected_msg);
2060 if (sid == VCL_INVALID_SESSION_INDEX)
2061 break;
2062 if (sid < n_bits && write_map)
2063 {
2064 clib_bitmap_set_no_check ((uword *) write_map, sid, 1);
2065 *bits_set += 1;
2066 }
Florin Coras86f04502018-09-12 16:08:01 -07002067 break;
2068 case SESSION_CTRL_EVT_DISCONNECTED:
2069 disconnected_msg = (session_disconnected_msg_t *) e->data;
Florin Coras3c7d4f92018-12-14 11:28:43 -08002070 session = vcl_session_disconnected_handler (wrk, disconnected_msg);
2071 if (!session)
2072 break;
2073 sid = session->session_index;
Florin Coras86f04502018-09-12 16:08:01 -07002074 if (sid < n_bits && except_map)
2075 {
David Johnsond9818dd2018-12-14 14:53:41 -05002076 clib_bitmap_set_no_check ((uword *) except_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002077 *bits_set += 1;
2078 }
2079 break;
2080 case SESSION_CTRL_EVT_RESET:
2081 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
2082 if (sid < n_bits && except_map)
2083 {
David Johnsond9818dd2018-12-14 14:53:41 -05002084 clib_bitmap_set_no_check ((uword *) except_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002085 *bits_set += 1;
2086 }
2087 break;
Florin Corasdfae9f92019-02-20 19:48:31 -08002088 case SESSION_CTRL_EVT_UNLISTEN_REPLY:
2089 vcl_session_unlisten_reply_handler (wrk, e->data);
2090 break;
Florin Coras30e79c22019-01-02 19:31:22 -08002091 case SESSION_CTRL_EVT_WORKER_UPDATE_REPLY:
2092 vcl_session_worker_update_reply_handler (wrk, e->data);
2093 break;
2094 case SESSION_CTRL_EVT_REQ_WORKER_UPDATE:
2095 vcl_session_req_worker_update_handler (wrk, e->data);
2096 break;
Florin Coras86f04502018-09-12 16:08:01 -07002097 default:
2098 clib_warning ("unhandled: %u", e->event_type);
2099 break;
2100 }
2101}
2102
2103static int
2104vcl_select_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
2105 unsigned long n_bits, unsigned long *read_map,
2106 unsigned long *write_map, unsigned long *except_map,
2107 double time_to_wait, u32 * bits_set)
2108{
Florin Coras99368312018-08-02 10:45:44 -07002109 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07002110 session_event_t *e;
Florin Coras86f04502018-09-12 16:08:01 -07002111 u32 i;
Florin Coras54693d22018-07-17 10:46:29 -07002112
2113 svm_msg_q_lock (mq);
2114 if (svm_msg_q_is_empty (mq))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002115 {
Florin Coras54693d22018-07-17 10:46:29 -07002116 if (*bits_set)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002117 {
Florin Coras54693d22018-07-17 10:46:29 -07002118 svm_msg_q_unlock (mq);
2119 return 0;
2120 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002121
Florin Coras54693d22018-07-17 10:46:29 -07002122 if (!time_to_wait)
2123 {
2124 svm_msg_q_unlock (mq);
2125 return 0;
2126 }
2127 else if (time_to_wait < 0)
2128 {
2129 svm_msg_q_wait (mq);
2130 }
2131 else
2132 {
2133 if (svm_msg_q_timedwait (mq, time_to_wait))
2134 {
2135 svm_msg_q_unlock (mq);
2136 return 0;
2137 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002138 }
2139 }
Florin Corase003a1b2019-06-05 10:47:16 -07002140 vcl_mq_dequeue_batch (wrk, mq, ~0);
Florin Coras54693d22018-07-17 10:46:29 -07002141 svm_msg_q_unlock (mq);
2142
Florin Coras134a9962018-08-28 11:32:04 -07002143 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07002144 {
Florin Coras134a9962018-08-28 11:32:04 -07002145 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07002146 e = svm_msg_q_msg_data (mq, msg);
Florin Coras86f04502018-09-12 16:08:01 -07002147 vcl_select_handle_mq_event (wrk, e, n_bits, read_map, write_map,
2148 except_map, bits_set);
Florin Coras99368312018-08-02 10:45:44 -07002149 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002150 }
Florin Coras134a9962018-08-28 11:32:04 -07002151 vec_reset_length (wrk->mq_msg_vector);
Florin Coras30e79c22019-01-02 19:31:22 -08002152 vcl_handle_pending_wrk_updates (wrk);
Florin Coras54693d22018-07-17 10:46:29 -07002153 return *bits_set;
Dave Wallace543852a2017-08-03 02:11:34 -04002154}
2155
Florin Coras99368312018-08-02 10:45:44 -07002156static int
Florin Coras294afe22019-01-07 17:49:17 -08002157vppcom_select_condvar (vcl_worker_t * wrk, int n_bits,
2158 vcl_si_set * read_map, vcl_si_set * write_map,
2159 vcl_si_set * except_map, double time_to_wait,
Florin Coras134a9962018-08-28 11:32:04 -07002160 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002161{
Florin Coras14ed6df2019-03-06 21:13:42 -08002162 double wait = 0, start = 0;
2163
2164 if (!*bits_set)
2165 {
2166 wait = time_to_wait;
2167 start = clib_time_now (&wrk->clib_time);
2168 }
2169
2170 do
2171 {
2172 vcl_select_handle_mq (wrk, wrk->app_event_queue, n_bits, read_map,
2173 write_map, except_map, wait, bits_set);
2174 if (*bits_set)
2175 return *bits_set;
2176 if (wait == -1)
2177 continue;
2178
2179 wait = wait - (clib_time_now (&wrk->clib_time) - start);
2180 }
2181 while (wait > 0);
2182
2183 return 0;
Florin Coras99368312018-08-02 10:45:44 -07002184}
2185
2186static int
Florin Coras294afe22019-01-07 17:49:17 -08002187vppcom_select_eventfd (vcl_worker_t * wrk, int n_bits,
2188 vcl_si_set * read_map, vcl_si_set * write_map,
2189 vcl_si_set * except_map, double time_to_wait,
Florin Coras134a9962018-08-28 11:32:04 -07002190 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002191{
2192 vcl_mq_evt_conn_t *mqc;
2193 int __clib_unused n_read;
2194 int n_mq_evts, i;
2195 u64 buf;
2196
Florin Coras134a9962018-08-28 11:32:04 -07002197 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
2198 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2199 vec_len (wrk->mq_events), time_to_wait);
Florin Coras99368312018-08-02 10:45:44 -07002200 for (i = 0; i < n_mq_evts; i++)
2201 {
Florin Coras134a9962018-08-28 11:32:04 -07002202 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002203 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002204 vcl_select_handle_mq (wrk, mqc->mq, n_bits, read_map, write_map,
Florin Coras99368312018-08-02 10:45:44 -07002205 except_map, 0, bits_set);
2206 }
2207
2208 return (n_mq_evts > 0 ? (int) *bits_set : 0);
2209}
2210
Dave Wallace543852a2017-08-03 02:11:34 -04002211int
Florin Coras294afe22019-01-07 17:49:17 -08002212vppcom_select (int n_bits, vcl_si_set * read_map, vcl_si_set * write_map,
2213 vcl_si_set * except_map, double time_to_wait)
Dave Wallace543852a2017-08-03 02:11:34 -04002214{
Florin Coras54693d22018-07-17 10:46:29 -07002215 u32 sid, minbits = clib_max (n_bits, BITS (uword)), bits_set = 0;
Florin Coras134a9962018-08-28 11:32:04 -07002216 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002217 vcl_session_t *session = 0;
Florin Coras86f04502018-09-12 16:08:01 -07002218 int rv, i;
Dave Wallace543852a2017-08-03 02:11:34 -04002219
Dave Wallace7876d392017-10-19 03:53:57 -04002220 if (n_bits && read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002221 {
Florin Coras134a9962018-08-28 11:32:04 -07002222 clib_bitmap_validate (wrk->rd_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002223 clib_memcpy_fast (wrk->rd_bitmap, read_map,
Florin Coras294afe22019-01-07 17:49:17 -08002224 vec_len (wrk->rd_bitmap) * sizeof (vcl_si_set));
2225 memset (read_map, 0, vec_len (wrk->rd_bitmap) * sizeof (vcl_si_set));
Dave Wallace543852a2017-08-03 02:11:34 -04002226 }
Dave Wallace7876d392017-10-19 03:53:57 -04002227 if (n_bits && write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002228 {
Florin Coras134a9962018-08-28 11:32:04 -07002229 clib_bitmap_validate (wrk->wr_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002230 clib_memcpy_fast (wrk->wr_bitmap, write_map,
Florin Coras294afe22019-01-07 17:49:17 -08002231 vec_len (wrk->wr_bitmap) * sizeof (vcl_si_set));
2232 memset (write_map, 0, vec_len (wrk->wr_bitmap) * sizeof (vcl_si_set));
Dave Wallace543852a2017-08-03 02:11:34 -04002233 }
Dave Wallace7876d392017-10-19 03:53:57 -04002234 if (n_bits && except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002235 {
Florin Coras134a9962018-08-28 11:32:04 -07002236 clib_bitmap_validate (wrk->ex_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002237 clib_memcpy_fast (wrk->ex_bitmap, except_map,
Florin Coras294afe22019-01-07 17:49:17 -08002238 vec_len (wrk->ex_bitmap) * sizeof (vcl_si_set));
2239 memset (except_map, 0, vec_len (wrk->ex_bitmap) * sizeof (vcl_si_set));
Dave Wallace543852a2017-08-03 02:11:34 -04002240 }
2241
Florin Coras54693d22018-07-17 10:46:29 -07002242 if (!n_bits)
2243 return 0;
2244
2245 if (!write_map)
2246 goto check_rd;
2247
2248 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002249 clib_bitmap_foreach (sid, wrk->wr_bitmap, ({
2250 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002251 {
Florin Coras47c40e22018-11-26 17:01:36 -08002252 if (except_map && sid < minbits)
2253 clib_bitmap_set_no_check (except_map, sid, 1);
2254 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002255 }
2256
Sirshak Das28aa5392019-02-05 01:33:33 -06002257 rv = svm_fifo_is_full_prod (session->tx_fifo);
Florin Coras54693d22018-07-17 10:46:29 -07002258 if (!rv)
2259 {
David Johnsond9818dd2018-12-14 14:53:41 -05002260 clib_bitmap_set_no_check ((uword*)write_map, sid, 1);
Florin Coras54693d22018-07-17 10:46:29 -07002261 bits_set++;
2262 }
Florin Coras294afe22019-01-07 17:49:17 -08002263 else
Florin Coras2d379d82019-06-28 12:45:12 -07002264 svm_fifo_add_want_deq_ntf (session->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
Florin Coras54693d22018-07-17 10:46:29 -07002265 }));
2266
2267check_rd:
2268 if (!read_map)
2269 goto check_mq;
Florin Coras99368312018-08-02 10:45:44 -07002270
Florin Coras134a9962018-08-28 11:32:04 -07002271 clib_bitmap_foreach (sid, wrk->rd_bitmap, ({
2272 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002273 {
Florin Coras47c40e22018-11-26 17:01:36 -08002274 if (except_map && sid < minbits)
2275 clib_bitmap_set_no_check (except_map, sid, 1);
2276 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002277 }
2278
Florin Coras0ef8ef22019-01-18 08:37:13 -08002279 rv = vcl_session_read_ready (session);
Florin Coras54693d22018-07-17 10:46:29 -07002280 if (rv)
2281 {
David Johnsond9818dd2018-12-14 14:53:41 -05002282 clib_bitmap_set_no_check ((uword*)read_map, sid, 1);
Florin Coras54693d22018-07-17 10:46:29 -07002283 bits_set++;
2284 }
2285 }));
2286 /* *INDENT-ON* */
2287
2288check_mq:
Dave Wallace543852a2017-08-03 02:11:34 -04002289
Florin Coras86f04502018-09-12 16:08:01 -07002290 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2291 {
2292 vcl_select_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i], n_bits,
2293 read_map, write_map, except_map, &bits_set);
2294 }
2295 vec_reset_length (wrk->unhandled_evts_vector);
2296
Florin Coras99368312018-08-02 10:45:44 -07002297 if (vcm->cfg.use_mq_eventfd)
Florin Coras134a9962018-08-28 11:32:04 -07002298 vppcom_select_eventfd (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002299 time_to_wait, &bits_set);
2300 else
Florin Coras134a9962018-08-28 11:32:04 -07002301 vppcom_select_condvar (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002302 time_to_wait, &bits_set);
Florin Coras54693d22018-07-17 10:46:29 -07002303
Dave Wallace543852a2017-08-03 02:11:34 -04002304 return (bits_set);
2305}
2306
Dave Wallacef7f809c2017-10-03 01:48:42 -04002307static inline void
Florin Coras7e5e62b2019-07-30 14:08:23 -07002308vep_verify_epoll_chain (vcl_worker_t * wrk, u32 vep_handle)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002309{
Florin Coras7e12d942018-06-27 14:32:43 -07002310 vcl_session_t *session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002311 vppcom_epoll_t *vep;
Florin Coras7e5e62b2019-07-30 14:08:23 -07002312 u32 sh = vep_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002313
Florin Corasc0737e92019-03-04 14:19:39 -08002314 if (VPPCOM_DEBUG <= 2)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002315 return;
2316
Florin Coras7e5e62b2019-07-30 14:08:23 -07002317 session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002318 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002319 {
Florin Coras7e5e62b2019-07-30 14:08:23 -07002320 VDBG (0, "ERROR: Invalid vep_sh (%u)!", vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002321 goto done;
2322 }
2323 if (PREDICT_FALSE (!session->is_vep))
2324 {
Florin Coras7e5e62b2019-07-30 14:08:23 -07002325 VDBG (0, "ERROR: vep_sh (%u) is not a vep!", vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002326 goto done;
2327 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002328 vep = &session->vep;
Florin Coras7e5e62b2019-07-30 14:08:23 -07002329 VDBG (0, "vep_sh (%u): Dumping epoll chain\n"
Florin Coras5e062572019-03-14 19:07:51 -07002330 "{\n"
2331 " is_vep = %u\n"
2332 " is_vep_session = %u\n"
Florin Coras7e5e62b2019-07-30 14:08:23 -07002333 " next_sh = 0x%x (%u)\n"
2334 "}\n", vep_handle, session->is_vep, session->is_vep_session,
Florin Coras5e062572019-03-14 19:07:51 -07002335 vep->next_sh, vep->next_sh);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002336
Florin Coras7e5e62b2019-07-30 14:08:23 -07002337 for (sh = vep->next_sh; sh != ~0; sh = vep->next_sh)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002338 {
Florin Coras7e5e62b2019-07-30 14:08:23 -07002339 session = vcl_session_get_w_handle (wrk, sh);
Florin Coras070453d2018-08-24 17:04:27 -07002340 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002341 {
Florin Coras7e5e62b2019-07-30 14:08:23 -07002342 VDBG (0, "ERROR: Invalid sh (%u)!", sh);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002343 goto done;
2344 }
2345 if (PREDICT_FALSE (session->is_vep))
Florin Coras5e062572019-03-14 19:07:51 -07002346 {
Florin Coras7e5e62b2019-07-30 14:08:23 -07002347 VDBG (0, "ERROR: sh (%u) is a vep!", vep_handle);
Florin Coras5e062572019-03-14 19:07:51 -07002348 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002349 else if (PREDICT_FALSE (!session->is_vep_session))
2350 {
Florin Coras7e5e62b2019-07-30 14:08:23 -07002351 VDBG (0, "ERROR: sh (%u) is not a vep session handle!", sh);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002352 goto done;
2353 }
2354 vep = &session->vep;
Florin Coras7e5e62b2019-07-30 14:08:23 -07002355 if (PREDICT_FALSE (vep->vep_sh != vep_handle))
2356 VDBG (0, "ERROR: session (%u) vep_sh (%u) != vep_sh (%u)!",
2357 sh, session->vep.vep_sh, vep_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002358 if (session->is_vep_session)
2359 {
Florin Coras7e5e62b2019-07-30 14:08:23 -07002360 VDBG (0, "vep_sh[%u]: sh 0x%x (%u)\n"
Florin Coras5e062572019-03-14 19:07:51 -07002361 "{\n"
Florin Coras7e5e62b2019-07-30 14:08:23 -07002362 " next_sh = 0x%x (%u)\n"
2363 " prev_sh = 0x%x (%u)\n"
2364 " vep_sh = 0x%x (%u)\n"
Florin Coras5e062572019-03-14 19:07:51 -07002365 " ev.events = 0x%x\n"
2366 " ev.data.u64 = 0x%llx\n"
2367 " et_mask = 0x%x\n"
2368 "}\n",
Florin Coras7e5e62b2019-07-30 14:08:23 -07002369 vep_handle, sh, sh, vep->next_sh, vep->next_sh, vep->prev_sh,
Florin Coras5e062572019-03-14 19:07:51 -07002370 vep->prev_sh, vep->vep_sh, vep->vep_sh, vep->ev.events,
2371 vep->ev.data.u64, vep->et_mask);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002372 }
2373 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002374
2375done:
Florin Coras7e5e62b2019-07-30 14:08:23 -07002376 VDBG (0, "vep_sh (%u): Dump complete!\n", vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002377}
2378
2379int
2380vppcom_epoll_create (void)
2381{
Florin Coras134a9962018-08-28 11:32:04 -07002382 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002383 vcl_session_t *vep_session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002384
Florin Coras134a9962018-08-28 11:32:04 -07002385 vep_session = vcl_session_alloc (wrk);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002386
2387 vep_session->is_vep = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002388 vep_session->vep.vep_sh = ~0;
2389 vep_session->vep.next_sh = ~0;
2390 vep_session->vep.prev_sh = ~0;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002391 vep_session->vpp_handle = ~0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002392
Florin Corasa7a1a222018-12-30 17:11:31 -08002393 vcl_evt (VCL_EVT_EPOLL_CREATE, vep_session, vep_session->session_index);
2394 VDBG (0, "Created vep_idx %u", vep_session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08002395
Florin Corasab2f6db2018-08-31 14:31:41 -07002396 return vcl_session_handle (vep_session);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002397}
2398
2399int
Florin Coras134a9962018-08-28 11:32:04 -07002400vppcom_epoll_ctl (uint32_t vep_handle, int op, uint32_t session_handle,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002401 struct epoll_event *event)
2402{
Florin Coras134a9962018-08-28 11:32:04 -07002403 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002404 vcl_session_t *vep_session;
2405 vcl_session_t *session;
Florin Coras070453d2018-08-24 17:04:27 -07002406 int rv = VPPCOM_OK;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002407
Florin Coras134a9962018-08-28 11:32:04 -07002408 if (vep_handle == session_handle)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002409 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002410 VDBG (0, "vep_sh == session handle (%u)!", vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002411 return VPPCOM_EINVAL;
2412 }
2413
Florin Coras134a9962018-08-28 11:32:04 -07002414 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002415 if (PREDICT_FALSE (!vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002416 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002417 VDBG (0, "Invalid vep_sh (%u)!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002418 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002419 }
2420 if (PREDICT_FALSE (!vep_session->is_vep))
2421 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002422 VDBG (0, "vep_sh (%u) is not a vep!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002423 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002424 }
2425
Florin Coras134a9962018-08-28 11:32:04 -07002426 ASSERT (vep_session->vep.vep_sh == ~0);
2427 ASSERT (vep_session->vep.prev_sh == ~0);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002428
Florin Coras134a9962018-08-28 11:32:04 -07002429 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002430 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002431 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002432 VDBG (0, "Invalid session_handle (%u)!", session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002433 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002434 }
2435 if (PREDICT_FALSE (session->is_vep))
2436 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002437 VDBG (0, "session_handle (%u) is a vep!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002438 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002439 }
2440
2441 switch (op)
2442 {
2443 case EPOLL_CTL_ADD:
2444 if (PREDICT_FALSE (!event))
2445 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002446 VDBG (0, "EPOLL_CTL_ADD: NULL pointer to epoll_event structure!");
Florin Coras070453d2018-08-24 17:04:27 -07002447 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002448 }
Florin Coras134a9962018-08-28 11:32:04 -07002449 if (vep_session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002450 {
Florin Coras7e12d942018-06-27 14:32:43 -07002451 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002452 next_session = vcl_session_get_w_handle (wrk,
2453 vep_session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002454 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002455 {
Florin Coras5e062572019-03-14 19:07:51 -07002456 VDBG (0, "EPOLL_CTL_ADD: Invalid vep.next_sh (%u) on "
Florin Corasa7a1a222018-12-30 17:11:31 -08002457 "vep_idx (%u)!", vep_session->vep.next_sh, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002458 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002459 }
Florin Coras134a9962018-08-28 11:32:04 -07002460 ASSERT (next_session->vep.prev_sh == vep_handle);
2461 next_session->vep.prev_sh = session_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002462 }
Florin Coras134a9962018-08-28 11:32:04 -07002463 session->vep.next_sh = vep_session->vep.next_sh;
2464 session->vep.prev_sh = vep_handle;
2465 session->vep.vep_sh = vep_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002466 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2467 session->vep.ev = *event;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002468 session->is_vep = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002469 session->is_vep_session = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002470 vep_session->vep.next_sh = session_handle;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08002471
Florin Coras1bcad5c2019-01-09 20:04:38 -08002472 if (session->tx_fifo)
Florin Coras2d379d82019-06-28 12:45:12 -07002473 svm_fifo_add_want_deq_ntf (session->tx_fifo,
2474 SVM_FIFO_WANT_DEQ_NOTIF_IF_FULL);
Florin Coras1bcad5c2019-01-09 20:04:38 -08002475
Florin Corasa7a1a222018-12-30 17:11:31 -08002476 VDBG (1, "EPOLL_CTL_ADD: vep_sh %u, sh %u, events 0x%x, data 0x%llx!",
2477 vep_handle, session_handle, event->events, event->data.u64);
Florin Coras0d427d82018-06-27 03:24:07 -07002478 vcl_evt (VCL_EVT_EPOLL_CTLADD, session, event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002479 break;
2480
2481 case EPOLL_CTL_MOD:
2482 if (PREDICT_FALSE (!event))
2483 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002484 VDBG (0, "EPOLL_CTL_MOD: NULL pointer to epoll_event structure!");
Dave Wallacef7f809c2017-10-03 01:48:42 -04002485 rv = VPPCOM_EINVAL;
2486 goto done;
2487 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002488 else if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002489 {
Florin Coras5e062572019-03-14 19:07:51 -07002490 VDBG (0, "sh %u EPOLL_CTL_MOD: not a vep session!", session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002491 rv = VPPCOM_EINVAL;
2492 goto done;
2493 }
Florin Coras134a9962018-08-28 11:32:04 -07002494 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002495 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002496 VDBG (0, "EPOLL_CTL_MOD: sh %u vep_sh (%u) != vep_sh (%u)!",
2497 session_handle, session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002498 rv = VPPCOM_EINVAL;
2499 goto done;
2500 }
2501 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2502 session->vep.ev = *event;
Florin Corasa7a1a222018-12-30 17:11:31 -08002503 VDBG (1, "EPOLL_CTL_MOD: vep_sh %u, sh %u, events 0x%x, data 0x%llx!",
2504 vep_handle, session_handle, event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002505 break;
2506
2507 case EPOLL_CTL_DEL:
Dave Wallace4878cbe2017-11-21 03:45:09 -05002508 if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002509 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002510 VDBG (0, "EPOLL_CTL_DEL: %u not a vep session!", session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002511 rv = VPPCOM_EINVAL;
2512 goto done;
2513 }
Florin Coras134a9962018-08-28 11:32:04 -07002514 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002515 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002516 VDBG (0, "EPOLL_CTL_DEL: sh %u vep_sh (%u) != vep_sh (%u)!",
2517 session_handle, session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002518 rv = VPPCOM_EINVAL;
2519 goto done;
2520 }
2521
Florin Coras134a9962018-08-28 11:32:04 -07002522 if (session->vep.prev_sh == vep_handle)
2523 vep_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002524 else
2525 {
Florin Coras7e12d942018-06-27 14:32:43 -07002526 vcl_session_t *prev_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002527 prev_session = vcl_session_get_w_handle (wrk, session->vep.prev_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002528 if (PREDICT_FALSE (!prev_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002529 {
Florin Coras5e062572019-03-14 19:07:51 -07002530 VDBG (0, "EPOLL_CTL_DEL: Invalid prev_sh (%u) on sh (%u)!",
Florin Corasa7a1a222018-12-30 17:11:31 -08002531 session->vep.prev_sh, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002532 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002533 }
Florin Coras134a9962018-08-28 11:32:04 -07002534 ASSERT (prev_session->vep.next_sh == session_handle);
2535 prev_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002536 }
Florin Coras134a9962018-08-28 11:32:04 -07002537 if (session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002538 {
Florin Coras7e12d942018-06-27 14:32:43 -07002539 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002540 next_session = vcl_session_get_w_handle (wrk, session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002541 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002542 {
Florin Coras5e062572019-03-14 19:07:51 -07002543 VDBG (0, "EPOLL_CTL_DEL: Invalid next_sh (%u) on sh (%u)!",
Florin Corasa7a1a222018-12-30 17:11:31 -08002544 session->vep.next_sh, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002545 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002546 }
Florin Coras134a9962018-08-28 11:32:04 -07002547 ASSERT (next_session->vep.prev_sh == session_handle);
2548 next_session->vep.prev_sh = session->vep.prev_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002549 }
2550
2551 memset (&session->vep, 0, sizeof (session->vep));
Florin Coras134a9962018-08-28 11:32:04 -07002552 session->vep.next_sh = ~0;
2553 session->vep.prev_sh = ~0;
2554 session->vep.vep_sh = ~0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002555 session->is_vep_session = 0;
Florin Coras1bcad5c2019-01-09 20:04:38 -08002556
2557 if (session->tx_fifo)
Florin Coras2d379d82019-06-28 12:45:12 -07002558 svm_fifo_del_want_deq_ntf (session->tx_fifo, SVM_FIFO_NO_DEQ_NOTIF);
Florin Coras1bcad5c2019-01-09 20:04:38 -08002559
Florin Coras5e062572019-03-14 19:07:51 -07002560 VDBG (1, "EPOLL_CTL_DEL: vep_idx %u, sh %u!", vep_handle,
Florin Corasa7a1a222018-12-30 17:11:31 -08002561 session_handle);
Florin Coras134a9962018-08-28 11:32:04 -07002562 vcl_evt (VCL_EVT_EPOLL_CTLDEL, session, vep_sh);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002563 break;
2564
2565 default:
Florin Corasa7a1a222018-12-30 17:11:31 -08002566 VDBG (0, "Invalid operation (%d)!", op);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002567 rv = VPPCOM_EINVAL;
2568 }
2569
Florin Coras134a9962018-08-28 11:32:04 -07002570 vep_verify_epoll_chain (wrk, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002571
2572done:
Dave Wallacef7f809c2017-10-03 01:48:42 -04002573 return rv;
2574}
2575
Florin Coras86f04502018-09-12 16:08:01 -07002576static inline void
2577vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
2578 struct epoll_event *events, u32 * num_ev)
Florin Coras54693d22018-07-17 10:46:29 -07002579{
2580 session_disconnected_msg_t *disconnected_msg;
2581 session_connected_msg_t *connected_msg;
Florin Coras99368312018-08-02 10:45:44 -07002582 u32 sid = ~0, session_events;
Florin Coras3c7d4f92018-12-14 11:28:43 -08002583 u64 session_evt_data = ~0;
Florin Coras54693d22018-07-17 10:46:29 -07002584 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07002585 u8 add_event = 0;
2586
2587 switch (e->event_type)
2588 {
Florin Coras653e43f2019-03-04 10:56:23 -08002589 case SESSION_IO_EVT_RX:
Florin Corasc0737e92019-03-04 14:19:39 -08002590 sid = e->session_index;
Florin Corasfa915f82018-12-26 16:29:06 -08002591 if (!(session = vcl_session_get (wrk, sid)))
2592 break;
Florin Corasc0737e92019-03-04 14:19:39 -08002593 vcl_fifo_rx_evt_valid_or_break (session);
Florin Coras86f04502018-09-12 16:08:01 -07002594 session_events = session->vep.ev.events;
Florin Corasaa27eb92018-10-13 12:20:01 -07002595 if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
Florin Coras86f04502018-09-12 16:08:01 -07002596 break;
2597 add_event = 1;
2598 events[*num_ev].events |= EPOLLIN;
2599 session_evt_data = session->vep.ev.data.u64;
Florin Corasaa27eb92018-10-13 12:20:01 -07002600 session->has_rx_evt = 1;
Florin Coras86f04502018-09-12 16:08:01 -07002601 break;
Florin Coras653e43f2019-03-04 10:56:23 -08002602 case SESSION_IO_EVT_TX:
Florin Corasc0737e92019-03-04 14:19:39 -08002603 sid = e->session_index;
Florin Corasfa915f82018-12-26 16:29:06 -08002604 if (!(session = vcl_session_get (wrk, sid)))
2605 break;
Florin Coras86f04502018-09-12 16:08:01 -07002606 session_events = session->vep.ev.events;
2607 if (!(EPOLLOUT & session_events))
2608 break;
2609 add_event = 1;
2610 events[*num_ev].events |= EPOLLOUT;
2611 session_evt_data = session->vep.ev.data.u64;
Florin Coras2d379d82019-06-28 12:45:12 -07002612 svm_fifo_reset_has_deq_ntf (session->tx_fifo);
Florin Coras86f04502018-09-12 16:08:01 -07002613 break;
Florin Coras86f04502018-09-12 16:08:01 -07002614 case SESSION_CTRL_EVT_ACCEPTED:
Florin Coras3c7d4f92018-12-14 11:28:43 -08002615 session = vcl_session_accepted (wrk,
2616 (session_accepted_msg_t *) e->data);
Florin Coras86f04502018-09-12 16:08:01 -07002617 if (!session)
Florin Coras3c7d4f92018-12-14 11:28:43 -08002618 break;
Florin Coras86f04502018-09-12 16:08:01 -07002619
Florin Coras86f04502018-09-12 16:08:01 -07002620 session_events = session->vep.ev.events;
2621 if (!(EPOLLIN & session_events))
2622 break;
2623
2624 add_event = 1;
2625 events[*num_ev].events |= EPOLLIN;
2626 session_evt_data = session->vep.ev.data.u64;
2627 break;
2628 case SESSION_CTRL_EVT_CONNECTED:
2629 connected_msg = (session_connected_msg_t *) e->data;
Florin Corasf1653e62019-11-06 15:41:37 -08002630 sid = vcl_session_connected_handler (wrk, connected_msg);
Florin Coras86f04502018-09-12 16:08:01 -07002631 /* Generate EPOLLOUT because there's no connected event */
Florin Corasfa915f82018-12-26 16:29:06 -08002632 if (!(session = vcl_session_get (wrk, sid)))
2633 break;
Florin Coras86f04502018-09-12 16:08:01 -07002634 session_events = session->vep.ev.events;
Florin Coras72f77822019-01-22 19:05:52 -08002635 if (!(EPOLLOUT & session_events))
2636 break;
2637 add_event = 1;
2638 events[*num_ev].events |= EPOLLOUT;
2639 session_evt_data = session->vep.ev.data.u64;
Florin Corasdbc9c592019-09-25 16:37:43 -07002640 if (session->session_state & STATE_FAILED)
2641 events[*num_ev].events |= EPOLLHUP;
Florin Coras86f04502018-09-12 16:08:01 -07002642 break;
2643 case SESSION_CTRL_EVT_DISCONNECTED:
2644 disconnected_msg = (session_disconnected_msg_t *) e->data;
Florin Coras3c7d4f92018-12-14 11:28:43 -08002645 session = vcl_session_disconnected_handler (wrk, disconnected_msg);
2646 if (!session)
Florin Coras86f04502018-09-12 16:08:01 -07002647 break;
Florin Coras72f77822019-01-22 19:05:52 -08002648 session_events = session->vep.ev.events;
2649 if (!((EPOLLHUP | EPOLLRDHUP) & session_events))
2650 break;
Florin Coras86f04502018-09-12 16:08:01 -07002651 add_event = 1;
2652 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2653 session_evt_data = session->vep.ev.data.u64;
Florin Coras86f04502018-09-12 16:08:01 -07002654 break;
2655 case SESSION_CTRL_EVT_RESET:
2656 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
2657 if (!(session = vcl_session_get (wrk, sid)))
2658 break;
Florin Coras72f77822019-01-22 19:05:52 -08002659 session_events = session->vep.ev.events;
2660 if (!((EPOLLHUP | EPOLLRDHUP) & session_events))
2661 break;
Florin Coras86f04502018-09-12 16:08:01 -07002662 add_event = 1;
2663 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2664 session_evt_data = session->vep.ev.data.u64;
Florin Coras86f04502018-09-12 16:08:01 -07002665 break;
Florin Corasdfae9f92019-02-20 19:48:31 -08002666 case SESSION_CTRL_EVT_UNLISTEN_REPLY:
2667 vcl_session_unlisten_reply_handler (wrk, e->data);
2668 break;
Florin Coras30e79c22019-01-02 19:31:22 -08002669 case SESSION_CTRL_EVT_REQ_WORKER_UPDATE:
2670 vcl_session_req_worker_update_handler (wrk, e->data);
2671 break;
2672 case SESSION_CTRL_EVT_WORKER_UPDATE_REPLY:
2673 vcl_session_worker_update_reply_handler (wrk, e->data);
2674 break;
Florin Coras86f04502018-09-12 16:08:01 -07002675 default:
2676 VDBG (0, "unhandled: %u", e->event_type);
2677 break;
2678 }
2679
2680 if (add_event)
2681 {
2682 events[*num_ev].data.u64 = session_evt_data;
2683 if (EPOLLONESHOT & session_events)
2684 {
2685 session = vcl_session_get (wrk, sid);
2686 session->vep.ev.events = 0;
2687 }
2688 *num_ev += 1;
2689 }
2690}
2691
2692static int
2693vcl_epoll_wait_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
2694 struct epoll_event *events, u32 maxevents,
2695 double wait_for_time, u32 * num_ev)
2696{
Florin Coras99368312018-08-02 10:45:44 -07002697 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07002698 session_event_t *e;
Florin Coras54693d22018-07-17 10:46:29 -07002699 int i;
2700
Florin Coras539663c2018-09-28 14:59:37 -07002701 if (vec_len (wrk->mq_msg_vector) && svm_msg_q_is_empty (mq))
2702 goto handle_dequeued;
2703
Florin Coras54693d22018-07-17 10:46:29 -07002704 svm_msg_q_lock (mq);
2705 if (svm_msg_q_is_empty (mq))
2706 {
2707 if (!wait_for_time)
2708 {
2709 svm_msg_q_unlock (mq);
2710 return 0;
2711 }
2712 else if (wait_for_time < 0)
2713 {
2714 svm_msg_q_wait (mq);
2715 }
2716 else
2717 {
Florin Coras60f1fc12018-08-16 14:57:31 -07002718 if (svm_msg_q_timedwait (mq, wait_for_time / 1e3))
Florin Coras54693d22018-07-17 10:46:29 -07002719 {
2720 svm_msg_q_unlock (mq);
2721 return 0;
2722 }
2723 }
2724 }
Florin Corase003a1b2019-06-05 10:47:16 -07002725 ASSERT (maxevents > *num_ev);
2726 vcl_mq_dequeue_batch (wrk, mq, maxevents - *num_ev);
Florin Coras54693d22018-07-17 10:46:29 -07002727 svm_msg_q_unlock (mq);
2728
Florin Coras539663c2018-09-28 14:59:37 -07002729handle_dequeued:
Florin Coras134a9962018-08-28 11:32:04 -07002730 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07002731 {
Florin Coras134a9962018-08-28 11:32:04 -07002732 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07002733 e = svm_msg_q_msg_data (mq, msg);
Florin Corase003a1b2019-06-05 10:47:16 -07002734 vcl_epoll_wait_handle_mq_event (wrk, e, events, num_ev);
Florin Coras99368312018-08-02 10:45:44 -07002735 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002736 }
Florin Corasaa27eb92018-10-13 12:20:01 -07002737 vec_reset_length (wrk->mq_msg_vector);
Florin Coras30e79c22019-01-02 19:31:22 -08002738 vcl_handle_pending_wrk_updates (wrk);
Florin Coras54693d22018-07-17 10:46:29 -07002739 return *num_ev;
2740}
2741
Florin Coras99368312018-08-02 10:45:44 -07002742static int
Florin Coras134a9962018-08-28 11:32:04 -07002743vppcom_epoll_wait_condvar (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002744 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002745{
Florin Corase003a1b2019-06-05 10:47:16 -07002746 double wait = 0, start = 0, now;
Florin Coras14ed6df2019-03-06 21:13:42 -08002747
2748 if (!n_evts)
2749 {
2750 wait = wait_for_time;
2751 start = clib_time_now (&wrk->clib_time);
2752 }
2753
2754 do
2755 {
2756 vcl_epoll_wait_handle_mq (wrk, wrk->app_event_queue, events, maxevents,
2757 wait, &n_evts);
2758 if (n_evts)
2759 return n_evts;
2760 if (wait == -1)
2761 continue;
2762
Florin Corase003a1b2019-06-05 10:47:16 -07002763 now = clib_time_now (&wrk->clib_time);
2764 wait -= now - start;
2765 start = now;
Florin Coras14ed6df2019-03-06 21:13:42 -08002766 }
2767 while (wait > 0);
2768
2769 return 0;
Florin Coras99368312018-08-02 10:45:44 -07002770}
2771
2772static int
Florin Coras134a9962018-08-28 11:32:04 -07002773vppcom_epoll_wait_eventfd (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002774 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002775{
2776 vcl_mq_evt_conn_t *mqc;
2777 int __clib_unused n_read;
2778 int n_mq_evts, i;
Florin Coras99368312018-08-02 10:45:44 -07002779 u64 buf;
2780
Florin Coras134a9962018-08-28 11:32:04 -07002781 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
Florin Corasa4878ed2018-10-12 13:09:36 -07002782again:
Florin Coras134a9962018-08-28 11:32:04 -07002783 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2784 vec_len (wrk->mq_events), wait_for_time);
Florin Coras99368312018-08-02 10:45:44 -07002785 for (i = 0; i < n_mq_evts; i++)
2786 {
Florin Coras134a9962018-08-28 11:32:04 -07002787 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002788 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002789 vcl_epoll_wait_handle_mq (wrk, mqc->mq, events, maxevents, 0, &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002790 }
Florin Corasa4878ed2018-10-12 13:09:36 -07002791 if (!n_evts && n_mq_evts > 0)
2792 goto again;
Florin Coras99368312018-08-02 10:45:44 -07002793
2794 return (int) n_evts;
2795}
2796
Dave Wallacef7f809c2017-10-03 01:48:42 -04002797int
Florin Coras134a9962018-08-28 11:32:04 -07002798vppcom_epoll_wait (uint32_t vep_handle, struct epoll_event *events,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002799 int maxevents, double wait_for_time)
2800{
Florin Coras134a9962018-08-28 11:32:04 -07002801 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002802 vcl_session_t *vep_session;
Florin Coras86f04502018-09-12 16:08:01 -07002803 u32 n_evts = 0;
2804 int i;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002805
2806 if (PREDICT_FALSE (maxevents <= 0))
2807 {
Florin Coras5e062572019-03-14 19:07:51 -07002808 VDBG (0, "ERROR: Invalid maxevents (%d)!", maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002809 return VPPCOM_EINVAL;
2810 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002811
Florin Coras134a9962018-08-28 11:32:04 -07002812 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras14598772018-09-04 19:47:52 -07002813 if (!vep_session)
2814 return VPPCOM_EBADFD;
2815
Florin Coras54693d22018-07-17 10:46:29 -07002816 if (PREDICT_FALSE (!vep_session->is_vep))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002817 {
Florin Coras5e062572019-03-14 19:07:51 -07002818 VDBG (0, "ERROR: vep_idx (%u) is not a vep!", vep_handle);
Florin Coras54693d22018-07-17 10:46:29 -07002819 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002820 }
Florin Coras54693d22018-07-17 10:46:29 -07002821
2822 memset (events, 0, sizeof (*events) * maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002823
Florin Coras86f04502018-09-12 16:08:01 -07002824 if (vec_len (wrk->unhandled_evts_vector))
2825 {
2826 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2827 {
2828 vcl_epoll_wait_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i],
2829 events, &n_evts);
2830 if (n_evts == maxevents)
2831 {
Florin Corase003a1b2019-06-05 10:47:16 -07002832 vec_delete (wrk->unhandled_evts_vector, i + 1, 0);
2833 return n_evts;
Florin Coras86f04502018-09-12 16:08:01 -07002834 }
2835 }
Florin Corase003a1b2019-06-05 10:47:16 -07002836 vec_reset_length (wrk->unhandled_evts_vector);
Florin Coras86f04502018-09-12 16:08:01 -07002837 }
2838
2839 if (vcm->cfg.use_mq_eventfd)
2840 return vppcom_epoll_wait_eventfd (wrk, events, maxevents, n_evts,
2841 wait_for_time);
2842
2843 return vppcom_epoll_wait_condvar (wrk, events, maxevents, n_evts,
2844 wait_for_time);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002845}
2846
Dave Wallace35830af2017-10-09 01:43:42 -04002847int
Florin Coras134a9962018-08-28 11:32:04 -07002848vppcom_session_attr (uint32_t session_handle, uint32_t op,
Dave Wallace35830af2017-10-09 01:43:42 -04002849 void *buffer, uint32_t * buflen)
2850{
Florin Coras134a9962018-08-28 11:32:04 -07002851 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002852 vcl_session_t *session;
Dave Wallace35830af2017-10-09 01:43:42 -04002853 int rv = VPPCOM_OK;
Florin Coras7baeb712019-01-04 17:05:43 -08002854 u32 *flags = buffer, tmp_flags = 0;
Steven2199aab2017-10-15 20:18:47 -07002855 vppcom_endpt_t *ep = buffer;
Dave Wallace35830af2017-10-09 01:43:42 -04002856
Florin Coras134a9962018-08-28 11:32:04 -07002857 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002858 if (!session)
2859 return VPPCOM_EBADFD;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002860
Dave Wallace35830af2017-10-09 01:43:42 -04002861 switch (op)
2862 {
2863 case VPPCOM_ATTR_GET_NREAD:
Florin Coras0ef8ef22019-01-18 08:37:13 -08002864 rv = vcl_session_read_ready (session);
Florin Coras5e062572019-03-14 19:07:51 -07002865 VDBG (2, "VPPCOM_ATTR_GET_NREAD: sh %u, nread = %d", session_handle,
2866 rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002867 break;
2868
Dave Wallace227867f2017-11-13 21:21:53 -05002869 case VPPCOM_ATTR_GET_NWRITE:
Florin Coras0ef8ef22019-01-18 08:37:13 -08002870 rv = vcl_session_write_ready (session);
Florin Coras5e062572019-03-14 19:07:51 -07002871 VDBG (2, "VPPCOM_ATTR_GET_NWRITE: sh %u, nwrite = %d", session_handle,
2872 rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002873 break;
2874
2875 case VPPCOM_ATTR_GET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002876 if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002877 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002878 *flags = O_RDWR | (VCL_SESS_ATTR_TEST (session->attr,
2879 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002880 *buflen = sizeof (*flags);
Florin Coras5e062572019-03-14 19:07:51 -07002881 VDBG (2, "VPPCOM_ATTR_GET_FLAGS: sh %u, flags = 0x%08x, "
2882 "is_nonblocking = %u", session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07002883 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002884 }
2885 else
2886 rv = VPPCOM_EINVAL;
2887 break;
2888
2889 case VPPCOM_ATTR_SET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002890 if (PREDICT_TRUE (buffer && buflen && (*buflen == sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002891 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002892 if (*flags & O_NONBLOCK)
2893 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
2894 else
2895 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_NONBLOCK);
2896
Florin Coras5e062572019-03-14 19:07:51 -07002897 VDBG (2, "VPPCOM_ATTR_SET_FLAGS: sh %u, flags = 0x%08x,"
2898 " is_nonblocking = %u", session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07002899 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002900 }
2901 else
2902 rv = VPPCOM_EINVAL;
2903 break;
2904
2905 case VPPCOM_ATTR_GET_PEER_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002906 if (PREDICT_TRUE (buffer && buflen &&
2907 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002908 {
Florin Coras7e12d942018-06-27 14:32:43 -07002909 ep->is_ip4 = session->transport.is_ip4;
2910 ep->port = session->transport.rmt_port;
2911 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05002912 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
2913 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07002914 else
Dave Barach178cf492018-11-13 16:34:13 -05002915 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
2916 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07002917 *buflen = sizeof (*ep);
Florin Coras5e062572019-03-14 19:07:51 -07002918 VDBG (1, "VPPCOM_ATTR_GET_PEER_ADDR: sh %u, is_ip4 = %u, "
2919 "addr = %U, port %u", session_handle, ep->is_ip4,
2920 format_ip46_address, &session->transport.rmt_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002921 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2922 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002923 }
2924 else
2925 rv = VPPCOM_EINVAL;
2926 break;
2927
2928 case VPPCOM_ATTR_GET_LCL_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002929 if (PREDICT_TRUE (buffer && buflen &&
2930 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002931 {
Florin Coras7e12d942018-06-27 14:32:43 -07002932 ep->is_ip4 = session->transport.is_ip4;
2933 ep->port = session->transport.lcl_port;
2934 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05002935 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip4,
2936 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07002937 else
Dave Barach178cf492018-11-13 16:34:13 -05002938 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip6,
2939 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07002940 *buflen = sizeof (*ep);
Florin Coras5e062572019-03-14 19:07:51 -07002941 VDBG (1, "VPPCOM_ATTR_GET_LCL_ADDR: sh %u, is_ip4 = %u, addr = %U"
2942 " port %d", session_handle, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07002943 &session->transport.lcl_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002944 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2945 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002946 }
2947 else
2948 rv = VPPCOM_EINVAL;
2949 break;
Stevenb5a11602017-10-11 09:59:30 -07002950
Florin Corasef7cbf62019-10-17 09:56:27 -07002951 case VPPCOM_ATTR_SET_LCL_ADDR:
2952 if (PREDICT_TRUE (buffer && buflen &&
2953 (*buflen >= sizeof (*ep)) && ep->ip))
2954 {
2955 session->transport.is_ip4 = ep->is_ip4;
2956 session->transport.lcl_port = ep->port;
2957 vcl_ip_copy_from_ep (&session->transport.lcl_ip, ep);
2958 *buflen = sizeof (*ep);
2959 VDBG (1, "VPPCOM_ATTR_SET_LCL_ADDR: sh %u, is_ip4 = %u, addr = %U"
2960 " port %d", session_handle, ep->is_ip4, format_ip46_address,
2961 &session->transport.lcl_ip,
2962 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2963 clib_net_to_host_u16 (ep->port));
2964 }
2965 else
2966 rv = VPPCOM_EINVAL;
2967 break;
2968
Dave Wallace048b1d62018-01-03 22:24:41 -05002969 case VPPCOM_ATTR_GET_LIBC_EPFD:
2970 rv = session->libc_epfd;
Florin Coras5e062572019-03-14 19:07:51 -07002971 VDBG (2, "VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d", rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002972 break;
2973
2974 case VPPCOM_ATTR_SET_LIBC_EPFD:
2975 if (PREDICT_TRUE (buffer && buflen &&
2976 (*buflen == sizeof (session->libc_epfd))))
2977 {
2978 session->libc_epfd = *(int *) buffer;
2979 *buflen = sizeof (session->libc_epfd);
2980
Florin Coras5e062572019-03-14 19:07:51 -07002981 VDBG (2, "VPPCOM_ATTR_SET_LIBC_EPFD: libc_epfd %d, buflen %d",
2982 session->libc_epfd, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002983 }
2984 else
2985 rv = VPPCOM_EINVAL;
2986 break;
2987
2988 case VPPCOM_ATTR_GET_PROTOCOL:
2989 if (buffer && buflen && (*buflen >= sizeof (int)))
2990 {
Florin Coras7e12d942018-06-27 14:32:43 -07002991 *(int *) buffer = session->session_type;
Dave Wallace048b1d62018-01-03 22:24:41 -05002992 *buflen = sizeof (int);
2993
Florin Coras5e062572019-03-14 19:07:51 -07002994 VDBG (2, "VPPCOM_ATTR_GET_PROTOCOL: %d (%s), buflen %d",
2995 *(int *) buffer, *(int *) buffer ? "UDP" : "TCP", *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002996 }
2997 else
2998 rv = VPPCOM_EINVAL;
2999 break;
3000
3001 case VPPCOM_ATTR_GET_LISTEN:
3002 if (buffer && buflen && (*buflen >= sizeof (int)))
3003 {
3004 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3005 VCL_SESS_ATTR_LISTEN);
3006 *buflen = sizeof (int);
3007
Florin Coras5e062572019-03-14 19:07:51 -07003008 VDBG (2, "VPPCOM_ATTR_GET_LISTEN: %d, buflen %d", *(int *) buffer,
3009 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003010 }
3011 else
3012 rv = VPPCOM_EINVAL;
3013 break;
3014
3015 case VPPCOM_ATTR_GET_ERROR:
3016 if (buffer && buflen && (*buflen >= sizeof (int)))
3017 {
3018 *(int *) buffer = 0;
3019 *buflen = sizeof (int);
3020
Florin Coras5e062572019-03-14 19:07:51 -07003021 VDBG (2, "VPPCOM_ATTR_GET_ERROR: %d, buflen %d, #VPP-TBD#",
3022 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003023 }
3024 else
3025 rv = VPPCOM_EINVAL;
3026 break;
3027
3028 case VPPCOM_ATTR_GET_TX_FIFO_LEN:
3029 if (buffer && buflen && (*buflen >= sizeof (u32)))
3030 {
Dave Wallace048b1d62018-01-03 22:24:41 -05003031
3032 /* VPP-TBD */
3033 *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08003034 session->tx_fifo ? session->tx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05003035 vcm->cfg.tx_fifo_size);
3036 *buflen = sizeof (u32);
3037
Florin Coras5e062572019-03-14 19:07:51 -07003038 VDBG (2, "VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), buflen %d,"
3039 " #VPP-TBD#", *(size_t *) buffer, *(size_t *) buffer,
3040 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003041 }
3042 else
3043 rv = VPPCOM_EINVAL;
3044 break;
3045
3046 case VPPCOM_ATTR_SET_TX_FIFO_LEN:
3047 if (buffer && buflen && (*buflen == sizeof (u32)))
3048 {
3049 /* VPP-TBD */
3050 session->sndbuf_size = *(u32 *) buffer;
Florin Coras5e062572019-03-14 19:07:51 -07003051 VDBG (2, "VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), buflen %d,"
3052 " #VPP-TBD#", session->sndbuf_size, session->sndbuf_size,
3053 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003054 }
3055 else
3056 rv = VPPCOM_EINVAL;
3057 break;
3058
3059 case VPPCOM_ATTR_GET_RX_FIFO_LEN:
3060 if (buffer && buflen && (*buflen >= sizeof (u32)))
3061 {
Dave Wallace048b1d62018-01-03 22:24:41 -05003062
3063 /* VPP-TBD */
3064 *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08003065 session->rx_fifo ? session->rx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05003066 vcm->cfg.rx_fifo_size);
3067 *buflen = sizeof (u32);
3068
Florin Coras5e062572019-03-14 19:07:51 -07003069 VDBG (2, "VPPCOM_ATTR_GET_RX_FIFO_LEN: %u (0x%x), buflen %d, "
3070 "#VPP-TBD#", *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003071 }
3072 else
3073 rv = VPPCOM_EINVAL;
3074 break;
3075
3076 case VPPCOM_ATTR_SET_RX_FIFO_LEN:
3077 if (buffer && buflen && (*buflen == sizeof (u32)))
3078 {
3079 /* VPP-TBD */
3080 session->rcvbuf_size = *(u32 *) buffer;
Florin Coras5e062572019-03-14 19:07:51 -07003081 VDBG (2, "VPPCOM_ATTR_SET_RX_FIFO_LEN: %u (0x%x), buflen %d,"
3082 " #VPP-TBD#", session->sndbuf_size, session->sndbuf_size,
3083 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003084 }
3085 else
3086 rv = VPPCOM_EINVAL;
3087 break;
3088
3089 case VPPCOM_ATTR_GET_REUSEADDR:
3090 if (buffer && buflen && (*buflen >= sizeof (int)))
3091 {
3092 /* VPP-TBD */
3093 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3094 VCL_SESS_ATTR_REUSEADDR);
3095 *buflen = sizeof (int);
3096
Florin Coras5e062572019-03-14 19:07:51 -07003097 VDBG (2, "VPPCOM_ATTR_GET_REUSEADDR: %d, buflen %d, #VPP-TBD#",
3098 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003099 }
3100 else
3101 rv = VPPCOM_EINVAL;
3102 break;
3103
Stevenb5a11602017-10-11 09:59:30 -07003104 case VPPCOM_ATTR_SET_REUSEADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05003105 if (buffer && buflen && (*buflen == sizeof (int)) &&
3106 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
3107 {
3108 /* VPP-TBD */
3109 if (*(int *) buffer)
3110 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEADDR);
3111 else
3112 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEADDR);
3113
Florin Coras5e062572019-03-14 19:07:51 -07003114 VDBG (2, "VPPCOM_ATTR_SET_REUSEADDR: %d, buflen %d, #VPP-TBD#",
3115 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_REUSEADDR),
3116 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003117 }
3118 else
3119 rv = VPPCOM_EINVAL;
3120 break;
3121
3122 case VPPCOM_ATTR_GET_REUSEPORT:
3123 if (buffer && buflen && (*buflen >= sizeof (int)))
3124 {
3125 /* VPP-TBD */
3126 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3127 VCL_SESS_ATTR_REUSEPORT);
3128 *buflen = sizeof (int);
3129
Florin Coras5e062572019-03-14 19:07:51 -07003130 VDBG (2, "VPPCOM_ATTR_GET_REUSEPORT: %d, buflen %d, #VPP-TBD#",
3131 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003132 }
3133 else
3134 rv = VPPCOM_EINVAL;
3135 break;
3136
3137 case VPPCOM_ATTR_SET_REUSEPORT:
3138 if (buffer && buflen && (*buflen == sizeof (int)) &&
3139 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
3140 {
3141 /* VPP-TBD */
3142 if (*(int *) buffer)
3143 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEPORT);
3144 else
3145 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEPORT);
3146
Florin Coras5e062572019-03-14 19:07:51 -07003147 VDBG (2, "VPPCOM_ATTR_SET_REUSEPORT: %d, buflen %d, #VPP-TBD#",
3148 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_REUSEPORT),
3149 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003150 }
3151 else
3152 rv = VPPCOM_EINVAL;
3153 break;
3154
3155 case VPPCOM_ATTR_GET_BROADCAST:
3156 if (buffer && buflen && (*buflen >= sizeof (int)))
3157 {
3158 /* VPP-TBD */
3159 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3160 VCL_SESS_ATTR_BROADCAST);
3161 *buflen = sizeof (int);
3162
Florin Coras5e062572019-03-14 19:07:51 -07003163 VDBG (2, "VPPCOM_ATTR_GET_BROADCAST: %d, buflen %d, #VPP-TBD#",
3164 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003165 }
3166 else
3167 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003168 break;
3169
3170 case VPPCOM_ATTR_SET_BROADCAST:
Dave Wallace048b1d62018-01-03 22:24:41 -05003171 if (buffer && buflen && (*buflen == sizeof (int)))
3172 {
3173 /* VPP-TBD */
3174 if (*(int *) buffer)
3175 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_BROADCAST);
3176 else
3177 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_BROADCAST);
3178
Florin Coras5e062572019-03-14 19:07:51 -07003179 VDBG (2, "VPPCOM_ATTR_SET_BROADCAST: %d, buflen %d, #VPP-TBD#",
3180 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_BROADCAST),
3181 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003182 }
3183 else
3184 rv = VPPCOM_EINVAL;
3185 break;
3186
3187 case VPPCOM_ATTR_GET_V6ONLY:
3188 if (buffer && buflen && (*buflen >= sizeof (int)))
3189 {
3190 /* VPP-TBD */
3191 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3192 VCL_SESS_ATTR_V6ONLY);
3193 *buflen = sizeof (int);
3194
Florin Coras5e062572019-03-14 19:07:51 -07003195 VDBG (2, "VPPCOM_ATTR_GET_V6ONLY: %d, buflen %d, #VPP-TBD#",
3196 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003197 }
3198 else
3199 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003200 break;
3201
3202 case VPPCOM_ATTR_SET_V6ONLY:
Dave Wallace048b1d62018-01-03 22:24:41 -05003203 if (buffer && buflen && (*buflen == sizeof (int)))
3204 {
3205 /* VPP-TBD */
3206 if (*(int *) buffer)
3207 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_V6ONLY);
3208 else
3209 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_V6ONLY);
3210
Florin Coras5e062572019-03-14 19:07:51 -07003211 VDBG (2, "VPPCOM_ATTR_SET_V6ONLY: %d, buflen %d, #VPP-TBD#",
3212 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_V6ONLY),
3213 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003214 }
3215 else
3216 rv = VPPCOM_EINVAL;
3217 break;
3218
3219 case VPPCOM_ATTR_GET_KEEPALIVE:
3220 if (buffer && buflen && (*buflen >= sizeof (int)))
3221 {
3222 /* VPP-TBD */
3223 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3224 VCL_SESS_ATTR_KEEPALIVE);
3225 *buflen = sizeof (int);
3226
Florin Coras5e062572019-03-14 19:07:51 -07003227 VDBG (2, "VPPCOM_ATTR_GET_KEEPALIVE: %d, buflen %d, #VPP-TBD#",
3228 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003229 }
3230 else
3231 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003232 break;
Stevenbccd3392017-10-12 20:42:21 -07003233
3234 case VPPCOM_ATTR_SET_KEEPALIVE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003235 if (buffer && buflen && (*buflen == sizeof (int)))
3236 {
3237 /* VPP-TBD */
3238 if (*(int *) buffer)
3239 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3240 else
3241 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3242
Florin Coras5e062572019-03-14 19:07:51 -07003243 VDBG (2, "VPPCOM_ATTR_SET_KEEPALIVE: %d, buflen %d, #VPP-TBD#",
3244 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_KEEPALIVE),
3245 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003246 }
3247 else
3248 rv = VPPCOM_EINVAL;
3249 break;
3250
3251 case VPPCOM_ATTR_GET_TCP_NODELAY:
3252 if (buffer && buflen && (*buflen >= sizeof (int)))
3253 {
3254 /* VPP-TBD */
3255 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3256 VCL_SESS_ATTR_TCP_NODELAY);
3257 *buflen = sizeof (int);
3258
Florin Coras5e062572019-03-14 19:07:51 -07003259 VDBG (2, "VPPCOM_ATTR_GET_TCP_NODELAY: %d, buflen %d, #VPP-TBD#",
3260 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003261 }
3262 else
3263 rv = VPPCOM_EINVAL;
3264 break;
3265
3266 case VPPCOM_ATTR_SET_TCP_NODELAY:
3267 if (buffer && buflen && (*buflen == sizeof (int)))
3268 {
3269 /* VPP-TBD */
3270 if (*(int *) buffer)
3271 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3272 else
3273 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3274
Florin Coras5e062572019-03-14 19:07:51 -07003275 VDBG (2, "VPPCOM_ATTR_SET_TCP_NODELAY: %d, buflen %d, #VPP-TBD#",
3276 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_TCP_NODELAY),
3277 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003278 }
3279 else
3280 rv = VPPCOM_EINVAL;
3281 break;
3282
3283 case VPPCOM_ATTR_GET_TCP_KEEPIDLE:
3284 if (buffer && buflen && (*buflen >= sizeof (int)))
3285 {
3286 /* VPP-TBD */
3287 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3288 VCL_SESS_ATTR_TCP_KEEPIDLE);
3289 *buflen = sizeof (int);
3290
Florin Coras5e062572019-03-14 19:07:51 -07003291 VDBG (2, "VPPCOM_ATTR_GET_TCP_KEEPIDLE: %d, buflen %d, #VPP-TBD#",
3292 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003293 }
3294 else
3295 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003296 break;
3297
3298 case VPPCOM_ATTR_SET_TCP_KEEPIDLE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003299 if (buffer && buflen && (*buflen == sizeof (int)))
3300 {
3301 /* VPP-TBD */
3302 if (*(int *) buffer)
3303 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3304 else
3305 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3306
Florin Coras5e062572019-03-14 19:07:51 -07003307 VDBG (2, "VPPCOM_ATTR_SET_TCP_KEEPIDLE: %d, buflen %d, #VPP-TBD#",
Florin Coras0d427d82018-06-27 03:24:07 -07003308 VCL_SESS_ATTR_TEST (session->attr,
3309 VCL_SESS_ATTR_TCP_KEEPIDLE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003310 }
3311 else
3312 rv = VPPCOM_EINVAL;
3313 break;
3314
3315 case VPPCOM_ATTR_GET_TCP_KEEPINTVL:
3316 if (buffer && buflen && (*buflen >= sizeof (int)))
3317 {
3318 /* VPP-TBD */
3319 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3320 VCL_SESS_ATTR_TCP_KEEPINTVL);
3321 *buflen = sizeof (int);
3322
Florin Coras5e062572019-03-14 19:07:51 -07003323 VDBG (2, "VPPCOM_ATTR_GET_TCP_KEEPINTVL: %d, buflen %d, #VPP-TBD#",
3324 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003325 }
3326 else
3327 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003328 break;
3329
3330 case VPPCOM_ATTR_SET_TCP_KEEPINTVL:
Dave Wallace048b1d62018-01-03 22:24:41 -05003331 if (buffer && buflen && (*buflen == sizeof (int)))
3332 {
3333 /* VPP-TBD */
3334 if (*(int *) buffer)
3335 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3336 else
3337 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3338
Florin Coras5e062572019-03-14 19:07:51 -07003339 VDBG (2, "VPPCOM_ATTR_SET_TCP_KEEPINTVL: %d, buflen %d, #VPP-TBD#",
Florin Coras0d427d82018-06-27 03:24:07 -07003340 VCL_SESS_ATTR_TEST (session->attr,
3341 VCL_SESS_ATTR_TCP_KEEPINTVL), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003342 }
3343 else
3344 rv = VPPCOM_EINVAL;
3345 break;
3346
3347 case VPPCOM_ATTR_GET_TCP_USER_MSS:
3348 if (buffer && buflen && (*buflen >= sizeof (u32)))
3349 {
3350 /* VPP-TBD */
3351 *(u32 *) buffer = session->user_mss;
3352 *buflen = sizeof (int);
3353
Florin Coras5e062572019-03-14 19:07:51 -07003354 VDBG (2, "VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d, #VPP-TBD#",
3355 *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003356 }
3357 else
3358 rv = VPPCOM_EINVAL;
3359 break;
3360
3361 case VPPCOM_ATTR_SET_TCP_USER_MSS:
3362 if (buffer && buflen && (*buflen == sizeof (u32)))
3363 {
3364 /* VPP-TBD */
3365 session->user_mss = *(u32 *) buffer;
3366
Florin Coras5e062572019-03-14 19:07:51 -07003367 VDBG (2, "VPPCOM_ATTR_SET_TCP_USER_MSS: %u, buflen %d, #VPP-TBD#",
3368 session->user_mss, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003369 }
3370 else
3371 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003372 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003373
Florin Coras7baeb712019-01-04 17:05:43 -08003374 case VPPCOM_ATTR_SET_SHUT:
3375 if (*flags == SHUT_RD || *flags == SHUT_RDWR)
3376 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_SHUT_RD);
3377 if (*flags == SHUT_WR || *flags == SHUT_RDWR)
3378 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_SHUT_WR);
3379 break;
3380
3381 case VPPCOM_ATTR_GET_SHUT:
3382 if (VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_SHUT_RD))
3383 tmp_flags = 1;
3384 if (VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_SHUT_WR))
3385 tmp_flags |= 2;
3386 if (tmp_flags == 1)
3387 *(int *) buffer = SHUT_RD;
3388 else if (tmp_flags == 2)
3389 *(int *) buffer = SHUT_WR;
3390 else if (tmp_flags == 3)
3391 *(int *) buffer = SHUT_RDWR;
3392 *buflen = sizeof (int);
3393 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003394 default:
3395 rv = VPPCOM_EINVAL;
3396 break;
Dave Wallace35830af2017-10-09 01:43:42 -04003397 }
3398
Dave Wallace35830af2017-10-09 01:43:42 -04003399 return rv;
3400}
3401
Stevenac1f96d2017-10-24 16:03:58 -07003402int
Florin Coras134a9962018-08-28 11:32:04 -07003403vppcom_session_recvfrom (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003404 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3405{
Florin Coras134a9962018-08-28 11:32:04 -07003406 vcl_worker_t *wrk = vcl_worker_get_current ();
Stevenac1f96d2017-10-24 16:03:58 -07003407 int rv = VPPCOM_OK;
Florin Coras7e12d942018-06-27 14:32:43 -07003408 vcl_session_t *session = 0;
Stevenac1f96d2017-10-24 16:03:58 -07003409
3410 if (ep)
3411 {
Florin Coras134a9962018-08-28 11:32:04 -07003412 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07003413 if (PREDICT_FALSE (!session))
Stevenac1f96d2017-10-24 16:03:58 -07003414 {
Florin Coras5e062572019-03-14 19:07:51 -07003415 VDBG (0, "sh 0x%llx is closed!", session_handle);
Florin Coras460dce62018-07-27 05:45:06 -07003416 return VPPCOM_EBADFD;
Stevenac1f96d2017-10-24 16:03:58 -07003417 }
Florin Coras7e12d942018-06-27 14:32:43 -07003418 ep->is_ip4 = session->transport.is_ip4;
3419 ep->port = session->transport.rmt_port;
Stevenac1f96d2017-10-24 16:03:58 -07003420 }
Steven58f464e2017-10-25 12:33:12 -07003421
3422 if (flags == 0)
Florin Coras134a9962018-08-28 11:32:04 -07003423 rv = vppcom_session_read (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003424 else if (flags & MSG_PEEK)
Florin Coras134a9962018-08-28 11:32:04 -07003425 rv = vppcom_session_peek (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003426 else
3427 {
Florin Corasa7a1a222018-12-30 17:11:31 -08003428 VDBG (0, "Unsupport flags for recvfrom %d", flags);
Florin Coras460dce62018-07-27 05:45:06 -07003429 return VPPCOM_EAFNOSUPPORT;
Stevenac1f96d2017-10-24 16:03:58 -07003430 }
3431
Florin Coras99368312018-08-02 10:45:44 -07003432 if (ep)
3433 {
3434 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05003435 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
3436 sizeof (ip4_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003437 else
Dave Barach178cf492018-11-13 16:34:13 -05003438 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
3439 sizeof (ip6_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003440 }
Florin Coras460dce62018-07-27 05:45:06 -07003441
Stevenac1f96d2017-10-24 16:03:58 -07003442 return rv;
3443}
3444
3445int
Florin Coras134a9962018-08-28 11:32:04 -07003446vppcom_session_sendto (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003447 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3448{
Dave Wallace617dffa2017-10-26 14:47:06 -04003449 if (!buffer)
3450 return VPPCOM_EINVAL;
3451
3452 if (ep)
3453 {
3454 // TBD
3455 return VPPCOM_EINVAL;
3456 }
3457
3458 if (flags)
3459 {
3460 // TBD check the flags and do the right thing
Florin Coras5e062572019-03-14 19:07:51 -07003461 VDBG (2, "handling flags 0x%u (%d) not implemented yet.", flags, flags);
Dave Wallace617dffa2017-10-26 14:47:06 -04003462 }
3463
Florin Coras42ceddb2018-12-12 10:56:01 -08003464 return (vppcom_session_write_inline (session_handle, buffer, buflen, 1));
Stevenac1f96d2017-10-24 16:03:58 -07003465}
3466
Dave Wallace048b1d62018-01-03 22:24:41 -05003467int
3468vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time)
3469{
Florin Coras134a9962018-08-28 11:32:04 -07003470 vcl_worker_t *wrk = vcl_worker_get_current ();
3471 f64 timeout = clib_time_now (&wrk->clib_time) + wait_for_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05003472 u32 i, keep_trying = 1;
Florin Coras6917b942018-11-13 22:44:54 -08003473 svm_msg_q_msg_t msg;
3474 session_event_t *e;
Dave Wallace048b1d62018-01-03 22:24:41 -05003475 int rv, num_ev = 0;
3476
Florin Coras5e062572019-03-14 19:07:51 -07003477 VDBG (3, "vp %p, nsids %u, wait_for_time %f", vp, n_sids, wait_for_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05003478
3479 if (!vp)
3480 return VPPCOM_EFAULT;
3481
3482 do
3483 {
Florin Coras7e12d942018-06-27 14:32:43 -07003484 vcl_session_t *session;
Dave Wallace048b1d62018-01-03 22:24:41 -05003485
Florin Coras6917b942018-11-13 22:44:54 -08003486 /* Dequeue all events and drop all unhandled io events */
3487 while (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0) == 0)
3488 {
3489 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
3490 vcl_handle_mq_event (wrk, e);
3491 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
3492 }
3493 vec_reset_length (wrk->unhandled_evts_vector);
3494
Dave Wallace048b1d62018-01-03 22:24:41 -05003495 for (i = 0; i < n_sids; i++)
3496 {
Florin Coras7baeb712019-01-04 17:05:43 -08003497 session = vcl_session_get (wrk, vp[i].sh);
Florin Coras070453d2018-08-24 17:04:27 -07003498 if (!session)
Florin Coras6917b942018-11-13 22:44:54 -08003499 {
3500 vp[i].revents = POLLHUP;
3501 num_ev++;
3502 continue;
3503 }
Dave Wallace048b1d62018-01-03 22:24:41 -05003504
Florin Coras6917b942018-11-13 22:44:54 -08003505 vp[i].revents = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003506
3507 if (POLLIN & vp[i].events)
3508 {
Florin Coras0ef8ef22019-01-18 08:37:13 -08003509 rv = vcl_session_read_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003510 if (rv > 0)
3511 {
Florin Coras6917b942018-11-13 22:44:54 -08003512 vp[i].revents |= POLLIN;
Dave Wallace048b1d62018-01-03 22:24:41 -05003513 num_ev++;
3514 }
3515 else if (rv < 0)
3516 {
3517 switch (rv)
3518 {
3519 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003520 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003521 break;
3522
3523 default:
Florin Coras6917b942018-11-13 22:44:54 -08003524 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003525 break;
3526 }
3527 num_ev++;
3528 }
3529 }
3530
3531 if (POLLOUT & vp[i].events)
3532 {
Florin Coras0ef8ef22019-01-18 08:37:13 -08003533 rv = vcl_session_write_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003534 if (rv > 0)
3535 {
Florin Coras6917b942018-11-13 22:44:54 -08003536 vp[i].revents |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05003537 num_ev++;
3538 }
3539 else if (rv < 0)
3540 {
3541 switch (rv)
3542 {
3543 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003544 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003545 break;
3546
3547 default:
Florin Coras6917b942018-11-13 22:44:54 -08003548 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003549 break;
3550 }
3551 num_ev++;
3552 }
3553 }
3554
Dave Wallace7e607a72018-06-18 18:41:32 -04003555 if (0) // Note "done:" label used by VCL_SESSION_LOCK_AND_GET()
Dave Wallace048b1d62018-01-03 22:24:41 -05003556 {
Florin Coras6917b942018-11-13 22:44:54 -08003557 vp[i].revents = POLLNVAL;
Dave Wallace048b1d62018-01-03 22:24:41 -05003558 num_ev++;
3559 }
3560 }
3561 if (wait_for_time != -1)
Florin Coras134a9962018-08-28 11:32:04 -07003562 keep_trying = (clib_time_now (&wrk->clib_time) <= timeout) ? 1 : 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003563 }
3564 while ((num_ev == 0) && keep_trying);
3565
Dave Wallace048b1d62018-01-03 22:24:41 -05003566 return num_ev;
3567}
3568
Florin Coras99368312018-08-02 10:45:44 -07003569int
3570vppcom_mq_epoll_fd (void)
3571{
Florin Coras134a9962018-08-28 11:32:04 -07003572 vcl_worker_t *wrk = vcl_worker_get_current ();
3573 return wrk->mqs_epfd;
3574}
3575
3576int
Florin Coras30e79c22019-01-02 19:31:22 -08003577vppcom_session_index (vcl_session_handle_t session_handle)
Florin Coras134a9962018-08-28 11:32:04 -07003578{
3579 return session_handle & 0xFFFFFF;
3580}
3581
3582int
Florin Coras30e79c22019-01-02 19:31:22 -08003583vppcom_session_worker (vcl_session_handle_t session_handle)
3584{
3585 return session_handle >> 24;
3586}
3587
3588int
Florin Coras134a9962018-08-28 11:32:04 -07003589vppcom_worker_register (void)
3590{
Florin Coras47c40e22018-11-26 17:01:36 -08003591 if (!vcl_worker_alloc_and_init ())
3592 return VPPCOM_EEXIST;
3593
3594 if (vcl_worker_set_bapi ())
3595 return VPPCOM_EEXIST;
3596
3597 if (vcl_worker_register_with_vpp ())
3598 return VPPCOM_EEXIST;
3599
3600 return VPPCOM_OK;
Florin Coras99368312018-08-02 10:45:44 -07003601}
3602
Florin Coras369db832019-07-08 12:34:45 -07003603void
3604vppcom_worker_unregister (void)
3605{
3606 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
3607 vcl_set_worker_index (~0);
3608}
3609
Florin Corasdfe4cf42018-11-28 22:13:45 -08003610int
3611vppcom_worker_index (void)
3612{
3613 return vcl_get_worker_index ();
3614}
3615
Florin Corase0982e52019-01-25 13:19:56 -08003616int
3617vppcom_worker_mqs_epfd (void)
3618{
3619 vcl_worker_t *wrk = vcl_worker_get_current ();
3620 if (!vcm->cfg.use_mq_eventfd)
3621 return -1;
3622 return wrk->mqs_epfd;
3623}
3624
Nathan Skrzypczak9fd99622019-05-16 14:38:44 +02003625int
3626vppcom_session_is_connectable_listener (uint32_t session_handle)
3627{
3628 vcl_session_t *session;
3629 vcl_worker_t *wrk = vcl_worker_get_current ();
3630 session = vcl_session_get_w_handle (wrk, session_handle);
3631 if (!session)
3632 return VPPCOM_EBADFD;
3633 return vcl_session_is_connectable_listener (wrk, session);
3634}
3635
3636int
3637vppcom_session_listener (uint32_t session_handle)
3638{
3639 vcl_worker_t *wrk = vcl_worker_get_current ();
3640 vcl_session_t *listen_session, *session;
3641 session = vcl_session_get_w_handle (wrk, session_handle);
3642 if (!session)
3643 return VPPCOM_EBADFD;
3644 if (session->listener_index == VCL_INVALID_SESSION_INDEX)
3645 return VPPCOM_EBADFD;
3646 listen_session = vcl_session_get_w_handle (wrk, session->listener_index);
3647 if (!listen_session)
3648 return VPPCOM_EBADFD;
3649 return vcl_session_handle (listen_session);
3650}
3651
3652int
3653vppcom_session_n_accepted (uint32_t session_handle)
3654{
3655 vcl_worker_t *wrk = vcl_worker_get_current ();
3656 vcl_session_t *session = vcl_session_get_w_handle (wrk, session_handle);
3657 if (!session)
3658 return VPPCOM_EBADFD;
3659 return session->n_accepted_sessions;
3660}
3661
Dave Wallacee22aa742017-10-20 12:30:38 -04003662/*
3663 * fd.io coding-style-patch-verification: ON
3664 *
3665 * Local Variables:
3666 * eval: (c-set-style "gnu")
3667 * End:
3668 */