blob: 07136e9c6c8793dde29649d7b16e8b5fdade475e [file] [log] [blame]
Dave Wallace543852a2017-08-03 02:11:34 -04001/*
Dave Wallace33e002b2017-09-06 01:20:02 -04002 * Copyright (c) 2017 Cisco and/or its affiliates.
Dave Wallace543852a2017-08-03 02:11:34 -04003 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <stdio.h>
17#include <stdlib.h>
Dave Wallace543852a2017-08-03 02:11:34 -040018#include <svm/svm_fifo_segment.h>
Dave Wallace5c7cf1c2017-10-24 04:12:18 -040019#include <vcl/vppcom.h>
Florin Coras0d427d82018-06-27 03:24:07 -070020#include <vcl/vcl_debug.h>
Florin Coras697faea2018-06-27 17:10:49 -070021#include <vcl/vcl_private.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 Coras54693d22018-07-17 10:46:29 -070025
Florin Corasd85de682018-11-29 17:02:29 -080026static int
27vcl_wait_for_segment (u64 segment_handle)
Florin Coras54693d22018-07-17 10:46:29 -070028{
Florin Corasd85de682018-11-29 17:02:29 -080029 vcl_worker_t *wrk = vcl_worker_get_current ();
30 u32 wait_for_seconds = 10, segment_index;
31 f64 timeout;
Florin Coras54693d22018-07-17 10:46:29 -070032
Florin Corasd85de682018-11-29 17:02:29 -080033 if (segment_handle == VCL_INVALID_SEGMENT_HANDLE)
34 return 1;
Florin Coras54693d22018-07-17 10:46:29 -070035
Florin Corasd85de682018-11-29 17:02:29 -080036 timeout = clib_time_now (&wrk->clib_time) + wait_for_seconds;
37 while (clib_time_now (&wrk->clib_time) < timeout)
Florin Coras54693d22018-07-17 10:46:29 -070038 {
Florin Corasd85de682018-11-29 17:02:29 -080039 segment_index = vcl_segment_table_lookup (segment_handle);
40 if (segment_index != VCL_INVALID_SEGMENT_INDEX)
41 return 0;
42 usleep (10);
Florin Coras54693d22018-07-17 10:46:29 -070043 }
Florin Corasd85de682018-11-29 17:02:29 -080044 return 1;
Florin Coras54693d22018-07-17 10:46:29 -070045}
46
Florin Coras697faea2018-06-27 17:10:49 -070047const char *
Dave Wallace543852a2017-08-03 02:11:34 -040048vppcom_session_state_str (session_state_t state)
49{
50 char *st;
51
52 switch (state)
53 {
54 case STATE_START:
55 st = "STATE_START";
56 break;
57
58 case STATE_CONNECT:
59 st = "STATE_CONNECT";
60 break;
61
62 case STATE_LISTEN:
63 st = "STATE_LISTEN";
64 break;
65
66 case STATE_ACCEPT:
67 st = "STATE_ACCEPT";
68 break;
69
Dave Wallace4878cbe2017-11-21 03:45:09 -050070 case STATE_CLOSE_ON_EMPTY:
71 st = "STATE_CLOSE_ON_EMPTY";
72 break;
73
Dave Wallace543852a2017-08-03 02:11:34 -040074 case STATE_DISCONNECT:
75 st = "STATE_DISCONNECT";
76 break;
77
78 case STATE_FAILED:
79 st = "STATE_FAILED";
80 break;
81
82 default:
83 st = "UNKNOWN_STATE";
84 break;
85 }
86
87 return st;
88}
89
Dave Wallace543852a2017-08-03 02:11:34 -040090u8 *
91format_ip4_address (u8 * s, va_list * args)
92{
93 u8 *a = va_arg (*args, u8 *);
94 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
95}
96
97u8 *
98format_ip6_address (u8 * s, va_list * args)
99{
100 ip6_address_t *a = va_arg (*args, ip6_address_t *);
101 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
102
103 i_max_n_zero = ARRAY_LEN (a->as_u16);
104 max_n_zeros = 0;
105 i_first_zero = i_max_n_zero;
106 n_zeros = 0;
107 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
108 {
109 u32 is_zero = a->as_u16[i] == 0;
110 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
111 {
112 i_first_zero = i;
113 n_zeros = 0;
114 }
115 n_zeros += is_zero;
116 if ((!is_zero && n_zeros > max_n_zeros)
117 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
118 {
119 i_max_n_zero = i_first_zero;
120 max_n_zeros = n_zeros;
121 i_first_zero = ARRAY_LEN (a->as_u16);
122 n_zeros = 0;
123 }
124 }
125
126 last_double_colon = 0;
127 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
128 {
129 if (i == i_max_n_zero && max_n_zeros > 1)
130 {
131 s = format (s, "::");
132 i += max_n_zeros - 1;
133 last_double_colon = 1;
134 }
135 else
136 {
137 s = format (s, "%s%x",
138 (last_double_colon || i == 0) ? "" : ":",
139 clib_net_to_host_u16 (a->as_u16[i]));
140 last_double_colon = 0;
141 }
142 }
143
144 return s;
145}
146
147/* Format an IP46 address. */
148u8 *
149format_ip46_address (u8 * s, va_list * args)
150{
151 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
152 ip46_type_t type = va_arg (*args, ip46_type_t);
153 int is_ip4 = 1;
154
155 switch (type)
156 {
157 case IP46_TYPE_ANY:
158 is_ip4 = ip46_address_is_ip4 (ip46);
159 break;
160 case IP46_TYPE_IP4:
161 is_ip4 = 1;
162 break;
163 case IP46_TYPE_IP6:
164 is_ip4 = 0;
165 break;
166 }
167
168 return is_ip4 ?
169 format (s, "%U", format_ip4_address, &ip46->ip4) :
170 format (s, "%U", format_ip6_address, &ip46->ip6);
171}
172
Florin Coras697faea2018-06-27 17:10:49 -0700173/*
174 * VPPCOM Utility Functions
175 */
176
Florin Coras697faea2018-06-27 17:10:49 -0700177
Florin Corasc9fbd662018-08-24 12:59:56 -0700178static svm_msg_q_t *
Florin Coras134a9962018-08-28 11:32:04 -0700179vcl_session_vpp_evt_q (vcl_worker_t * wrk, vcl_session_t * s)
Florin Corasc9fbd662018-08-24 12:59:56 -0700180{
181 if (vcl_session_is_ct (s))
Florin Coras134a9962018-08-28 11:32:04 -0700182 return wrk->vpp_event_queues[0];
Florin Corasc9fbd662018-08-24 12:59:56 -0700183 else
Florin Coras134a9962018-08-28 11:32:04 -0700184 return wrk->vpp_event_queues[s->tx_fifo->master_thread_index];
Florin Corasc9fbd662018-08-24 12:59:56 -0700185}
186
Florin Coras54693d22018-07-17 10:46:29 -0700187static void
188vcl_send_session_accepted_reply (svm_msg_q_t * mq, u32 context,
189 session_handle_t handle, int retval)
190{
191 app_session_evt_t _app_evt, *app_evt = &_app_evt;
192 session_accepted_reply_msg_t *rmp;
193 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_ACCEPTED_REPLY);
194 rmp = (session_accepted_reply_msg_t *) app_evt->evt->data;
195 rmp->handle = handle;
196 rmp->context = context;
197 rmp->retval = retval;
198 app_send_ctrl_evt_to_vpp (mq, app_evt);
199}
200
Florin Coras99368312018-08-02 10:45:44 -0700201static void
202vcl_send_session_disconnected_reply (svm_msg_q_t * mq, u32 context,
203 session_handle_t handle, int retval)
204{
205 app_session_evt_t _app_evt, *app_evt = &_app_evt;
206 session_disconnected_reply_msg_t *rmp;
207 app_alloc_ctrl_evt_to_vpp (mq, app_evt,
208 SESSION_CTRL_EVT_DISCONNECTED_REPLY);
209 rmp = (session_disconnected_reply_msg_t *) app_evt->evt->data;
210 rmp->handle = handle;
211 rmp->context = context;
212 rmp->retval = retval;
213 app_send_ctrl_evt_to_vpp (mq, app_evt);
214}
215
Florin Corasc9fbd662018-08-24 12:59:56 -0700216static void
217vcl_send_session_reset_reply (svm_msg_q_t * mq, u32 context,
218 session_handle_t handle, int retval)
219{
220 app_session_evt_t _app_evt, *app_evt = &_app_evt;
221 session_reset_reply_msg_t *rmp;
222 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_RESET_REPLY);
223 rmp = (session_reset_reply_msg_t *) app_evt->evt->data;
224 rmp->handle = handle;
225 rmp->context = context;
226 rmp->retval = retval;
227 app_send_ctrl_evt_to_vpp (mq, app_evt);
228}
229
Florin Coras54693d22018-07-17 10:46:29 -0700230static u32
Florin Coras134a9962018-08-28 11:32:04 -0700231vcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp)
Florin Coras54693d22018-07-17 10:46:29 -0700232{
233 vcl_session_t *session, *listen_session;
234 svm_fifo_t *rx_fifo, *tx_fifo;
Florin Coras134a9962018-08-28 11:32:04 -0700235 u32 vpp_wrk_index;
Florin Coras99368312018-08-02 10:45:44 -0700236 svm_msg_q_t *evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700237
Florin Coras134a9962018-08-28 11:32:04 -0700238 session = vcl_session_alloc (wrk);
Florin Coras99368312018-08-02 10:45:44 -0700239
Florin Coras134a9962018-08-28 11:32:04 -0700240 listen_session = vcl_session_table_lookup_listener (wrk,
241 mp->listener_handle);
Florin Coras54693d22018-07-17 10:46:29 -0700242 if (!listen_session)
243 {
244 svm_msg_q_t *evt_q;
245 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
246 clib_warning ("VCL<%d>: ERROR: couldn't find listen session: "
247 "unknown vpp listener handle %llx",
248 getpid (), mp->listener_handle);
249 vcl_send_session_accepted_reply (evt_q, mp->context, mp->handle,
250 VNET_API_ERROR_INVALID_ARGUMENT);
Florin Coras134a9962018-08-28 11:32:04 -0700251 vcl_session_free (wrk, session);
Florin Coras54693d22018-07-17 10:46:29 -0700252 return VCL_INVALID_SESSION_INDEX;
253 }
254
Florin Coras54693d22018-07-17 10:46:29 -0700255 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
256 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
257
258 if (mp->server_event_queue_address)
259 {
260 session->vpp_evt_q = uword_to_pointer (mp->client_event_queue_address,
261 svm_msg_q_t *);
262 session->our_evt_q = uword_to_pointer (mp->server_event_queue_address,
263 svm_msg_q_t *);
Florin Corasd85de682018-11-29 17:02:29 -0800264 if (vcl_wait_for_segment (mp->segment_handle))
265 {
266 clib_warning ("segment for session %u couldn't be mounted!",
267 session->session_index);
268 return VCL_INVALID_SESSION_INDEX;
269 }
Florin Coras134a9962018-08-28 11:32:04 -0700270 rx_fifo->master_session_index = session->session_index;
271 tx_fifo->master_session_index = session->session_index;
Florin Coras21795132018-09-09 09:40:51 -0700272 rx_fifo->master_thread_index = vcl_get_worker_index ();
273 tx_fifo->master_thread_index = vcl_get_worker_index ();
Florin Coras134a9962018-08-28 11:32:04 -0700274 vec_validate (wrk->vpp_event_queues, 0);
Florin Coras99368312018-08-02 10:45:44 -0700275 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
Florin Coras134a9962018-08-28 11:32:04 -0700276 wrk->vpp_event_queues[0] = evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700277 }
278 else
279 {
280 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
281 svm_msg_q_t *);
Florin Coras134a9962018-08-28 11:32:04 -0700282 rx_fifo->client_session_index = session->session_index;
283 tx_fifo->client_session_index = session->session_index;
Florin Coras21795132018-09-09 09:40:51 -0700284 rx_fifo->client_thread_index = vcl_get_worker_index ();
285 tx_fifo->client_thread_index = vcl_get_worker_index ();
Florin Coras99368312018-08-02 10:45:44 -0700286 vpp_wrk_index = tx_fifo->master_thread_index;
Florin Coras134a9962018-08-28 11:32:04 -0700287 vec_validate (wrk->vpp_event_queues, vpp_wrk_index);
288 wrk->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700289 }
290
291 session->vpp_handle = mp->handle;
292 session->client_context = mp->context;
293 session->rx_fifo = rx_fifo;
294 session->tx_fifo = tx_fifo;
295
296 session->session_state = STATE_ACCEPT;
297 session->transport.rmt_port = mp->port;
298 session->transport.is_ip4 = mp->is_ip4;
Dave Barach178cf492018-11-13 16:34:13 -0500299 clib_memcpy_fast (&session->transport.rmt_ip, mp->ip,
300 sizeof (ip46_address_t));
Florin Coras54693d22018-07-17 10:46:29 -0700301
Florin Coras134a9962018-08-28 11:32:04 -0700302 vcl_session_table_add_vpp_handle (wrk, mp->handle, session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -0700303 session->transport.lcl_port = listen_session->transport.lcl_port;
304 session->transport.lcl_ip = listen_session->transport.lcl_ip;
Florin Coras460dce62018-07-27 05:45:06 -0700305 session->session_type = listen_session->session_type;
306 session->is_dgram = session->session_type == VPPCOM_PROTO_UDP;
Florin Coras54693d22018-07-17 10:46:29 -0700307
308 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: client accept request from %s"
Florin Coras134a9962018-08-28 11:32:04 -0700309 " address %U port %d queue %p!", getpid (), mp->handle,
310 session->session_index,
Florin Coras54693d22018-07-17 10:46:29 -0700311 mp->is_ip4 ? "IPv4" : "IPv6", format_ip46_address, &mp->ip,
312 mp->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
313 clib_net_to_host_u16 (mp->port), session->vpp_evt_q);
314 vcl_evt (VCL_EVT_ACCEPT, session, listen_session, session_index);
315
Florin Coras134a9962018-08-28 11:32:04 -0700316 return session->session_index;
Florin Coras54693d22018-07-17 10:46:29 -0700317}
318
319static u32
Florin Coras134a9962018-08-28 11:32:04 -0700320vcl_session_connected_handler (vcl_worker_t * wrk,
321 session_connected_msg_t * mp)
Florin Coras54693d22018-07-17 10:46:29 -0700322{
Florin Coras99368312018-08-02 10:45:44 -0700323 u32 session_index, vpp_wrk_index;
Florin Coras54693d22018-07-17 10:46:29 -0700324 svm_fifo_t *rx_fifo, *tx_fifo;
Florin Coras99368312018-08-02 10:45:44 -0700325 vcl_session_t *session = 0;
326 svm_msg_q_t *evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700327
328 session_index = mp->context;
Florin Coras134a9962018-08-28 11:32:04 -0700329 session = vcl_session_get (wrk, session_index);
Florin Coras070453d2018-08-24 17:04:27 -0700330 if (!session)
331 {
332 clib_warning ("[%s] ERROR: vpp handle 0x%llx, sid %u: "
333 "Invalid session index (%u)!",
334 getpid (), mp->handle, session_index);
335 return VCL_INVALID_SESSION_INDEX;
336 }
Florin Coras54693d22018-07-17 10:46:29 -0700337 if (mp->retval)
338 {
Florin Coras070453d2018-08-24 17:04:27 -0700339 clib_warning ("VCL<%d>: ERROR: sid %u: connect failed! %U", getpid (),
Florin Coras21795132018-09-09 09:40:51 -0700340 session_index, format_api_error, ntohl (mp->retval));
Florin Coras070453d2018-08-24 17:04:27 -0700341 session->session_state = STATE_FAILED;
342 session->vpp_handle = mp->handle;
343 return session_index;
Florin Coras54693d22018-07-17 10:46:29 -0700344 }
345
Florin Coras460dce62018-07-27 05:45:06 -0700346 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
347 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
Florin Corasd85de682018-11-29 17:02:29 -0800348 if (vcl_wait_for_segment (mp->segment_handle))
349 {
350 clib_warning ("segment for session %u couldn't be mounted!",
351 session->session_index);
352 return VCL_INVALID_SESSION_INDEX;
353 }
354
Florin Coras460dce62018-07-27 05:45:06 -0700355 rx_fifo->client_session_index = session_index;
356 tx_fifo->client_session_index = session_index;
Florin Coras21795132018-09-09 09:40:51 -0700357 rx_fifo->client_thread_index = vcl_get_worker_index ();
358 tx_fifo->client_thread_index = vcl_get_worker_index ();
Florin Coras460dce62018-07-27 05:45:06 -0700359
Florin Coras54693d22018-07-17 10:46:29 -0700360 if (mp->client_event_queue_address)
361 {
362 session->vpp_evt_q = uword_to_pointer (mp->server_event_queue_address,
363 svm_msg_q_t *);
364 session->our_evt_q = uword_to_pointer (mp->client_event_queue_address,
365 svm_msg_q_t *);
Florin Coras99368312018-08-02 10:45:44 -0700366
Florin Coras134a9962018-08-28 11:32:04 -0700367 vec_validate (wrk->vpp_event_queues, 0);
Florin Coras99368312018-08-02 10:45:44 -0700368 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
Florin Coras134a9962018-08-28 11:32:04 -0700369 wrk->vpp_event_queues[0] = evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700370 }
371 else
Florin Coras99368312018-08-02 10:45:44 -0700372 {
373 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
374 svm_msg_q_t *);
375 vpp_wrk_index = tx_fifo->master_thread_index;
Florin Coras134a9962018-08-28 11:32:04 -0700376 vec_validate (wrk->vpp_event_queues, vpp_wrk_index);
377 wrk->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
Florin Coras99368312018-08-02 10:45:44 -0700378 }
Florin Coras54693d22018-07-17 10:46:29 -0700379
Florin Coras54693d22018-07-17 10:46:29 -0700380 session->rx_fifo = rx_fifo;
381 session->tx_fifo = tx_fifo;
382 session->vpp_handle = mp->handle;
383 session->transport.is_ip4 = mp->is_ip4;
Dave Barach178cf492018-11-13 16:34:13 -0500384 clib_memcpy_fast (&session->transport.lcl_ip, mp->lcl_ip,
385 sizeof (session->transport.lcl_ip));
Florin Coras54693d22018-07-17 10:46:29 -0700386 session->transport.lcl_port = mp->lcl_port;
387 session->session_state = STATE_CONNECT;
388
389 /* Add it to lookup table */
Florin Coras134a9962018-08-28 11:32:04 -0700390 hash_set (wrk->session_index_by_vpp_handles, mp->handle, session_index);
Florin Coras54693d22018-07-17 10:46:29 -0700391
392 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: connect succeeded! "
393 "session_rx_fifo %p, refcnt %d, session_tx_fifo %p, refcnt %d",
394 getpid (), mp->handle, session_index, session->rx_fifo,
395 session->rx_fifo->refcnt, session->tx_fifo, session->tx_fifo->refcnt);
Florin Coras070453d2018-08-24 17:04:27 -0700396
Florin Coras54693d22018-07-17 10:46:29 -0700397 return session_index;
398}
399
Florin Corasc9fbd662018-08-24 12:59:56 -0700400static u32
Florin Coras134a9962018-08-28 11:32:04 -0700401vcl_session_reset_handler (vcl_worker_t * wrk,
402 session_reset_msg_t * reset_msg)
Florin Corasc9fbd662018-08-24 12:59:56 -0700403{
404 vcl_session_t *session;
405 u32 sid;
406
Florin Coras134a9962018-08-28 11:32:04 -0700407 sid = vcl_session_index_from_vpp_handle (wrk, reset_msg->handle);
408 session = vcl_session_get (wrk, sid);
Florin Corasc9fbd662018-08-24 12:59:56 -0700409 if (!session)
410 {
411 VDBG (0, "request to reset unknown handle 0x%llx", reset_msg->handle);
412 return VCL_INVALID_SESSION_INDEX;
413 }
414 session->session_state = STATE_CLOSE_ON_EMPTY;
415 VDBG (0, "reset handle 0x%llx, sid %u ", reset_msg->handle, sid);
Florin Coras134a9962018-08-28 11:32:04 -0700416 vcl_send_session_reset_reply (vcl_session_vpp_evt_q (wrk, session),
Florin Coras47c40e22018-11-26 17:01:36 -0800417 wrk->my_client_index, reset_msg->handle, 0);
Florin Corasc9fbd662018-08-24 12:59:56 -0700418 return sid;
419}
420
Florin Coras60116992018-08-27 09:52:18 -0700421static u32
Florin Coras134a9962018-08-28 11:32:04 -0700422vcl_session_bound_handler (vcl_worker_t * wrk, session_bound_msg_t * mp)
Florin Coras60116992018-08-27 09:52:18 -0700423{
424 vcl_session_t *session;
425 u32 sid = mp->context;
426
Florin Coras134a9962018-08-28 11:32:04 -0700427 session = vcl_session_get (wrk, sid);
Florin Coras60116992018-08-27 09:52:18 -0700428 if (mp->retval)
429 {
Florin Corasd85de682018-11-29 17:02:29 -0800430 VERR ("vpp handle 0x%llx, sid %u: bind failed: %U", mp->handle, sid,
431 format_api_error, mp->retval);
Florin Coras60116992018-08-27 09:52:18 -0700432 if (session)
433 {
434 session->session_state = STATE_FAILED;
435 session->vpp_handle = mp->handle;
436 return sid;
437 }
438 else
439 {
440 clib_warning ("[%s] ERROR: vpp handle 0x%llx, sid %u: "
441 "Invalid session index (%u)!",
442 getpid (), mp->handle, sid);
443 return VCL_INVALID_SESSION_INDEX;
444 }
445 }
446
447 session->vpp_handle = mp->handle;
448 session->transport.is_ip4 = mp->lcl_is_ip4;
Dave Barach178cf492018-11-13 16:34:13 -0500449 clib_memcpy_fast (&session->transport.lcl_ip, mp->lcl_ip,
450 sizeof (ip46_address_t));
Florin Coras60116992018-08-27 09:52:18 -0700451 session->transport.lcl_port = mp->lcl_port;
Florin Coras134a9962018-08-28 11:32:04 -0700452 vcl_session_table_add_listener (wrk, mp->handle, sid);
Florin Coras60116992018-08-27 09:52:18 -0700453 session->session_state = STATE_LISTEN;
454
455 if (session->is_dgram)
456 {
457 svm_fifo_t *rx_fifo, *tx_fifo;
458 session->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
459 rx_fifo = uword_to_pointer (mp->rx_fifo, svm_fifo_t *);
460 rx_fifo->client_session_index = sid;
461 tx_fifo = uword_to_pointer (mp->tx_fifo, svm_fifo_t *);
462 tx_fifo->client_session_index = sid;
463 session->rx_fifo = rx_fifo;
464 session->tx_fifo = tx_fifo;
465 }
466
Florin Corasdc2e2512018-12-03 17:47:26 -0800467 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: bind succeeded!",
Florin Coras60116992018-08-27 09:52:18 -0700468 getpid (), mp->handle, sid);
469 return sid;
470}
471
Florin Coras86f04502018-09-12 16:08:01 -0700472static int
473vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e)
Florin Coras54693d22018-07-17 10:46:29 -0700474{
475 session_accepted_msg_t *accepted_msg;
476 session_disconnected_msg_t *disconnected_msg;
477 vcl_session_msg_t *vcl_msg;
478 vcl_session_t *session;
479 u64 handle;
480 u32 sid;
481
482 switch (e->event_type)
483 {
484 case FIFO_EVENT_APP_RX:
Florin Coras86f04502018-09-12 16:08:01 -0700485 case FIFO_EVENT_APP_TX:
486 case SESSION_IO_EVT_CT_RX:
487 case SESSION_IO_EVT_CT_TX:
488 vec_add1 (wrk->unhandled_evts_vector, *e);
Florin Coras54693d22018-07-17 10:46:29 -0700489 break;
490 case SESSION_CTRL_EVT_ACCEPTED:
491 accepted_msg = (session_accepted_msg_t *) e->data;
492 handle = accepted_msg->listener_handle;
Florin Coras134a9962018-08-28 11:32:04 -0700493 session = vcl_session_table_lookup_listener (wrk, handle);
Florin Coras54693d22018-07-17 10:46:29 -0700494 if (!session)
495 {
496 clib_warning ("VCL<%d>: ERROR: couldn't find listen session:"
497 "listener handle %llx", getpid (), handle);
498 break;
499 }
500
501 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
502 vcl_msg->accepted_msg = *accepted_msg;
503 break;
504 case SESSION_CTRL_EVT_CONNECTED:
Florin Coras134a9962018-08-28 11:32:04 -0700505 vcl_session_connected_handler (wrk,
506 (session_connected_msg_t *) e->data);
Florin Coras54693d22018-07-17 10:46:29 -0700507 break;
508 case SESSION_CTRL_EVT_DISCONNECTED:
509 disconnected_msg = (session_disconnected_msg_t *) e->data;
Florin Coras134a9962018-08-28 11:32:04 -0700510 sid = vcl_session_index_from_vpp_handle (wrk, disconnected_msg->handle);
511 session = vcl_session_get (wrk, sid);
Florin Corasc9fbd662018-08-24 12:59:56 -0700512 if (!session)
513 {
514 VDBG (0, "request to disconnect unknown handle 0x%llx",
515 disconnected_msg->handle);
516 break;
517 }
Florin Coras54693d22018-07-17 10:46:29 -0700518 session->session_state = STATE_DISCONNECT;
Florin Coras86f04502018-09-12 16:08:01 -0700519 VDBG (0, "disconnected handle 0x%llx, sid %u", disconnected_msg->handle,
Florin Corasc9fbd662018-08-24 12:59:56 -0700520 sid);
521 break;
522 case SESSION_CTRL_EVT_RESET:
Florin Coras134a9962018-08-28 11:32:04 -0700523 vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
Florin Coras60116992018-08-27 09:52:18 -0700524 break;
525 case SESSION_CTRL_EVT_BOUND:
Florin Coras134a9962018-08-28 11:32:04 -0700526 vcl_session_bound_handler (wrk, (session_bound_msg_t *) e->data);
Florin Coras54693d22018-07-17 10:46:29 -0700527 break;
528 default:
529 clib_warning ("unhandled %u", e->event_type);
530 }
531 return VPPCOM_OK;
532}
533
Florin Coras697faea2018-06-27 17:10:49 -0700534static inline int
535vppcom_wait_for_session_state_change (u32 session_index,
536 session_state_t state,
537 f64 wait_for_time)
538{
Florin Coras134a9962018-08-28 11:32:04 -0700539 vcl_worker_t *wrk = vcl_worker_get_current ();
540 f64 timeout = clib_time_now (&wrk->clib_time) + wait_for_time;
Florin Coras697faea2018-06-27 17:10:49 -0700541 vcl_session_t *volatile session;
Florin Coras54693d22018-07-17 10:46:29 -0700542 svm_msg_q_msg_t msg;
543 session_event_t *e;
Dave Wallace543852a2017-08-03 02:11:34 -0400544
Florin Coras697faea2018-06-27 17:10:49 -0700545 do
Dave Wallace543852a2017-08-03 02:11:34 -0400546 {
Florin Coras134a9962018-08-28 11:32:04 -0700547 session = vcl_session_get (wrk, session_index);
Florin Coras070453d2018-08-24 17:04:27 -0700548 if (PREDICT_FALSE (!session))
Florin Coras697faea2018-06-27 17:10:49 -0700549 {
Florin Coras070453d2018-08-24 17:04:27 -0700550 return VPPCOM_EBADFD;
Florin Coras697faea2018-06-27 17:10:49 -0700551 }
552 if (session->session_state & state)
553 {
Florin Coras697faea2018-06-27 17:10:49 -0700554 return VPPCOM_OK;
555 }
556 if (session->session_state & STATE_FAILED)
557 {
Florin Coras697faea2018-06-27 17:10:49 -0700558 return VPPCOM_ECONNREFUSED;
559 }
Florin Coras54693d22018-07-17 10:46:29 -0700560
Florin Coras134a9962018-08-28 11:32:04 -0700561 if (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0))
Florin Corasdc2e2512018-12-03 17:47:26 -0800562 {
563 usleep (100);
564 continue;
565 }
Florin Coras134a9962018-08-28 11:32:04 -0700566 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
Florin Coras86f04502018-09-12 16:08:01 -0700567 vcl_handle_mq_event (wrk, e);
Florin Coras134a9962018-08-28 11:32:04 -0700568 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Corasdcf55ce2017-11-16 15:32:50 -0800569 }
Florin Coras134a9962018-08-28 11:32:04 -0700570 while (clib_time_now (&wrk->clib_time) < timeout);
Florin Corasdcf55ce2017-11-16 15:32:50 -0800571
Florin Coras697faea2018-06-27 17:10:49 -0700572 VDBG (0, "VCL<%d>: timeout waiting for state 0x%x (%s)", getpid (), state,
573 vppcom_session_state_str (state));
574 vcl_evt (VCL_EVT_SESSION_TIMEOUT, session, session_state);
Dave Wallace543852a2017-08-03 02:11:34 -0400575
Florin Coras697faea2018-06-27 17:10:49 -0700576 return VPPCOM_ETIMEDOUT;
Dave Wallace60caa062017-11-10 17:07:13 -0500577}
578
Florin Coras697faea2018-06-27 17:10:49 -0700579static int
580vppcom_app_session_enable (void)
Dave Wallace543852a2017-08-03 02:11:34 -0400581{
Florin Coras697faea2018-06-27 17:10:49 -0700582 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -0400583
Florin Coras697faea2018-06-27 17:10:49 -0700584 if (vcm->app_state != STATE_APP_ENABLED)
585 {
586 vppcom_send_session_enable_disable (1 /* is_enabled == TRUE */ );
Florin Coras134a9962018-08-28 11:32:04 -0700587 rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
Florin Coras697faea2018-06-27 17:10:49 -0700588 if (PREDICT_FALSE (rv))
589 {
590 VDBG (0, "VCL<%d>: application session enable timed out! "
591 "returning %d (%s)", getpid (), rv, vppcom_retval_str (rv));
592 return rv;
593 }
594 }
595 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400596}
597
Florin Coras697faea2018-06-27 17:10:49 -0700598static int
599vppcom_app_attach (void)
Dave Wallace543852a2017-08-03 02:11:34 -0400600{
Florin Coras697faea2018-06-27 17:10:49 -0700601 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -0400602
Florin Coras697faea2018-06-27 17:10:49 -0700603 vppcom_app_send_attach ();
Florin Coras134a9962018-08-28 11:32:04 -0700604 rv = vcl_wait_for_app_state_change (STATE_APP_ATTACHED);
Florin Coras697faea2018-06-27 17:10:49 -0700605 if (PREDICT_FALSE (rv))
606 {
607 VDBG (0, "VCL<%d>: application attach timed out! returning %d (%s)",
608 getpid (), rv, vppcom_retval_str (rv));
609 return rv;
610 }
Dave Wallace543852a2017-08-03 02:11:34 -0400611
Florin Coras697faea2018-06-27 17:10:49 -0700612 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400613}
614
615static int
Florin Corasab2f6db2018-08-31 14:31:41 -0700616vppcom_session_unbind (u32 session_handle)
Dave Wallace543852a2017-08-03 02:11:34 -0400617{
Florin Coras134a9962018-08-28 11:32:04 -0700618 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -0700619 vcl_session_t *session = 0;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500620 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400621
Florin Corasab2f6db2018-08-31 14:31:41 -0700622 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -0700623 if (!session)
624 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500625
626 vpp_handle = session->vpp_handle;
Florin Coras134a9962018-08-28 11:32:04 -0700627 vcl_session_table_del_listener (wrk, vpp_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500628 session->vpp_handle = ~0;
Florin Coras7e12d942018-06-27 14:32:43 -0700629 session->session_state = STATE_DISCONNECT;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500630
Florin Coras0d427d82018-06-27 03:24:07 -0700631 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending unbind msg! new state"
Florin Corasab2f6db2018-08-31 14:31:41 -0700632 " 0x%x (%s)", getpid (), vpp_handle, session_handle, STATE_DISCONNECT,
Florin Coras0d427d82018-06-27 03:24:07 -0700633 vppcom_session_state_str (STATE_DISCONNECT));
634 vcl_evt (VCL_EVT_UNBIND, session);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500635 vppcom_send_unbind_sock (vpp_handle);
636
Florin Coras070453d2018-08-24 17:04:27 -0700637 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400638}
639
Florin Coras697faea2018-06-27 17:10:49 -0700640static int
Florin Corasab2f6db2018-08-31 14:31:41 -0700641vppcom_session_disconnect (u32 session_handle)
Dave Wallace543852a2017-08-03 02:11:34 -0400642{
Florin Coras134a9962018-08-28 11:32:04 -0700643 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras99368312018-08-02 10:45:44 -0700644 svm_msg_q_t *vpp_evt_q;
Florin Coras7e12d942018-06-27 14:32:43 -0700645 vcl_session_t *session;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500646 session_state_t state;
Florin Coras99368312018-08-02 10:45:44 -0700647 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400648
Florin Corasab2f6db2018-08-31 14:31:41 -0700649 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras21795132018-09-09 09:40:51 -0700650 if (!session)
651 return VPPCOM_EBADFD;
652
Dave Wallace4878cbe2017-11-21 03:45:09 -0500653 vpp_handle = session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -0700654 state = session->session_state;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500655
Florin Coras0d427d82018-06-27 03:24:07 -0700656 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u state 0x%x (%s)", getpid (),
Florin Corasab2f6db2018-08-31 14:31:41 -0700657 vpp_handle, session_handle, state, vppcom_session_state_str (state));
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400658
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800659 if (PREDICT_FALSE (state & STATE_LISTEN))
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400660 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500661 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -0500662 "Cannot disconnect a listen socket!",
Florin Corasab2f6db2018-08-31 14:31:41 -0700663 getpid (), vpp_handle, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -0700664 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500665 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400666
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800667 if (state & STATE_CLOSE_ON_EMPTY)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500668 {
Florin Coras134a9962018-08-28 11:32:04 -0700669 vpp_evt_q = vcl_session_vpp_evt_q (wrk, session);
Florin Coras47c40e22018-11-26 17:01:36 -0800670 vcl_send_session_disconnected_reply (vpp_evt_q, wrk->my_client_index,
Florin Coras99368312018-08-02 10:45:44 -0700671 vpp_handle, 0);
Florin Coras0d427d82018-06-27 03:24:07 -0700672 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect "
Florin Corasab2f6db2018-08-31 14:31:41 -0700673 "REPLY...", getpid (), vpp_handle, session_handle);
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400674 }
675 else
Dave Wallace227867f2017-11-13 21:21:53 -0500676 {
Florin Coras0d427d82018-06-27 03:24:07 -0700677 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect...",
Florin Corasab2f6db2018-08-31 14:31:41 -0700678 getpid (), vpp_handle, session_handle);
679 vppcom_send_disconnect_session (vpp_handle);
Dave Wallace227867f2017-11-13 21:21:53 -0500680 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400681
Florin Coras070453d2018-08-24 17:04:27 -0700682 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400683}
684
Florin Coras053a0e42018-11-13 15:52:38 -0800685static void
686vcl_cleanup_bapi (void)
687{
Florin Coras47c40e22018-11-26 17:01:36 -0800688 socket_client_main_t *scm = &socket_client_main;
Florin Coras053a0e42018-11-13 15:52:38 -0800689 api_main_t *am = &api_main;
690
691 am->my_client_index = ~0;
692 am->my_registration = 0;
693 am->vl_input_queue = 0;
694 am->msg_index_by_name_and_crc = 0;
Florin Coras47c40e22018-11-26 17:01:36 -0800695 scm->socket_fd = 0;
Florin Coras053a0e42018-11-13 15:52:38 -0800696
697 vl_client_api_unmap ();
698}
699
Florin Coras01f3f892018-12-02 12:45:53 -0800700static void
701vcl_cleanup_forked_child (vcl_worker_t * wrk, vcl_worker_t * child_wrk)
702{
703 vcl_worker_t *sub_child;
704 int tries = 0;
705
706 if (child_wrk->forked_child != ~0)
707 {
708 sub_child = vcl_worker_get_if_valid (child_wrk->forked_child);
709 if (sub_child)
710 {
711 /* Wait a bit, maybe the process is going away */
712 while (kill (sub_child->current_pid, 0) >= 0 && tries++ < 50)
713 usleep (1e3);
714 if (kill (sub_child->current_pid, 0) < 0)
715 vcl_cleanup_forked_child (child_wrk, sub_child);
716 }
717 }
718 vcl_worker_cleanup (child_wrk, 1 /* notify vpp */ );
719 VDBG (0, "Cleaned up wrk %u", child_wrk->wrk_index);
720 wrk->forked_child = ~0;
721}
722
723static struct sigaction old_sa;
724
725static void
726vcl_intercept_sigchld_handler (int signum, siginfo_t * si, void *uc)
727{
728 vcl_worker_t *wrk, *child_wrk;
729
730 if (vcl_get_worker_index () == ~0)
731 return;
732
733 sigaction (SIGCHLD, &old_sa, 0);
734
735 wrk = vcl_worker_get_current ();
736 if (wrk->forked_child == ~0)
737 return;
738
739 child_wrk = vcl_worker_get_if_valid (wrk->forked_child);
740 if (si->si_pid != child_wrk->current_pid)
741 {
742 VDBG (0, "unexpected child pid %u", si->si_pid);
743 return;
744 }
745 if (child_wrk)
746 vcl_cleanup_forked_child (wrk, child_wrk);
747
748 if (old_sa.sa_flags & SA_SIGINFO)
749 {
750 void (*fn) (int, siginfo_t *, void *) = old_sa.sa_sigaction;
751 fn (signum, si, uc);
752 }
753 else
754 {
755 void (*fn) (int) = old_sa.sa_handler;
756 if (fn)
757 fn (signum);
758 }
759}
760
761static void
762vcl_incercept_sigchld ()
763{
764 struct sigaction sa;
765 clib_memset (&sa, 0, sizeof (sa));
766 sa.sa_sigaction = vcl_intercept_sigchld_handler;
767 sa.sa_flags = SA_SIGINFO;
768 if (sigaction (SIGCHLD, &sa, &old_sa))
769 {
770 VERR ("couldn't intercept sigchld");
771 exit (-1);
772 }
773}
774
775static void
776vcl_app_pre_fork (void)
777{
778 vcl_incercept_sigchld ();
779}
780
781static void
Florin Coras053a0e42018-11-13 15:52:38 -0800782vcl_app_fork_child_handler (void)
783{
Florin Coras01f3f892018-12-02 12:45:53 -0800784 int rv, parent_wrk_index;
785 vcl_worker_t *parent_wrk;
Florin Coras053a0e42018-11-13 15:52:38 -0800786 u8 *child_name;
Florin Coras053a0e42018-11-13 15:52:38 -0800787
Florin Coras01f3f892018-12-02 12:45:53 -0800788 parent_wrk_index = vcl_get_worker_index ();
789 VDBG (0, "initializing forked child with parent wrk %u", parent_wrk_index);
Florin Coras053a0e42018-11-13 15:52:38 -0800790
Florin Coras47c40e22018-11-26 17:01:36 -0800791 /*
792 * Allocate worker
793 */
Florin Coras47c40e22018-11-26 17:01:36 -0800794 vcl_set_worker_index (~0);
795 if (!vcl_worker_alloc_and_init ())
796 VERR ("couldn't allocate new worker");
797
798 /*
799 * Attach to binary api
800 */
801 child_name = format (0, "%v-child-%u%c", vcm->app_name, getpid (), 0);
Florin Coras053a0e42018-11-13 15:52:38 -0800802 vcl_cleanup_bapi ();
803 vppcom_api_hookup ();
804 vcm->app_state = STATE_APP_START;
805 rv = vppcom_connect_to_vpp ((char *) child_name);
806 vec_free (child_name);
807 if (rv)
808 {
809 VERR ("couldn't connect to VPP!");
810 return;
811 }
812
Florin Coras47c40e22018-11-26 17:01:36 -0800813 /*
814 * Register worker with vpp and share sessions
815 */
816 vcl_worker_register_with_vpp ();
Florin Coras01f3f892018-12-02 12:45:53 -0800817 parent_wrk = vcl_worker_get (parent_wrk_index);
Florin Coras47c40e22018-11-26 17:01:36 -0800818 vcl_worker_share_sessions (parent_wrk);
Florin Coras01f3f892018-12-02 12:45:53 -0800819 parent_wrk->forked_child = vcl_get_worker_index ();
Florin Coras47c40e22018-11-26 17:01:36 -0800820
Florin Coras053a0e42018-11-13 15:52:38 -0800821 VDBG (0, "forked child main worker initialized");
Florin Coras47c40e22018-11-26 17:01:36 -0800822 vcm->forking = 0;
823}
824
Florin Coras01f3f892018-12-02 12:45:53 -0800825static void
Florin Coras47c40e22018-11-26 17:01:36 -0800826vcl_app_fork_parent_handler (void)
827{
828 vcm->forking = 1;
Florin Coras47c40e22018-11-26 17:01:36 -0800829 while (vcm->forking)
830 ;
Florin Coras053a0e42018-11-13 15:52:38 -0800831}
832
Florin Coras940f78f2018-11-30 12:11:20 -0800833/**
834 * Handle app exit
835 *
836 * Notify vpp of the disconnect and mark the worker as free. If we're the
837 * last worker, do a full cleanup otherwise, since we're probably a forked
838 * child, avoid syscalls as much as possible. We might've lost privileges.
839 */
840void
841vppcom_app_exit (void)
842{
843 if (!pool_elts (vcm->workers))
844 return;
Florin Coras01f3f892018-12-02 12:45:53 -0800845 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
846 vcl_set_worker_index (~0);
Florin Coras940f78f2018-11-30 12:11:20 -0800847 vcl_elog_stop (vcm);
848 if (vec_len (vcm->workers) == 1)
849 vl_client_disconnect_from_vlib ();
850 else
851 vl_client_send_disconnect ();
852}
853
Dave Wallace543852a2017-08-03 02:11:34 -0400854/*
855 * VPPCOM Public API functions
856 */
857int
858vppcom_app_create (char *app_name)
859{
Dave Wallace543852a2017-08-03 02:11:34 -0400860 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
Dave Wallace543852a2017-08-03 02:11:34 -0400861 int rv;
862
Florin Coras47c40e22018-11-26 17:01:36 -0800863 if (vcm->is_init)
Dave Wallace543852a2017-08-03 02:11:34 -0400864 {
Florin Corasdc2e2512018-12-03 17:47:26 -0800865 clib_warning ("vcl<%u> already initialized", getpid ());
Florin Coras47c40e22018-11-26 17:01:36 -0800866 return -1;
Dave Wallace543852a2017-08-03 02:11:34 -0400867 }
868
Florin Coras47c40e22018-11-26 17:01:36 -0800869 vcm->is_init = 1;
870 vppcom_cfg (&vcm->cfg);
871 vcl_cfg = &vcm->cfg;
872
873 vcm->main_cpu = pthread_self ();
874 vcm->main_pid = getpid ();
875 vcm->app_name = format (0, "%s", app_name);
876 vppcom_init_error_string_table ();
Florin Corasadc74d72018-12-02 13:36:00 -0800877 svm_fifo_segment_main_init (&vcm->segment_main, vcl_cfg->segment_baseva,
Florin Coras47c40e22018-11-26 17:01:36 -0800878 20 /* timeout in secs */ );
879 pool_alloc (vcm->workers, vcl_cfg->max_workers);
880 clib_spinlock_init (&vcm->workers_lock);
Florin Corasd85de682018-11-29 17:02:29 -0800881 clib_rwlock_init (&vcm->segment_table_lock);
Florin Coras01f3f892018-12-02 12:45:53 -0800882 pthread_atfork (vcl_app_pre_fork, vcl_app_fork_parent_handler,
Florin Coras47c40e22018-11-26 17:01:36 -0800883 vcl_app_fork_child_handler);
Florin Coras940f78f2018-11-30 12:11:20 -0800884 atexit (vppcom_app_exit);
Florin Coras47c40e22018-11-26 17:01:36 -0800885
886 /* Allocate default worker */
887 vcl_worker_alloc_and_init ();
888
889 /* API hookup and connect to VPP */
890 vppcom_api_hookup ();
891 vcl_elog_init (vcm);
892 vcm->app_state = STATE_APP_START;
893 rv = vppcom_connect_to_vpp (app_name);
894 if (rv)
Dave Wallace543852a2017-08-03 02:11:34 -0400895 {
Florin Coras47c40e22018-11-26 17:01:36 -0800896 VERR ("couldn't connect to VPP!");
897 return rv;
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400898 }
Florin Coras47c40e22018-11-26 17:01:36 -0800899 VDBG (0, "sending session enable");
900 rv = vppcom_app_session_enable ();
901 if (rv)
902 {
903 VERR ("vppcom_app_session_enable() failed!");
904 return rv;
905 }
906
907 VDBG (0, "sending app attach");
908 rv = vppcom_app_attach ();
909 if (rv)
910 {
911 VERR ("vppcom_app_attach() failed!");
912 return rv;
913 }
914
915 VDBG (0, "app_name '%s', my_client_index %d (0x%x)", app_name,
916 vcm->workers[0].my_client_index, vcm->workers[0].my_client_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400917
918 return VPPCOM_OK;
919}
920
921void
922vppcom_app_destroy (void)
923{
Dave Wallace543852a2017-08-03 02:11:34 -0400924 int rv;
Dave Wallacede910062018-03-20 09:22:13 -0400925 f64 orig_app_timeout;
Dave Wallace543852a2017-08-03 02:11:34 -0400926
Florin Coras940f78f2018-11-30 12:11:20 -0800927 if (!pool_elts (vcm->workers))
928 return;
929
Florin Coras0d427d82018-06-27 03:24:07 -0700930 vcl_evt (VCL_EVT_DETACH, vcm);
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -0800931
Florin Coras940f78f2018-11-30 12:11:20 -0800932 if (pool_elts (vcm->workers) == 1)
Florin Coras47c40e22018-11-26 17:01:36 -0800933 {
934 vppcom_app_send_detach ();
935 orig_app_timeout = vcm->cfg.app_timeout;
936 vcm->cfg.app_timeout = 2.0;
937 rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
938 vcm->cfg.app_timeout = orig_app_timeout;
939 if (PREDICT_FALSE (rv))
940 VDBG (0, "application detach timed out! returning %d (%s)", rv,
941 vppcom_retval_str (rv));
Florin Coras940f78f2018-11-30 12:11:20 -0800942 vec_free (vcm->app_name);
Florin Coras01f3f892018-12-02 12:45:53 -0800943 vcl_worker_cleanup (vcl_worker_get_current (), 0 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -0800944 }
945 else
946 {
Florin Coras01f3f892018-12-02 12:45:53 -0800947 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -0800948 }
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -0800949
Florin Coras01f3f892018-12-02 12:45:53 -0800950 vcl_set_worker_index (~0);
Florin Coras0d427d82018-06-27 03:24:07 -0700951 vcl_elog_stop (vcm);
Dave Wallace543852a2017-08-03 02:11:34 -0400952 vl_client_disconnect_from_vlib ();
Dave Wallace543852a2017-08-03 02:11:34 -0400953}
954
955int
Dave Wallacec04cbf12018-02-07 18:14:02 -0500956vppcom_session_create (u8 proto, u8 is_nonblocking)
Dave Wallace543852a2017-08-03 02:11:34 -0400957{
Florin Coras134a9962018-08-28 11:32:04 -0700958 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -0700959 vcl_session_t *session;
Dave Wallace543852a2017-08-03 02:11:34 -0400960
Florin Coras134a9962018-08-28 11:32:04 -0700961 session = vcl_session_alloc (wrk);
Dave Wallace543852a2017-08-03 02:11:34 -0400962
Florin Coras7e12d942018-06-27 14:32:43 -0700963 session->session_type = proto;
964 session->session_state = STATE_START;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500965 session->vpp_handle = ~0;
Florin Coras460dce62018-07-27 05:45:06 -0700966 session->is_dgram = proto == VPPCOM_PROTO_UDP;
Dave Wallace543852a2017-08-03 02:11:34 -0400967
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800968 if (is_nonblocking)
969 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
Dave Wallace543852a2017-08-03 02:11:34 -0400970
Florin Coras7e12d942018-06-27 14:32:43 -0700971 vcl_evt (VCL_EVT_CREATE, session, session_type, session->session_state,
972 is_nonblocking, session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -0800973
Florin Coras053a0e42018-11-13 15:52:38 -0800974 VDBG (0, "created sid %u", session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -0800975
Florin Coras134a9962018-08-28 11:32:04 -0700976 return vcl_session_handle (session);
Dave Wallace543852a2017-08-03 02:11:34 -0400977}
978
979int
Florin Coras134a9962018-08-28 11:32:04 -0700980vppcom_session_close (uint32_t session_handle)
Dave Wallace543852a2017-08-03 02:11:34 -0400981{
Florin Coras134a9962018-08-28 11:32:04 -0700982 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras47c40e22018-11-26 17:01:36 -0800983 u8 is_vep, do_disconnect = 1;
Florin Coras7e12d942018-06-27 14:32:43 -0700984 vcl_session_t *session = 0;
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400985 session_state_t state;
Florin Coras134a9962018-08-28 11:32:04 -0700986 u32 next_sh, vep_sh;
987 int rv = VPPCOM_OK;
988 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400989
Florin Coras134a9962018-08-28 11:32:04 -0700990 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -0700991 if (!session)
992 return VPPCOM_EBADFD;
993
Florin Coras47c40e22018-11-26 17:01:36 -0800994 if (session->shared_index != ~0)
995 do_disconnect = vcl_worker_unshare_session (wrk, session);
996
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400997 is_vep = session->is_vep;
Florin Coras134a9962018-08-28 11:32:04 -0700998 next_sh = session->vep.next_sh;
999 vep_sh = session->vep.vep_sh;
Florin Coras7e12d942018-06-27 14:32:43 -07001000 state = session->session_state;
Dave Wallaceee45d412017-11-24 21:44:06 -05001001 vpp_handle = session->vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -04001002
Florin Coras47c40e22018-11-26 17:01:36 -08001003 VDBG (0, "Closing session handle %u vpp handle %u", session_handle,
1004 vpp_handle);
Dave Wallace543852a2017-08-03 02:11:34 -04001005
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001006 if (is_vep)
Dave Wallace543852a2017-08-03 02:11:34 -04001007 {
Florin Coras134a9962018-08-28 11:32:04 -07001008 while (next_sh != ~0)
Dave Wallace19481612017-09-15 18:47:44 -04001009 {
Florin Coras134a9962018-08-28 11:32:04 -07001010 rv = vppcom_epoll_ctl (session_handle, EPOLL_CTL_DEL, next_sh, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001011 if (PREDICT_FALSE (rv < 0))
Florin Coras47c40e22018-11-26 17:01:36 -08001012 VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u"
1013 " failed! rv %d (%s)", vpp_handle, next_sh, vep_sh, rv,
1014 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001015
Florin Coras134a9962018-08-28 11:32:04 -07001016 next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001017 }
1018 }
1019 else
1020 {
Florin Coras47c40e22018-11-26 17:01:36 -08001021 if (session->is_vep_session)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001022 {
Florin Coras134a9962018-08-28 11:32:04 -07001023 rv = vppcom_epoll_ctl (vep_sh, EPOLL_CTL_DEL, session_handle, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001024 if (rv < 0)
Florin Coras47c40e22018-11-26 17:01:36 -08001025 VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u "
1026 "failed! rv %d (%s)", vpp_handle, session_handle, vep_sh,
1027 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001028 }
1029
Florin Coras47c40e22018-11-26 17:01:36 -08001030 if (!do_disconnect)
1031 goto cleanup;
1032
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001033 if (state & STATE_LISTEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001034 {
Florin Coras134a9962018-08-28 11:32:04 -07001035 rv = vppcom_session_unbind (session_handle);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001036 if (PREDICT_FALSE (rv < 0))
Florin Coras47c40e22018-11-26 17:01:36 -08001037 VDBG (0, "vpp handle 0x%llx, sid %u: listener unbind failed! "
1038 "rv %d (%s)", vpp_handle, session_handle, rv,
1039 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001040 }
Florin Coras070453d2018-08-24 17:04:27 -07001041 else if (state & STATE_OPEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001042 {
Florin Coras134a9962018-08-28 11:32:04 -07001043 rv = vppcom_session_disconnect (session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001044 if (PREDICT_FALSE (rv < 0))
Dave Wallace048b1d62018-01-03 22:24:41 -05001045 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001046 "session disconnect failed! rv %d (%s)",
Florin Coras134a9962018-08-28 11:32:04 -07001047 getpid (), vpp_handle, session_handle,
Dave Wallaceee45d412017-11-24 21:44:06 -05001048 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001049 }
Dave Wallace19481612017-09-15 18:47:44 -04001050 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001051
Florin Coras47c40e22018-11-26 17:01:36 -08001052cleanup:
1053
Florin Coras99368312018-08-02 10:45:44 -07001054 if (vcl_session_is_ct (session))
1055 {
1056 vcl_cut_through_registration_t *ctr;
1057 uword mq_addr;
1058
1059 mq_addr = pointer_to_uword (session->our_evt_q);
Florin Coras134a9962018-08-28 11:32:04 -07001060 ctr = vcl_ct_registration_lock_and_lookup (wrk, mq_addr);
Florin Coras99368312018-08-02 10:45:44 -07001061 ASSERT (ctr);
1062 if (ctr->epoll_evt_conn_index != ~0)
Florin Coras134a9962018-08-28 11:32:04 -07001063 vcl_mq_epoll_del_evfd (wrk, ctr->epoll_evt_conn_index);
Florin Coras99368312018-08-02 10:45:44 -07001064 VDBG (0, "Removing ct registration %u",
Florin Coras134a9962018-08-28 11:32:04 -07001065 vcl_ct_registration_index (wrk, ctr));
1066 vcl_ct_registration_del (wrk, ctr);
1067 vcl_ct_registration_lookup_del (wrk, mq_addr);
1068 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07001069 }
Florin Coras54693d22018-07-17 10:46:29 -07001070
Dave Wallaceee45d412017-11-24 21:44:06 -05001071 if (vpp_handle != ~0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001072 {
Florin Coras134a9962018-08-28 11:32:04 -07001073 vcl_session_table_del_vpp_handle (wrk, vpp_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001074 }
Florin Coras134a9962018-08-28 11:32:04 -07001075 vcl_session_free (wrk, session);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001076
Florin Coras47c40e22018-11-26 17:01:36 -08001077 VDBG (0, "session handle %u vpp handle %u removed", session_handle,
1078 vpp_handle);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001079
Florin Coras0d427d82018-06-27 03:24:07 -07001080 vcl_evt (VCL_EVT_CLOSE, session, rv);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001081
Dave Wallace543852a2017-08-03 02:11:34 -04001082 return rv;
1083}
1084
1085int
Florin Coras134a9962018-08-28 11:32:04 -07001086vppcom_session_bind (uint32_t session_handle, vppcom_endpt_t * ep)
Dave Wallace543852a2017-08-03 02:11:34 -04001087{
Florin Coras134a9962018-08-28 11:32:04 -07001088 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001089 vcl_session_t *session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001090
1091 if (!ep || !ep->ip)
1092 return VPPCOM_EINVAL;
1093
Florin Coras134a9962018-08-28 11:32:04 -07001094 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001095 if (!session)
1096 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001097
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001098 if (session->is_vep)
1099 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001100 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
Florin Coras134a9962018-08-28 11:32:04 -07001101 "bind to an epoll session!", getpid (), session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001102 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001103 }
1104
Florin Coras7e12d942018-06-27 14:32:43 -07001105 session->transport.is_ip4 = ep->is_ip4;
Florin Coras54693d22018-07-17 10:46:29 -07001106 if (ep->is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001107 clib_memcpy_fast (&session->transport.lcl_ip.ip4, ep->ip,
1108 sizeof (ip4_address_t));
Florin Coras54693d22018-07-17 10:46:29 -07001109 else
Dave Barach178cf492018-11-13 16:34:13 -05001110 clib_memcpy_fast (&session->transport.lcl_ip.ip6, ep->ip,
1111 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001112 session->transport.lcl_port = ep->port;
Stevenac1f96d2017-10-24 16:03:58 -07001113
Florin Coras0d427d82018-06-27 03:24:07 -07001114 VDBG (0, "VCL<%d>: sid %u: binding to local %s address %U port %u, "
Florin Coras134a9962018-08-28 11:32:04 -07001115 "proto %s", getpid (), session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001116 session->transport.is_ip4 ? "IPv4" : "IPv6",
1117 format_ip46_address, &session->transport.lcl_ip,
1118 session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
1119 clib_net_to_host_u16 (session->transport.lcl_port),
1120 session->session_type ? "UDP" : "TCP");
Florin Coras0d427d82018-06-27 03:24:07 -07001121 vcl_evt (VCL_EVT_BIND, session);
Florin Coras460dce62018-07-27 05:45:06 -07001122
1123 if (session->session_type == VPPCOM_PROTO_UDP)
Florin Coras134a9962018-08-28 11:32:04 -07001124 vppcom_session_listen (session_handle, 10);
Florin Coras460dce62018-07-27 05:45:06 -07001125
Florin Coras070453d2018-08-24 17:04:27 -07001126 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001127}
1128
1129int
Florin Coras134a9962018-08-28 11:32:04 -07001130vppcom_session_listen (uint32_t listen_sh, uint32_t q_len)
Dave Wallace543852a2017-08-03 02:11:34 -04001131{
Florin Coras134a9962018-08-28 11:32:04 -07001132 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001133 vcl_session_t *listen_session = 0;
Dave Wallaceee45d412017-11-24 21:44:06 -05001134 u64 listen_vpp_handle;
Florin Coras070453d2018-08-24 17:04:27 -07001135 int rv;
1136
Florin Coras134a9962018-08-28 11:32:04 -07001137 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras070453d2018-08-24 17:04:27 -07001138 if (!listen_session)
1139 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001140
Keith Burns (alagalah)aba98de2018-02-22 03:23:40 -08001141 if (q_len == 0 || q_len == ~0)
1142 q_len = vcm->cfg.listen_queue_size;
1143
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001144 if (listen_session->is_vep)
1145 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001146 clib_warning ("VCL<%d>: ERROR: sid %u: cannot listen on an "
Florin Coras134a9962018-08-28 11:32:04 -07001147 "epoll session!", getpid (), listen_sh);
Florin Coras070453d2018-08-24 17:04:27 -07001148 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001149 }
1150
Dave Wallaceee45d412017-11-24 21:44:06 -05001151 listen_vpp_handle = listen_session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -07001152 if (listen_session->session_state & STATE_LISTEN)
Dave Wallacee695cb42017-11-02 22:04:42 -04001153 {
Florin Coras0d427d82018-06-27 03:24:07 -07001154 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: already in listen state!",
Florin Coras134a9962018-08-28 11:32:04 -07001155 getpid (), listen_vpp_handle, listen_sh);
Florin Coras070453d2018-08-24 17:04:27 -07001156 return VPPCOM_OK;
Dave Wallacee695cb42017-11-02 22:04:42 -04001157 }
1158
Florin Coras0d427d82018-06-27 03:24:07 -07001159 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: sending VPP bind+listen "
Florin Coras134a9962018-08-28 11:32:04 -07001160 "request...", getpid (), listen_vpp_handle, listen_sh);
Dave Wallace543852a2017-08-03 02:11:34 -04001161
Florin Coras070453d2018-08-24 17:04:27 -07001162 /*
1163 * Send listen request to vpp and wait for reply
1164 */
Florin Coras134a9962018-08-28 11:32:04 -07001165 vppcom_send_bind_sock (listen_session);
1166 rv = vppcom_wait_for_session_state_change (listen_session->session_index,
1167 STATE_LISTEN,
1168 vcm->cfg.session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001169
Florin Coras070453d2018-08-24 17:04:27 -07001170 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001171 {
Florin Coras134a9962018-08-28 11:32:04 -07001172 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras0d427d82018-06-27 03:24:07 -07001173 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: bind+listen failed! "
1174 "returning %d (%s)", getpid (), listen_session->vpp_handle,
Florin Coras134a9962018-08-28 11:32:04 -07001175 listen_sh, rv, vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001176 return rv;
Dave Wallaceee45d412017-11-24 21:44:06 -05001177 }
1178
Florin Coras070453d2018-08-24 17:04:27 -07001179 return VPPCOM_OK;
Keith Burns (alagalah)0d2b0d52018-03-06 15:55:22 -08001180}
1181
Florin Coras134a9962018-08-28 11:32:04 -07001182static int
1183validate_args_session_accept_ (vcl_worker_t * wrk,
1184 vcl_session_t * listen_session)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001185{
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001186 /* Input validation - expects spinlock on sessions_lockp */
1187 if (listen_session->is_vep)
1188 {
1189 clib_warning ("VCL<%d>: ERROR: sid %u: cannot accept on an "
Florin Coras134a9962018-08-28 11:32:04 -07001190 "epoll session!", getpid (),
1191 listen_session->session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001192 return VPPCOM_EBADFD;
1193 }
1194
Florin Coras7e12d942018-06-27 14:32:43 -07001195 if (listen_session->session_state != STATE_LISTEN)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001196 {
1197 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
1198 "not in listen state! state 0x%x (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001199 listen_session->vpp_handle, listen_session->session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001200 listen_session->session_state,
1201 vppcom_session_state_str (listen_session->session_state));
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001202 return VPPCOM_EBADFD;
1203 }
1204 return VPPCOM_OK;
1205}
1206
1207int
Florin Coras134a9962018-08-28 11:32:04 -07001208vppcom_session_accept (uint32_t listen_session_handle, vppcom_endpt_t * ep,
Dave Wallace048b1d62018-01-03 22:24:41 -05001209 uint32_t flags)
Dave Wallace543852a2017-08-03 02:11:34 -04001210{
Florin Coras134a9962018-08-28 11:32:04 -07001211 u32 client_session_index = ~0, listen_session_index;
1212 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001213 session_accepted_msg_t accepted_msg;
Florin Coras7e12d942018-06-27 14:32:43 -07001214 vcl_session_t *listen_session = 0;
1215 vcl_session_t *client_session = 0;
Florin Coras54693d22018-07-17 10:46:29 -07001216 svm_msg_q_t *vpp_evt_q;
1217 vcl_session_msg_t *evt;
Dave Wallaceee45d412017-11-24 21:44:06 -05001218 u64 listen_vpp_handle;
Florin Coras54693d22018-07-17 10:46:29 -07001219 svm_msg_q_msg_t msg;
1220 session_event_t *e;
1221 u8 is_nonblocking;
1222 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001223
Florin Coras134a9962018-08-28 11:32:04 -07001224 listen_session = vcl_session_get_w_handle (wrk, listen_session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001225 if (!listen_session)
1226 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001227
Florin Coras134a9962018-08-28 11:32:04 -07001228 listen_session_index = listen_session->session_index;
1229 if ((rv = validate_args_session_accept_ (wrk, listen_session)))
Florin Coras070453d2018-08-24 17:04:27 -07001230 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001231
Florin Coras54693d22018-07-17 10:46:29 -07001232 if (clib_fifo_elts (listen_session->accept_evts_fifo))
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001233 {
Florin Coras54693d22018-07-17 10:46:29 -07001234 clib_fifo_sub2 (listen_session->accept_evts_fifo, evt);
1235 accepted_msg = evt->accepted_msg;
1236 goto handle;
1237 }
1238
1239 is_nonblocking = VCL_SESS_ATTR_TEST (listen_session->attr,
1240 VCL_SESS_ATTR_NONBLOCK);
Florin Coras134a9962018-08-28 11:32:04 -07001241 if (svm_msg_q_is_empty (wrk->app_event_queue) && is_nonblocking)
Florin Coras54693d22018-07-17 10:46:29 -07001242 return VPPCOM_EAGAIN;
1243
1244 while (1)
1245 {
Florin Coras134a9962018-08-28 11:32:04 -07001246 if (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_WAIT, 0))
Florin Coras54693d22018-07-17 10:46:29 -07001247 return VPPCOM_EAGAIN;
1248
Florin Coras134a9962018-08-28 11:32:04 -07001249 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001250 if (e->event_type != SESSION_CTRL_EVT_ACCEPTED)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001251 {
Florin Coras54693d22018-07-17 10:46:29 -07001252 clib_warning ("discarded event: %u", e->event_type);
Florin Coras134a9962018-08-28 11:32:04 -07001253 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001254 continue;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001255 }
Dave Barach178cf492018-11-13 16:34:13 -05001256 clib_memcpy_fast (&accepted_msg, e->data, sizeof (accepted_msg));
Florin Coras134a9962018-08-28 11:32:04 -07001257 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001258 break;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001259 }
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001260
Florin Coras54693d22018-07-17 10:46:29 -07001261handle:
Keith Burns (alagalah)00f44cc2018-03-07 09:26:38 -08001262
Florin Coras134a9962018-08-28 11:32:04 -07001263 client_session_index = vcl_session_accepted_handler (wrk, &accepted_msg);
1264 listen_session = vcl_session_get (wrk, listen_session_index);
1265 client_session = vcl_session_get (wrk, client_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001266
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001267 if (flags & O_NONBLOCK)
1268 VCL_SESS_ATTR_SET (client_session->attr, VCL_SESS_ATTR_NONBLOCK);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001269
Florin Coras54693d22018-07-17 10:46:29 -07001270 listen_vpp_handle = listen_session->vpp_handle;
Florin Corasdc2e2512018-12-03 17:47:26 -08001271 VDBG (0, "vpp handle 0x%llx, sid %u: Got a client request! "
Florin Coras0d427d82018-06-27 03:24:07 -07001272 "vpp handle 0x%llx, sid %u, flags %d, is_nonblocking %u",
Florin Corasdc2e2512018-12-03 17:47:26 -08001273 listen_vpp_handle, listen_session_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001274 client_session->vpp_handle, client_session_index,
1275 flags, VCL_SESS_ATTR_TEST (client_session->attr,
1276 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace543852a2017-08-03 02:11:34 -04001277
Dave Wallace048b1d62018-01-03 22:24:41 -05001278 if (ep)
1279 {
Florin Coras7e12d942018-06-27 14:32:43 -07001280 ep->is_ip4 = client_session->transport.is_ip4;
1281 ep->port = client_session->transport.rmt_port;
1282 if (client_session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001283 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip4,
1284 sizeof (ip4_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001285 else
Dave Barach178cf492018-11-13 16:34:13 -05001286 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip6,
1287 sizeof (ip6_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001288 }
Dave Wallace60caa062017-11-10 17:07:13 -05001289
Florin Coras54693d22018-07-17 10:46:29 -07001290 if (accepted_msg.server_event_queue_address)
1291 vpp_evt_q = uword_to_pointer (accepted_msg.vpp_event_queue_address,
1292 svm_msg_q_t *);
1293 else
1294 vpp_evt_q = client_session->vpp_evt_q;
Florin Coras99368312018-08-02 10:45:44 -07001295
Florin Coras54693d22018-07-17 10:46:29 -07001296 vcl_send_session_accepted_reply (vpp_evt_q, client_session->client_context,
1297 client_session->vpp_handle, 0);
Dave Wallace60caa062017-11-10 17:07:13 -05001298
Florin Corasdc2e2512018-12-03 17:47:26 -08001299 VDBG (0, "vpp handle 0x%llx, sid %u: accepted vpp handle 0x%llx, "
Florin Coras54693d22018-07-17 10:46:29 -07001300 "sid %u connection from peer %s address %U port %u to local %s "
Florin Corasdc2e2512018-12-03 17:47:26 -08001301 "address %U port %u", listen_vpp_handle,
Florin Coras134a9962018-08-28 11:32:04 -07001302 listen_session_handle, client_session->vpp_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001303 client_session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001304 client_session->transport.is_ip4 ? "IPv4" : "IPv6",
1305 format_ip46_address, &client_session->transport.rmt_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001306 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001307 clib_net_to_host_u16 (client_session->transport.rmt_port),
1308 client_session->transport.is_ip4 ? "IPv4" : "IPv6",
1309 format_ip46_address, &client_session->transport.lcl_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001310 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001311 clib_net_to_host_u16 (client_session->transport.lcl_port));
Florin Coras0d427d82018-06-27 03:24:07 -07001312 vcl_evt (VCL_EVT_ACCEPT, client_session, listen_session,
1313 client_session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001314
Florin Corasab2f6db2018-08-31 14:31:41 -07001315 return vcl_session_handle (client_session);
Dave Wallace543852a2017-08-03 02:11:34 -04001316}
1317
1318int
Florin Coras134a9962018-08-28 11:32:04 -07001319vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep)
Dave Wallace543852a2017-08-03 02:11:34 -04001320{
Florin Coras134a9962018-08-28 11:32:04 -07001321 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001322 vcl_session_t *session = 0;
Florin Coras134a9962018-08-28 11:32:04 -07001323 u32 session_index;
Florin Coras070453d2018-08-24 17:04:27 -07001324 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001325
Florin Coras134a9962018-08-28 11:32:04 -07001326 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001327 if (!session)
1328 return VPPCOM_EBADFD;
Florin Coras134a9962018-08-28 11:32:04 -07001329 session_index = session->session_index;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001330
1331 if (PREDICT_FALSE (session->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001332 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001333 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
Florin Coras134a9962018-08-28 11:32:04 -07001334 "connect on an epoll session!", getpid (),
1335 session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001336 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001337 }
1338
Florin Coras7e12d942018-06-27 14:32:43 -07001339 if (PREDICT_FALSE (session->session_state & CLIENT_STATE_OPEN))
Dave Wallace543852a2017-08-03 02:11:34 -04001340 {
Florin Coras0d427d82018-06-27 03:24:07 -07001341 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: session already "
1342 "connected to %s %U port %d proto %s, state 0x%x (%s)",
Florin Coras134a9962018-08-28 11:32:04 -07001343 getpid (), session->vpp_handle, session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001344 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001345 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001346 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001347 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001348 clib_net_to_host_u16 (session->transport.rmt_port),
1349 session->session_type ? "UDP" : "TCP", session->session_state,
1350 vppcom_session_state_str (session->session_state));
Florin Coras070453d2018-08-24 17:04:27 -07001351 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001352 }
1353
Florin Coras7e12d942018-06-27 14:32:43 -07001354 session->transport.is_ip4 = server_ep->is_ip4;
1355 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001356 clib_memcpy_fast (&session->transport.rmt_ip.ip4, server_ep->ip,
1357 sizeof (ip4_address_t));
Dave Wallaced239f8d2018-06-19 13:37:30 -04001358 else
Dave Barach178cf492018-11-13 16:34:13 -05001359 clib_memcpy_fast (&session->transport.rmt_ip.ip6, server_ep->ip,
1360 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001361 session->transport.rmt_port = server_ep->port;
Dave Wallace543852a2017-08-03 02:11:34 -04001362
Florin Coras0d427d82018-06-27 03:24:07 -07001363 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connecting to server %s %U "
1364 "port %d proto %s",
Florin Coras134a9962018-08-28 11:32:04 -07001365 getpid (), session->vpp_handle, session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001366 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001367 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001368 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001369 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001370 clib_net_to_host_u16 (session->transport.rmt_port),
1371 session->session_type ? "UDP" : "TCP");
Dave Wallace543852a2017-08-03 02:11:34 -04001372
Florin Coras070453d2018-08-24 17:04:27 -07001373 /*
1374 * Send connect request and wait for reply from vpp
1375 */
Florin Coras134a9962018-08-28 11:32:04 -07001376 vppcom_send_connect_sock (session);
Florin Coras070453d2018-08-24 17:04:27 -07001377 rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
1378 vcm->cfg.session_timeout);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001379
Florin Coras134a9962018-08-28 11:32:04 -07001380 session = vcl_session_get (wrk, session_index);
Dave Wallace7876d392017-10-19 03:53:57 -04001381
Florin Coras070453d2018-08-24 17:04:27 -07001382 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001383 {
Dave Wallaceee45d412017-11-24 21:44:06 -05001384 if (VPPCOM_DEBUG > 0)
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001385 {
1386 if (session)
Florin Coras0d427d82018-06-27 03:24:07 -07001387 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connect "
Florin Coras134a9962018-08-28 11:32:04 -07001388 "failed! returning %d (%s)", getpid (),
1389 session->vpp_handle, session_handle, rv,
1390 vppcom_retval_str (rv));
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001391 else
1392 clib_warning ("VCL<%d>: no session for sid %u: connect failed! "
1393 "returning %d (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001394 session_handle, rv, vppcom_retval_str (rv));
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001395 }
Dave Wallaceee45d412017-11-24 21:44:06 -05001396 }
Florin Coras0d427d82018-06-27 03:24:07 -07001397 else
1398 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connected!",
Florin Coras134a9962018-08-28 11:32:04 -07001399 getpid (), session->vpp_handle, session_handle);
Dave Wallaceee45d412017-11-24 21:44:06 -05001400
Dave Wallace4878cbe2017-11-21 03:45:09 -05001401 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001402}
1403
Florin Coras54693d22018-07-17 10:46:29 -07001404static u8
1405vcl_is_rx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1406{
1407 if (!is_ct)
1408 return (e->event_type == FIFO_EVENT_APP_RX
1409 && e->fifo->client_session_index == sid);
1410 else
1411 return (e->event_type == SESSION_IO_EVT_CT_TX);
1412}
1413
Florin Coras460dce62018-07-27 05:45:06 -07001414static inline u8
1415vcl_session_is_readable (vcl_session_t * s)
1416{
1417 return ((s->session_state & STATE_OPEN)
1418 || (s->session_state == STATE_LISTEN
1419 && s->session_type == VPPCOM_PROTO_UDP));
1420}
1421
Steven58f464e2017-10-25 12:33:12 -07001422static inline int
Florin Coras134a9962018-08-28 11:32:04 -07001423vppcom_session_read_internal (uint32_t session_handle, void *buf, int n,
Steven58f464e2017-10-25 12:33:12 -07001424 u8 peek)
Dave Wallace543852a2017-08-03 02:11:34 -04001425{
Florin Coras134a9962018-08-28 11:32:04 -07001426 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001427 int n_read = 0, rv, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001428 vcl_session_t *s = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001429 svm_fifo_t *rx_fifo;
Florin Coras54693d22018-07-17 10:46:29 -07001430 svm_msg_q_msg_t msg;
1431 session_event_t *e;
1432 svm_msg_q_t *mq;
Florin Coras41c9e042018-09-11 00:10:41 -07001433 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001434
Florin Coras070453d2018-08-24 17:04:27 -07001435 if (PREDICT_FALSE (!buf))
1436 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001437
Florin Coras134a9962018-08-28 11:32:04 -07001438 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras2cba8532018-09-11 16:33:36 -07001439 if (PREDICT_FALSE (!s || s->is_vep))
Florin Coras070453d2018-08-24 17:04:27 -07001440 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001441
Florin Coras460dce62018-07-27 05:45:06 -07001442 if (PREDICT_FALSE (!vcl_session_is_readable (s)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001443 {
Florin Coras460dce62018-07-27 05:45:06 -07001444 session_state_t state = s->session_state;
Keith Burns (alagalah)56a0d062018-02-15 07:52:50 -08001445 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001446
Florin Coras0d427d82018-06-27 03:24:07 -07001447 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: %s session is not open! "
1448 "state 0x%x (%s), returning %d (%s)",
Florin Coras134a9962018-08-28 11:32:04 -07001449 getpid (), s->vpp_handle, session_handle, state,
Florin Coras0d427d82018-06-27 03:24:07 -07001450 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001451 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001452 }
1453
Florin Coras2cba8532018-09-11 16:33:36 -07001454 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
Florin Coras41c9e042018-09-11 00:10:41 -07001455 is_ct = vcl_session_is_ct (s);
1456 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
Florin Coras2cba8532018-09-11 16:33:36 -07001457 rx_fifo = s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001458 s->has_rx_evt = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001459
Florin Coras54693d22018-07-17 10:46:29 -07001460 if (svm_fifo_is_empty (rx_fifo))
Dave Wallacef7f809c2017-10-03 01:48:42 -04001461 {
Florin Coras54693d22018-07-17 10:46:29 -07001462 if (is_nonblocking)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001463 {
Florin Coras41c9e042018-09-11 00:10:41 -07001464 svm_fifo_unset_event (rx_fifo);
Florin Corasaa27eb92018-10-13 12:20:01 -07001465 return VPPCOM_EWOULDBLOCK;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001466 }
Florin Coras41c9e042018-09-11 00:10:41 -07001467 while (svm_fifo_is_empty (rx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001468 {
Florin Coras41c9e042018-09-11 00:10:41 -07001469 svm_fifo_unset_event (rx_fifo);
Florin Coras99368312018-08-02 10:45:44 -07001470 svm_msg_q_lock (mq);
Florin Coras54693d22018-07-17 10:46:29 -07001471 if (svm_msg_q_is_empty (mq))
1472 svm_msg_q_wait (mq);
Florin Coras99368312018-08-02 10:45:44 -07001473
Florin Coras54693d22018-07-17 10:46:29 -07001474 svm_msg_q_sub_w_lock (mq, &msg);
1475 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001476 svm_msg_q_unlock (mq);
Florin Coras41c9e042018-09-11 00:10:41 -07001477 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
Florin Coras54693d22018-07-17 10:46:29 -07001478 {
Florin Coras86f04502018-09-12 16:08:01 -07001479 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001480 svm_msg_q_free_msg (mq, &msg);
1481 continue;
1482 }
Florin Coras54693d22018-07-17 10:46:29 -07001483 svm_msg_q_free_msg (mq, &msg);
Florin Coras41c9e042018-09-11 00:10:41 -07001484
Florin Coras60f1fc12018-08-16 14:57:31 -07001485 if (PREDICT_FALSE (s->session_state == STATE_CLOSE_ON_EMPTY))
1486 return 0;
Florin Coras54693d22018-07-17 10:46:29 -07001487 }
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001488 }
Florin Coras54693d22018-07-17 10:46:29 -07001489
Florin Coras460dce62018-07-27 05:45:06 -07001490 if (s->is_dgram)
Florin Coras99368312018-08-02 10:45:44 -07001491 n_read = app_recv_dgram_raw (rx_fifo, buf, n, &s->transport, 0, peek);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001492 else
Florin Coras99368312018-08-02 10:45:44 -07001493 n_read = app_recv_stream_raw (rx_fifo, buf, n, 0, peek);
Florin Coras54693d22018-07-17 10:46:29 -07001494
Florin Coras41c9e042018-09-11 00:10:41 -07001495 if (svm_fifo_is_empty (rx_fifo))
1496 svm_fifo_unset_event (rx_fifo);
1497
Florin Coras58c101a2018-10-06 13:49:16 -07001498 if (is_ct && svm_fifo_want_tx_evt (rx_fifo))
Florin Coras99368312018-08-02 10:45:44 -07001499 {
Florin Coras58c101a2018-10-06 13:49:16 -07001500 svm_fifo_set_want_tx_evt (s->rx_fifo, 0);
1501 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo, SESSION_IO_EVT_CT_RX,
1502 SVM_Q_WAIT);
Florin Coras99368312018-08-02 10:45:44 -07001503 }
Florin Coras54693d22018-07-17 10:46:29 -07001504
Florin Coras2cba8532018-09-11 16:33:36 -07001505 VDBG (2, "VCL<%d>: vpp handle 0x%llx, sid %u: read %d bytes from (%p)",
1506 getpid (), s->vpp_handle, session_handle, n_read, rx_fifo);
1507
Florin Coras54693d22018-07-17 10:46:29 -07001508 return n_read;
Dave Wallace543852a2017-08-03 02:11:34 -04001509}
1510
Steven58f464e2017-10-25 12:33:12 -07001511int
Florin Coras134a9962018-08-28 11:32:04 -07001512vppcom_session_read (uint32_t session_handle, void *buf, size_t n)
Steven58f464e2017-10-25 12:33:12 -07001513{
Florin Coras134a9962018-08-28 11:32:04 -07001514 return (vppcom_session_read_internal (session_handle, buf, n, 0));
Steven58f464e2017-10-25 12:33:12 -07001515}
1516
1517static int
Florin Coras134a9962018-08-28 11:32:04 -07001518vppcom_session_peek (uint32_t session_handle, void *buf, int n)
Steven58f464e2017-10-25 12:33:12 -07001519{
Florin Coras134a9962018-08-28 11:32:04 -07001520 return (vppcom_session_read_internal (session_handle, buf, n, 1));
Steven58f464e2017-10-25 12:33:12 -07001521}
1522
Florin Coras2cba8532018-09-11 16:33:36 -07001523int
1524vppcom_session_read_segments (uint32_t session_handle,
1525 vppcom_data_segments_t ds)
1526{
1527 vcl_worker_t *wrk = vcl_worker_get_current ();
1528 int n_read = 0, rv, is_nonblocking;
1529 vcl_session_t *s = 0;
1530 svm_fifo_t *rx_fifo;
1531 svm_msg_q_msg_t msg;
1532 session_event_t *e;
1533 svm_msg_q_t *mq;
1534 u8 is_ct;
1535
1536 s = vcl_session_get_w_handle (wrk, session_handle);
1537 if (PREDICT_FALSE (!s || s->is_vep))
1538 return VPPCOM_EBADFD;
1539
1540 if (PREDICT_FALSE (!vcl_session_is_readable (s)))
1541 {
1542 session_state_t state = s->session_state;
1543 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1544 return rv;
1545 }
1546
1547 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1548 is_ct = vcl_session_is_ct (s);
1549 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
1550 rx_fifo = s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001551 s->has_rx_evt = 0;
Florin Coras2cba8532018-09-11 16:33:36 -07001552
1553 if (svm_fifo_is_empty (rx_fifo))
1554 {
1555 if (is_nonblocking)
1556 {
1557 svm_fifo_unset_event (rx_fifo);
Florin Corasaa27eb92018-10-13 12:20:01 -07001558 return VPPCOM_EWOULDBLOCK;
Florin Coras2cba8532018-09-11 16:33:36 -07001559 }
1560 while (svm_fifo_is_empty (rx_fifo))
1561 {
1562 svm_fifo_unset_event (rx_fifo);
1563 svm_msg_q_lock (mq);
1564 if (svm_msg_q_is_empty (mq))
1565 svm_msg_q_wait (mq);
1566
1567 svm_msg_q_sub_w_lock (mq, &msg);
1568 e = svm_msg_q_msg_data (mq, &msg);
1569 svm_msg_q_unlock (mq);
1570 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
1571 {
Florin Coras86f04502018-09-12 16:08:01 -07001572 vcl_handle_mq_event (wrk, e);
Florin Coras2cba8532018-09-11 16:33:36 -07001573 svm_msg_q_free_msg (mq, &msg);
1574 continue;
1575 }
1576 svm_msg_q_free_msg (mq, &msg);
1577
1578 if (PREDICT_FALSE (s->session_state == STATE_CLOSE_ON_EMPTY))
1579 return 0;
1580 }
1581 }
1582
1583 n_read = svm_fifo_segments (rx_fifo, (svm_fifo_segment_t *) ds);
1584 svm_fifo_unset_event (rx_fifo);
1585
1586 if (is_ct && n_read + svm_fifo_max_dequeue (rx_fifo) == rx_fifo->nitems)
1587 {
1588 /* If the peer is not polling send notification */
1589 if (!svm_fifo_has_event (s->rx_fifo))
1590 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo,
1591 SESSION_IO_EVT_CT_RX, SVM_Q_WAIT);
1592 }
1593
1594 return n_read;
1595}
1596
1597void
1598vppcom_session_free_segments (uint32_t session_handle,
1599 vppcom_data_segments_t ds)
1600{
1601 vcl_worker_t *wrk = vcl_worker_get_current ();
1602 vcl_session_t *s;
1603
1604 s = vcl_session_get_w_handle (wrk, session_handle);
1605 if (PREDICT_FALSE (!s || s->is_vep))
1606 return;
1607
1608 svm_fifo_segments_free (s->rx_fifo, (svm_fifo_segment_t *) ds);
1609}
1610
Dave Wallace543852a2017-08-03 02:11:34 -04001611static inline int
Florin Coras54693d22018-07-17 10:46:29 -07001612vppcom_session_read_ready (vcl_session_t * session)
Dave Wallace543852a2017-08-03 02:11:34 -04001613{
Dave Wallace543852a2017-08-03 02:11:34 -04001614 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05001615 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001616 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001617 clib_warning ("VCL<%d>: ERROR: sid %u: cannot read from an "
Florin Coras134a9962018-08-28 11:32:04 -07001618 "epoll session!", getpid (), session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -07001619 return VPPCOM_EBADFD;
1620 }
1621
1622 if (PREDICT_FALSE (!(session->session_state & (STATE_OPEN | STATE_LISTEN))))
1623 {
1624 session_state_t state = session->session_state;
1625 int rv;
1626
1627 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1628
1629 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open!"
1630 " state 0x%x (%s), returning %d (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001631 session->vpp_handle, session->session_index, state,
Florin Coras54693d22018-07-17 10:46:29 -07001632 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
1633 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001634 }
Dave Wallace33e002b2017-09-06 01:20:02 -04001635
Florin Coras7e12d942018-06-27 14:32:43 -07001636 if (session->session_state & STATE_LISTEN)
Florin Coras54693d22018-07-17 10:46:29 -07001637 return clib_fifo_elts (session->accept_evts_fifo);
1638
1639 return svm_fifo_max_dequeue (session->rx_fifo);
1640}
1641
Florin Coras2cba8532018-09-11 16:33:36 -07001642int
1643vppcom_data_segment_copy (void *buf, vppcom_data_segments_t ds, u32 max_bytes)
1644{
1645 u32 first_copy = clib_min (ds[0].len, max_bytes);
Dave Barach178cf492018-11-13 16:34:13 -05001646 clib_memcpy_fast (buf, ds[0].data, first_copy);
Florin Coras2cba8532018-09-11 16:33:36 -07001647 if (first_copy < max_bytes)
1648 {
Dave Barach178cf492018-11-13 16:34:13 -05001649 clib_memcpy_fast (buf + first_copy, ds[1].data,
1650 clib_min (ds[1].len, max_bytes - first_copy));
Florin Coras2cba8532018-09-11 16:33:36 -07001651 }
1652 return 0;
1653}
1654
Florin Coras54693d22018-07-17 10:46:29 -07001655static u8
1656vcl_is_tx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1657{
1658 if (!is_ct)
1659 return (e->event_type == FIFO_EVENT_APP_TX
1660 && e->fifo->client_session_index == sid);
Dave Wallace543852a2017-08-03 02:11:34 -04001661 else
Florin Coras54693d22018-07-17 10:46:29 -07001662 return (e->event_type == SESSION_IO_EVT_CT_RX);
Dave Wallace543852a2017-08-03 02:11:34 -04001663}
1664
1665int
Florin Coras134a9962018-08-28 11:32:04 -07001666vppcom_session_write (uint32_t session_handle, void *buf, size_t n)
Dave Wallace543852a2017-08-03 02:11:34 -04001667{
Florin Coras134a9962018-08-28 11:32:04 -07001668 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001669 int rv, n_write, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001670 vcl_session_t *s = 0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001671 svm_fifo_t *tx_fifo = 0;
Florin Coras460dce62018-07-27 05:45:06 -07001672 session_evt_type_t et;
Florin Coras54693d22018-07-17 10:46:29 -07001673 svm_msg_q_msg_t msg;
1674 session_event_t *e;
Florin Coras3c2fed52018-07-04 04:15:05 -07001675 svm_msg_q_t *mq;
Florin Coras0e88e852018-09-17 22:09:02 -07001676 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001677
Florin Coras070453d2018-08-24 17:04:27 -07001678 if (PREDICT_FALSE (!buf))
1679 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001680
Florin Coras134a9962018-08-28 11:32:04 -07001681 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001682 if (PREDICT_FALSE (!s))
1683 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001684
Florin Coras460dce62018-07-27 05:45:06 -07001685 if (PREDICT_FALSE (s->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001686 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001687 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001688 "cannot write to an epoll session!",
Florin Coras134a9962018-08-28 11:32:04 -07001689 getpid (), s->vpp_handle, session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001690
Florin Coras070453d2018-08-24 17:04:27 -07001691 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001692 }
1693
Florin Coras0e88e852018-09-17 22:09:02 -07001694 if (PREDICT_FALSE (!(s->session_state & STATE_OPEN)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001695 {
Florin Coras460dce62018-07-27 05:45:06 -07001696 session_state_t state = s->session_state;
Florin Coras54693d22018-07-17 10:46:29 -07001697 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Florin Coras0d427d82018-06-27 03:24:07 -07001698 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open! "
Florin Coras0e88e852018-09-17 22:09:02 -07001699 "state 0x%x (%s)", getpid (), s->vpp_handle, session_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001700 state, vppcom_session_state_str (state));
Florin Coras070453d2018-08-24 17:04:27 -07001701 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001702 }
1703
Florin Coras0e88e852018-09-17 22:09:02 -07001704 tx_fifo = s->tx_fifo;
1705 is_ct = vcl_session_is_ct (s);
1706 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1707 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
Florin Coras54693d22018-07-17 10:46:29 -07001708 if (svm_fifo_is_full (tx_fifo))
Dave Wallace543852a2017-08-03 02:11:34 -04001709 {
Florin Coras54693d22018-07-17 10:46:29 -07001710 if (is_nonblocking)
1711 {
Florin Coras070453d2018-08-24 17:04:27 -07001712 return VPPCOM_EWOULDBLOCK;
Florin Coras54693d22018-07-17 10:46:29 -07001713 }
Florin Coras60f1fc12018-08-16 14:57:31 -07001714 while (svm_fifo_is_full (tx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001715 {
Florin Coras0e88e852018-09-17 22:09:02 -07001716 svm_fifo_set_want_tx_evt (tx_fifo, 1);
Florin Coras99368312018-08-02 10:45:44 -07001717 svm_msg_q_lock (mq);
Florin Corasaa27eb92018-10-13 12:20:01 -07001718 if (svm_msg_q_is_empty (mq))
1719 svm_msg_q_wait (mq);
Florin Coras0e88e852018-09-17 22:09:02 -07001720
Florin Coras54693d22018-07-17 10:46:29 -07001721 svm_msg_q_sub_w_lock (mq, &msg);
1722 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001723 svm_msg_q_unlock (mq);
1724
Florin Coras0e88e852018-09-17 22:09:02 -07001725 if (!vcl_is_tx_evt_for_session (e, s->session_index, is_ct))
Florin Coras86f04502018-09-12 16:08:01 -07001726 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001727 svm_msg_q_free_msg (mq, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001728 }
Dave Wallace543852a2017-08-03 02:11:34 -04001729 }
Dave Wallace543852a2017-08-03 02:11:34 -04001730
Florin Coras460dce62018-07-27 05:45:06 -07001731 ASSERT (FIFO_EVENT_APP_TX + 1 == SESSION_IO_EVT_CT_TX);
1732 et = FIFO_EVENT_APP_TX + vcl_session_is_ct (s);
1733 if (s->is_dgram)
1734 n_write = app_send_dgram_raw (tx_fifo, &s->transport,
1735 s->vpp_evt_q, buf, n, et, SVM_Q_WAIT);
1736 else
1737 n_write = app_send_stream_raw (tx_fifo, s->vpp_evt_q, buf, n, et,
1738 SVM_Q_WAIT);
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -07001739
Florin Coras460dce62018-07-27 05:45:06 -07001740 ASSERT (n_write > 0);
Dave Wallace543852a2017-08-03 02:11:34 -04001741
Florin Coras0e88e852018-09-17 22:09:02 -07001742 VDBG (2, "VCL<%d>: vpp handle 0x%llx, sid %u: wrote %d bytes", getpid (),
1743 s->vpp_handle, session_handle, n_write);
1744
Florin Coras54693d22018-07-17 10:46:29 -07001745 return n_write;
Dave Wallace543852a2017-08-03 02:11:34 -04001746}
1747
Florin Coras99368312018-08-02 10:45:44 -07001748static vcl_session_t *
Florin Coras134a9962018-08-28 11:32:04 -07001749vcl_ct_session_get_from_fifo (vcl_worker_t * wrk, svm_fifo_t * f, u8 type)
Florin Coras99368312018-08-02 10:45:44 -07001750{
1751 vcl_session_t *s;
Florin Coras134a9962018-08-28 11:32:04 -07001752 s = vcl_session_get (wrk, f->client_session_index);
Florin Coras99368312018-08-02 10:45:44 -07001753 if (s)
1754 {
1755 /* rx fifo */
1756 if (type == 0 && s->rx_fifo == f)
1757 return s;
1758 /* tx fifo */
1759 if (type == 1 && s->tx_fifo == f)
1760 return s;
1761 }
Florin Coras134a9962018-08-28 11:32:04 -07001762 s = vcl_session_get (wrk, f->master_session_index);
Florin Coras99368312018-08-02 10:45:44 -07001763 if (s)
1764 {
1765 if (type == 0 && s->rx_fifo == f)
1766 return s;
1767 if (type == 1 && s->tx_fifo == f)
1768 return s;
1769 }
1770 return 0;
1771}
1772
Dave Wallace543852a2017-08-03 02:11:34 -04001773static inline int
Florin Coras134a9962018-08-28 11:32:04 -07001774vppcom_session_write_ready (vcl_session_t * session)
Dave Wallace543852a2017-08-03 02:11:34 -04001775{
Dave Wallace543852a2017-08-03 02:11:34 -04001776 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05001777 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001778 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001779 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001780 "cannot write to an epoll session!",
Florin Coras134a9962018-08-28 11:32:04 -07001781 getpid (), session->vpp_handle, session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -07001782 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001783 }
1784
Florin Coras7e12d942018-06-27 14:32:43 -07001785 if (PREDICT_FALSE (session->session_state & STATE_LISTEN))
Dave Wallace33e002b2017-09-06 01:20:02 -04001786 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001787 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001788 "cannot write to a listen session!",
Florin Coras134a9962018-08-28 11:32:04 -07001789 getpid (), session->vpp_handle, session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -07001790 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001791 }
1792
Florin Coras54693d22018-07-17 10:46:29 -07001793 if (PREDICT_FALSE (!(session->session_state & STATE_OPEN)))
Dave Wallace4878cbe2017-11-21 03:45:09 -05001794 {
Florin Coras7e12d942018-06-27 14:32:43 -07001795 session_state_t state = session->session_state;
Florin Coras54693d22018-07-17 10:46:29 -07001796 int rv;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001797
Keith Burns (alagalah)56a0d062018-02-15 07:52:50 -08001798 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Dave Wallace048b1d62018-01-03 22:24:41 -05001799 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001800 "session is not open! state 0x%x (%s), "
Dave Wallaceee45d412017-11-24 21:44:06 -05001801 "returning %d (%s)", getpid (), session->vpp_handle,
Florin Coras134a9962018-08-28 11:32:04 -07001802 session->session_index,
Dave Wallace4878cbe2017-11-21 03:45:09 -05001803 state, vppcom_session_state_str (state),
1804 rv, vppcom_retval_str (rv));
Florin Coras54693d22018-07-17 10:46:29 -07001805 return rv;
Dave Wallace33e002b2017-09-06 01:20:02 -04001806 }
1807
Florin Coras0d427d82018-06-27 03:24:07 -07001808 VDBG (3, "VCL<%d>: vpp handle 0x%llx, sid %u: peek %s (%p), ready = %d",
Florin Coras134a9962018-08-28 11:32:04 -07001809 getpid (), session->vpp_handle, session->session_index,
1810 session->tx_fifo, svm_fifo_max_enqueue (session->tx_fifo));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001811
Florin Coras54693d22018-07-17 10:46:29 -07001812 return svm_fifo_max_enqueue (session->tx_fifo);
1813}
1814
Florin Coras99368312018-08-02 10:45:44 -07001815static inline int
Florin Coras134a9962018-08-28 11:32:04 -07001816vcl_mq_dequeue_batch (vcl_worker_t * wrk, svm_msg_q_t * mq)
Florin Coras99368312018-08-02 10:45:44 -07001817{
1818 svm_msg_q_msg_t *msg;
1819 u32 n_msgs;
1820 int i;
1821
1822 n_msgs = svm_msg_q_size (mq);
1823 for (i = 0; i < n_msgs; i++)
1824 {
Florin Coras134a9962018-08-28 11:32:04 -07001825 vec_add2 (wrk->mq_msg_vector, msg, 1);
Florin Coras99368312018-08-02 10:45:44 -07001826 svm_msg_q_sub_w_lock (mq, msg);
1827 }
1828 return n_msgs;
1829}
1830
Florin Coras6d4bb422018-09-04 22:07:27 -07001831#define vcl_fifo_rx_evt_valid_or_break(_fifo) \
1832if (PREDICT_FALSE (svm_fifo_is_empty (_fifo))) \
1833 { \
1834 svm_fifo_unset_event (_fifo); \
1835 if (svm_fifo_is_empty (_fifo)) \
Florin Coras41c9e042018-09-11 00:10:41 -07001836 break; \
Florin Coras6d4bb422018-09-04 22:07:27 -07001837 } \
1838
Florin Coras86f04502018-09-12 16:08:01 -07001839static void
1840vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
1841 unsigned long n_bits, unsigned long *read_map,
1842 unsigned long *write_map,
1843 unsigned long *except_map, u32 * bits_set)
Florin Coras54693d22018-07-17 10:46:29 -07001844{
1845 session_disconnected_msg_t *disconnected_msg;
Florin Coras99368312018-08-02 10:45:44 -07001846 session_connected_msg_t *connected_msg;
Florin Coras54693d22018-07-17 10:46:29 -07001847 session_accepted_msg_t *accepted_msg;
1848 vcl_session_msg_t *vcl_msg;
1849 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07001850 u64 handle;
1851 u32 sid;
1852
1853 switch (e->event_type)
1854 {
1855 case FIFO_EVENT_APP_RX:
1856 vcl_fifo_rx_evt_valid_or_break (e->fifo);
1857 sid = e->fifo->client_session_index;
1858 session = vcl_session_get (wrk, sid);
1859 if (!session)
1860 break;
1861 if (sid < n_bits && read_map)
1862 {
1863 clib_bitmap_set_no_check (read_map, sid, 1);
1864 *bits_set += 1;
1865 }
1866 break;
1867 case FIFO_EVENT_APP_TX:
1868 sid = e->fifo->client_session_index;
1869 session = vcl_session_get (wrk, sid);
1870 if (!session)
1871 break;
1872 if (sid < n_bits && write_map)
1873 {
1874 clib_bitmap_set_no_check (write_map, sid, 1);
1875 *bits_set += 1;
1876 }
1877 break;
1878 case SESSION_IO_EVT_CT_TX:
1879 vcl_fifo_rx_evt_valid_or_break (e->fifo);
1880 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0);
1881 if (!session)
1882 break;
1883 sid = session->session_index;
1884 if (sid < n_bits && read_map)
1885 {
1886 clib_bitmap_set_no_check (read_map, sid, 1);
1887 *bits_set += 1;
1888 }
1889 break;
1890 case SESSION_IO_EVT_CT_RX:
1891 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1);
1892 if (!session)
1893 break;
1894 sid = session->session_index;
1895 if (sid < n_bits && write_map)
1896 {
1897 clib_bitmap_set_no_check (write_map, sid, 1);
1898 *bits_set += 1;
1899 }
1900 break;
1901 case SESSION_CTRL_EVT_ACCEPTED:
1902 accepted_msg = (session_accepted_msg_t *) e->data;
1903 handle = accepted_msg->listener_handle;
1904 session = vcl_session_table_lookup_listener (wrk, handle);
1905 if (!session)
1906 {
1907 clib_warning ("VCL<%d>: ERROR: couldn't find listen session:"
1908 "listener handle %llx", getpid (), handle);
1909 break;
1910 }
1911
1912 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
1913 vcl_msg->accepted_msg = *accepted_msg;
1914 sid = session->session_index;
1915 if (sid < n_bits && read_map)
1916 {
1917 clib_bitmap_set_no_check (read_map, sid, 1);
1918 *bits_set += 1;
1919 }
1920 break;
1921 case SESSION_CTRL_EVT_CONNECTED:
1922 connected_msg = (session_connected_msg_t *) e->data;
1923 vcl_session_connected_handler (wrk, connected_msg);
1924 break;
1925 case SESSION_CTRL_EVT_DISCONNECTED:
1926 disconnected_msg = (session_disconnected_msg_t *) e->data;
1927 sid = vcl_session_index_from_vpp_handle (wrk, disconnected_msg->handle);
1928 if (sid < n_bits && except_map)
1929 {
1930 clib_bitmap_set_no_check (except_map, sid, 1);
1931 *bits_set += 1;
1932 }
1933 break;
1934 case SESSION_CTRL_EVT_RESET:
1935 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
1936 if (sid < n_bits && except_map)
1937 {
1938 clib_bitmap_set_no_check (except_map, sid, 1);
1939 *bits_set += 1;
1940 }
1941 break;
1942 default:
1943 clib_warning ("unhandled: %u", e->event_type);
1944 break;
1945 }
1946}
1947
1948static int
1949vcl_select_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
1950 unsigned long n_bits, unsigned long *read_map,
1951 unsigned long *write_map, unsigned long *except_map,
1952 double time_to_wait, u32 * bits_set)
1953{
Florin Coras99368312018-08-02 10:45:44 -07001954 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07001955 session_event_t *e;
Florin Coras86f04502018-09-12 16:08:01 -07001956 u32 i;
Florin Coras54693d22018-07-17 10:46:29 -07001957
1958 svm_msg_q_lock (mq);
1959 if (svm_msg_q_is_empty (mq))
Dave Wallace4878cbe2017-11-21 03:45:09 -05001960 {
Florin Coras54693d22018-07-17 10:46:29 -07001961 if (*bits_set)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001962 {
Florin Coras54693d22018-07-17 10:46:29 -07001963 svm_msg_q_unlock (mq);
1964 return 0;
1965 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001966
Florin Coras54693d22018-07-17 10:46:29 -07001967 if (!time_to_wait)
1968 {
1969 svm_msg_q_unlock (mq);
1970 return 0;
1971 }
1972 else if (time_to_wait < 0)
1973 {
1974 svm_msg_q_wait (mq);
1975 }
1976 else
1977 {
1978 if (svm_msg_q_timedwait (mq, time_to_wait))
1979 {
1980 svm_msg_q_unlock (mq);
1981 return 0;
1982 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001983 }
1984 }
Florin Coras134a9962018-08-28 11:32:04 -07001985 vcl_mq_dequeue_batch (wrk, mq);
Florin Coras54693d22018-07-17 10:46:29 -07001986 svm_msg_q_unlock (mq);
1987
Florin Coras134a9962018-08-28 11:32:04 -07001988 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07001989 {
Florin Coras134a9962018-08-28 11:32:04 -07001990 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07001991 e = svm_msg_q_msg_data (mq, msg);
Florin Coras86f04502018-09-12 16:08:01 -07001992 vcl_select_handle_mq_event (wrk, e, n_bits, read_map, write_map,
1993 except_map, bits_set);
Florin Coras99368312018-08-02 10:45:44 -07001994 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07001995 }
Florin Coras134a9962018-08-28 11:32:04 -07001996 vec_reset_length (wrk->mq_msg_vector);
Florin Coras54693d22018-07-17 10:46:29 -07001997 return *bits_set;
Dave Wallace543852a2017-08-03 02:11:34 -04001998}
1999
Florin Coras99368312018-08-02 10:45:44 -07002000static int
Florin Coras134a9962018-08-28 11:32:04 -07002001vppcom_select_condvar (vcl_worker_t * wrk, unsigned long n_bits,
2002 unsigned long *read_map, unsigned long *write_map,
2003 unsigned long *except_map, double time_to_wait,
2004 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002005{
2006 double total_wait = 0, wait_slice;
2007 vcl_cut_through_registration_t *cr;
2008
2009 time_to_wait = (time_to_wait == -1) ? 10e9 : time_to_wait;
Florin Coras134a9962018-08-28 11:32:04 -07002010 wait_slice = wrk->cut_through_registrations ? 10e-6 : time_to_wait;
Florin Coras99368312018-08-02 10:45:44 -07002011 do
2012 {
Florin Coras134a9962018-08-28 11:32:04 -07002013 vcl_ct_registration_lock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002014 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002015 pool_foreach (cr, wrk->cut_through_registrations, ({
2016 vcl_select_handle_mq (wrk, cr->mq, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002017 0, bits_set);
2018 }));
2019 /* *INDENT-ON* */
Florin Coras134a9962018-08-28 11:32:04 -07002020 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002021
Florin Coras134a9962018-08-28 11:32:04 -07002022 vcl_select_handle_mq (wrk, wrk->app_event_queue, n_bits, read_map,
2023 write_map, except_map, time_to_wait, bits_set);
Florin Coras99368312018-08-02 10:45:44 -07002024 total_wait += wait_slice;
2025 if (*bits_set)
2026 return *bits_set;
2027 }
2028 while (total_wait < time_to_wait);
2029
2030 return 0;
2031}
2032
2033static int
Florin Coras134a9962018-08-28 11:32:04 -07002034vppcom_select_eventfd (vcl_worker_t * wrk, unsigned long n_bits,
2035 unsigned long *read_map, unsigned long *write_map,
2036 unsigned long *except_map, double time_to_wait,
2037 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002038{
2039 vcl_mq_evt_conn_t *mqc;
2040 int __clib_unused n_read;
2041 int n_mq_evts, i;
2042 u64 buf;
2043
Florin Coras134a9962018-08-28 11:32:04 -07002044 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
2045 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2046 vec_len (wrk->mq_events), time_to_wait);
Florin Coras99368312018-08-02 10:45:44 -07002047 for (i = 0; i < n_mq_evts; i++)
2048 {
Florin Coras134a9962018-08-28 11:32:04 -07002049 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002050 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002051 vcl_select_handle_mq (wrk, mqc->mq, n_bits, read_map, write_map,
Florin Coras99368312018-08-02 10:45:44 -07002052 except_map, 0, bits_set);
2053 }
2054
2055 return (n_mq_evts > 0 ? (int) *bits_set : 0);
2056}
2057
Dave Wallace543852a2017-08-03 02:11:34 -04002058int
2059vppcom_select (unsigned long n_bits, unsigned long *read_map,
2060 unsigned long *write_map, unsigned long *except_map,
2061 double time_to_wait)
2062{
Florin Coras54693d22018-07-17 10:46:29 -07002063 u32 sid, minbits = clib_max (n_bits, BITS (uword)), bits_set = 0;
Florin Coras134a9962018-08-28 11:32:04 -07002064 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002065 vcl_session_t *session = 0;
Florin Coras86f04502018-09-12 16:08:01 -07002066 int rv, i;
Dave Wallace543852a2017-08-03 02:11:34 -04002067
2068 ASSERT (sizeof (clib_bitmap_t) == sizeof (long int));
2069
Dave Wallace7876d392017-10-19 03:53:57 -04002070 if (n_bits && read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002071 {
Florin Coras134a9962018-08-28 11:32:04 -07002072 clib_bitmap_validate (wrk->rd_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002073 clib_memcpy_fast (wrk->rd_bitmap, read_map,
2074 vec_len (wrk->rd_bitmap) * sizeof (clib_bitmap_t));
Florin Coras134a9962018-08-28 11:32:04 -07002075 memset (read_map, 0, vec_len (wrk->rd_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace543852a2017-08-03 02:11:34 -04002076 }
Dave Wallace7876d392017-10-19 03:53:57 -04002077 if (n_bits && write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002078 {
Florin Coras134a9962018-08-28 11:32:04 -07002079 clib_bitmap_validate (wrk->wr_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002080 clib_memcpy_fast (wrk->wr_bitmap, write_map,
2081 vec_len (wrk->wr_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05002082 memset (write_map, 0,
Florin Coras134a9962018-08-28 11:32:04 -07002083 vec_len (wrk->wr_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace543852a2017-08-03 02:11:34 -04002084 }
Dave Wallace7876d392017-10-19 03:53:57 -04002085 if (n_bits && except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002086 {
Florin Coras134a9962018-08-28 11:32:04 -07002087 clib_bitmap_validate (wrk->ex_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002088 clib_memcpy_fast (wrk->ex_bitmap, except_map,
2089 vec_len (wrk->ex_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05002090 memset (except_map, 0,
Florin Coras134a9962018-08-28 11:32:04 -07002091 vec_len (wrk->ex_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace543852a2017-08-03 02:11:34 -04002092 }
2093
Florin Coras54693d22018-07-17 10:46:29 -07002094 if (!n_bits)
2095 return 0;
2096
2097 if (!write_map)
2098 goto check_rd;
2099
2100 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002101 clib_bitmap_foreach (sid, wrk->wr_bitmap, ({
2102 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002103 {
Florin Coras47c40e22018-11-26 17:01:36 -08002104 if (except_map && sid < minbits)
2105 clib_bitmap_set_no_check (except_map, sid, 1);
2106 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002107 }
2108
2109 rv = svm_fifo_is_full (session->tx_fifo);
Florin Coras54693d22018-07-17 10:46:29 -07002110 if (!rv)
2111 {
2112 clib_bitmap_set_no_check (write_map, sid, 1);
2113 bits_set++;
2114 }
2115 }));
2116
2117check_rd:
2118 if (!read_map)
2119 goto check_mq;
Florin Coras99368312018-08-02 10:45:44 -07002120
Florin Coras134a9962018-08-28 11:32:04 -07002121 clib_bitmap_foreach (sid, wrk->rd_bitmap, ({
2122 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002123 {
Florin Coras47c40e22018-11-26 17:01:36 -08002124 if (except_map && sid < minbits)
2125 clib_bitmap_set_no_check (except_map, sid, 1);
2126 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002127 }
2128
2129 rv = vppcom_session_read_ready (session);
Florin Coras54693d22018-07-17 10:46:29 -07002130 if (rv)
2131 {
2132 clib_bitmap_set_no_check (read_map, sid, 1);
2133 bits_set++;
2134 }
2135 }));
2136 /* *INDENT-ON* */
2137
2138check_mq:
Dave Wallace543852a2017-08-03 02:11:34 -04002139
Florin Coras86f04502018-09-12 16:08:01 -07002140 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2141 {
2142 vcl_select_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i], n_bits,
2143 read_map, write_map, except_map, &bits_set);
2144 }
2145 vec_reset_length (wrk->unhandled_evts_vector);
2146
Florin Coras99368312018-08-02 10:45:44 -07002147 if (vcm->cfg.use_mq_eventfd)
Florin Coras134a9962018-08-28 11:32:04 -07002148 vppcom_select_eventfd (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002149 time_to_wait, &bits_set);
2150 else
Florin Coras134a9962018-08-28 11:32:04 -07002151 vppcom_select_condvar (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002152 time_to_wait, &bits_set);
Florin Coras54693d22018-07-17 10:46:29 -07002153
Dave Wallace543852a2017-08-03 02:11:34 -04002154 return (bits_set);
2155}
2156
Dave Wallacef7f809c2017-10-03 01:48:42 -04002157static inline void
Florin Coras134a9962018-08-28 11:32:04 -07002158vep_verify_epoll_chain (vcl_worker_t * wrk, u32 vep_idx)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002159{
Florin Coras7e12d942018-06-27 14:32:43 -07002160 vcl_session_t *session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002161 vppcom_epoll_t *vep;
Dave Wallace498b3a52017-11-09 13:00:34 -05002162 u32 sid = vep_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002163
Dave Wallace498b3a52017-11-09 13:00:34 -05002164 if (VPPCOM_DEBUG <= 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002165 return;
2166
2167 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Florin Coras134a9962018-08-28 11:32:04 -07002168 session = vcl_session_get (wrk, vep_idx);
Florin Coras070453d2018-08-24 17:04:27 -07002169 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002170 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002171 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!",
2172 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002173 goto done;
2174 }
2175 if (PREDICT_FALSE (!session->is_vep))
2176 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002177 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
2178 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002179 goto done;
2180 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002181 vep = &session->vep;
Dave Wallace048b1d62018-01-03 22:24:41 -05002182 clib_warning ("VCL<%d>: vep_idx (%u): Dumping epoll chain\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05002183 "{\n"
2184 " is_vep = %u\n"
2185 " is_vep_session = %u\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05002186 " next_sid = 0x%x (%u)\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05002187 " wait_cont_idx = 0x%x (%u)\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05002188 "}\n", getpid (), vep_idx,
2189 session->is_vep, session->is_vep_session,
Florin Coras134a9962018-08-28 11:32:04 -07002190 vep->next_sh, vep->next_sh,
Dave Wallace498b3a52017-11-09 13:00:34 -05002191 session->wait_cont_idx, session->wait_cont_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002192
Florin Coras134a9962018-08-28 11:32:04 -07002193 for (sid = vep->next_sh; sid != ~0; sid = vep->next_sh)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002194 {
Florin Coras134a9962018-08-28 11:32:04 -07002195 session = vcl_session_get (wrk, sid);
Florin Coras070453d2018-08-24 17:04:27 -07002196 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002197 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002198 clib_warning ("VCL<%d>: ERROR: Invalid sid (%u)!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002199 goto done;
2200 }
2201 if (PREDICT_FALSE (session->is_vep))
Dave Wallace048b1d62018-01-03 22:24:41 -05002202 clib_warning ("VCL<%d>: ERROR: sid (%u) is a vep!",
2203 getpid (), vep_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002204 else if (PREDICT_FALSE (!session->is_vep_session))
2205 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002206 clib_warning ("VCL<%d>: ERROR: session (%u) "
2207 "is not a vep session!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002208 goto done;
2209 }
2210 vep = &session->vep;
Florin Coras134a9962018-08-28 11:32:04 -07002211 if (PREDICT_FALSE (vep->vep_sh != vep_idx))
Dave Wallace048b1d62018-01-03 22:24:41 -05002212 clib_warning ("VCL<%d>: ERROR: session (%u) vep_idx (%u) != "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002213 "vep_idx (%u)!", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002214 sid, session->vep.vep_sh, vep_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002215 if (session->is_vep_session)
2216 {
2217 clib_warning ("vep_idx[%u]: sid 0x%x (%u)\n"
2218 "{\n"
2219 " next_sid = 0x%x (%u)\n"
2220 " prev_sid = 0x%x (%u)\n"
2221 " vep_idx = 0x%x (%u)\n"
2222 " ev.events = 0x%x\n"
2223 " ev.data.u64 = 0x%llx\n"
2224 " et_mask = 0x%x\n"
2225 "}\n",
2226 vep_idx, sid, sid,
Florin Coras134a9962018-08-28 11:32:04 -07002227 vep->next_sh, vep->next_sh,
2228 vep->prev_sh, vep->prev_sh,
2229 vep->vep_sh, vep->vep_sh,
Dave Wallace4878cbe2017-11-21 03:45:09 -05002230 vep->ev.events, vep->ev.data.u64, vep->et_mask);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002231 }
2232 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002233
2234done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002235 clib_warning ("VCL<%d>: vep_idx (%u): Dump complete!\n",
2236 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002237}
2238
2239int
2240vppcom_epoll_create (void)
2241{
Florin Coras134a9962018-08-28 11:32:04 -07002242 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002243 vcl_session_t *vep_session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002244
Florin Coras134a9962018-08-28 11:32:04 -07002245 vep_session = vcl_session_alloc (wrk);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002246
2247 vep_session->is_vep = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002248 vep_session->vep.vep_sh = ~0;
2249 vep_session->vep.next_sh = ~0;
2250 vep_session->vep.prev_sh = ~0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002251 vep_session->wait_cont_idx = ~0;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002252 vep_session->vpp_handle = ~0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002253
Florin Coras134a9962018-08-28 11:32:04 -07002254 vcl_evt (VCL_EVT_EPOLL_CREATE, vep_session, vep_sh);
Florin Coras0d427d82018-06-27 03:24:07 -07002255 VDBG (0, "VCL<%d>: Created vep_idx %u / sid %u!",
Florin Coras134a9962018-08-28 11:32:04 -07002256 getpid (), vep_session->session_index, vep_session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08002257
Florin Corasab2f6db2018-08-31 14:31:41 -07002258 return vcl_session_handle (vep_session);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002259}
2260
2261int
Florin Coras134a9962018-08-28 11:32:04 -07002262vppcom_epoll_ctl (uint32_t vep_handle, int op, uint32_t session_handle,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002263 struct epoll_event *event)
2264{
Florin Coras134a9962018-08-28 11:32:04 -07002265 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002266 vcl_session_t *vep_session;
2267 vcl_session_t *session;
Florin Coras070453d2018-08-24 17:04:27 -07002268 int rv = VPPCOM_OK;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002269
Florin Coras134a9962018-08-28 11:32:04 -07002270 if (vep_handle == session_handle)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002271 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002272 clib_warning ("VCL<%d>: ERROR: vep_idx == session_index (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002273 getpid (), vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002274 return VPPCOM_EINVAL;
2275 }
2276
Florin Coras134a9962018-08-28 11:32:04 -07002277 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002278 if (PREDICT_FALSE (!vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002279 {
Florin Coras134a9962018-08-28 11:32:04 -07002280 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002281 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002282 }
2283 if (PREDICT_FALSE (!vep_session->is_vep))
2284 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002285 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
Florin Coras134a9962018-08-28 11:32:04 -07002286 getpid (), vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002287 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002288 }
2289
Florin Coras134a9962018-08-28 11:32:04 -07002290 ASSERT (vep_session->vep.vep_sh == ~0);
2291 ASSERT (vep_session->vep.prev_sh == ~0);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002292
Florin Coras134a9962018-08-28 11:32:04 -07002293 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002294 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002295 {
Florin Coras134a9962018-08-28 11:32:04 -07002296 VDBG (0, "VCL<%d>: ERROR: Invalid session_handle (%u)!",
2297 getpid (), session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002298 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002299 }
2300 if (PREDICT_FALSE (session->is_vep))
2301 {
Florin Coras134a9962018-08-28 11:32:04 -07002302 clib_warning ("ERROR: session_handle (%u) is a vep!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002303 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002304 }
2305
2306 switch (op)
2307 {
2308 case EPOLL_CTL_ADD:
2309 if (PREDICT_FALSE (!event))
2310 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002311 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002312 "epoll_event structure!", getpid ());
Florin Coras070453d2018-08-24 17:04:27 -07002313 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002314 }
Florin Coras134a9962018-08-28 11:32:04 -07002315 if (vep_session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002316 {
Florin Coras7e12d942018-06-27 14:32:43 -07002317 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002318 next_session = vcl_session_get_w_handle (wrk,
2319 vep_session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002320 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002321 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002322 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: Invalid "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002323 "vep.next_sid (%u) on vep_idx (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002324 getpid (), vep_session->vep.next_sh, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002325 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002326 }
Florin Coras134a9962018-08-28 11:32:04 -07002327 ASSERT (next_session->vep.prev_sh == vep_handle);
2328 next_session->vep.prev_sh = session_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002329 }
Florin Coras134a9962018-08-28 11:32:04 -07002330 session->vep.next_sh = vep_session->vep.next_sh;
2331 session->vep.prev_sh = vep_handle;
2332 session->vep.vep_sh = vep_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002333 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2334 session->vep.ev = *event;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002335 session->is_vep = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002336 session->is_vep_session = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002337 vep_session->vep.next_sh = session_handle;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08002338
Florin Coras070453d2018-08-24 17:04:27 -07002339 VDBG (1, "VCL<%d>: EPOLL_CTL_ADD: vep_idx %u, sid %u, events 0x%x, "
Florin Coras134a9962018-08-28 11:32:04 -07002340 "data 0x%llx!", getpid (), vep_handle, session_handle,
2341 event->events, event->data.u64);
Florin Coras0d427d82018-06-27 03:24:07 -07002342 vcl_evt (VCL_EVT_EPOLL_CTLADD, session, event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002343 break;
2344
2345 case EPOLL_CTL_MOD:
2346 if (PREDICT_FALSE (!event))
2347 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002348 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_MOD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002349 "epoll_event structure!", getpid ());
Dave Wallacef7f809c2017-10-03 01:48:42 -04002350 rv = VPPCOM_EINVAL;
2351 goto done;
2352 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002353 else if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002354 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002355 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: "
Florin Coras134a9962018-08-28 11:32:04 -07002356 "not a vep session!", getpid (), session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002357 rv = VPPCOM_EINVAL;
2358 goto done;
2359 }
Florin Coras134a9962018-08-28 11:32:04 -07002360 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002361 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002362 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002363 "vep_idx (%u) != vep_idx (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002364 getpid (), session_handle,
2365 session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002366 rv = VPPCOM_EINVAL;
2367 goto done;
2368 }
2369 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2370 session->vep.ev = *event;
Florin Coras0d427d82018-06-27 03:24:07 -07002371 VDBG (1, "VCL<%d>: EPOLL_CTL_MOD: vep_idx %u, sid %u, events 0x%x,"
Florin Coras134a9962018-08-28 11:32:04 -07002372 " data 0x%llx!", getpid (), vep_handle, session_handle,
2373 event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002374 break;
2375
2376 case EPOLL_CTL_DEL:
Dave Wallace4878cbe2017-11-21 03:45:09 -05002377 if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002378 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002379 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: "
Florin Coras134a9962018-08-28 11:32:04 -07002380 "not a vep session!", getpid (), session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002381 rv = VPPCOM_EINVAL;
2382 goto done;
2383 }
Florin Coras134a9962018-08-28 11:32:04 -07002384 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002385 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002386 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002387 "vep_idx (%u) != vep_idx (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002388 getpid (), session_handle,
2389 session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002390 rv = VPPCOM_EINVAL;
2391 goto done;
2392 }
2393
2394 vep_session->wait_cont_idx =
Florin Coras134a9962018-08-28 11:32:04 -07002395 (vep_session->wait_cont_idx == session_handle) ?
2396 session->vep.next_sh : vep_session->wait_cont_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002397
Florin Coras134a9962018-08-28 11:32:04 -07002398 if (session->vep.prev_sh == vep_handle)
2399 vep_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002400 else
2401 {
Florin Coras7e12d942018-06-27 14:32:43 -07002402 vcl_session_t *prev_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002403 prev_session = vcl_session_get_w_handle (wrk, session->vep.prev_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002404 if (PREDICT_FALSE (!prev_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002405 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002406 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002407 "vep.prev_sid (%u) on sid (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002408 getpid (), session->vep.prev_sh, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002409 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002410 }
Florin Coras134a9962018-08-28 11:32:04 -07002411 ASSERT (prev_session->vep.next_sh == session_handle);
2412 prev_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002413 }
Florin Coras134a9962018-08-28 11:32:04 -07002414 if (session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002415 {
Florin Coras7e12d942018-06-27 14:32:43 -07002416 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002417 next_session = vcl_session_get_w_handle (wrk, session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002418 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002419 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002420 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002421 "vep.next_sid (%u) on sid (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002422 getpid (), session->vep.next_sh, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002423 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002424 }
Florin Coras134a9962018-08-28 11:32:04 -07002425 ASSERT (next_session->vep.prev_sh == session_handle);
2426 next_session->vep.prev_sh = session->vep.prev_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002427 }
2428
2429 memset (&session->vep, 0, sizeof (session->vep));
Florin Coras134a9962018-08-28 11:32:04 -07002430 session->vep.next_sh = ~0;
2431 session->vep.prev_sh = ~0;
2432 session->vep.vep_sh = ~0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002433 session->is_vep_session = 0;
Florin Coras0d427d82018-06-27 03:24:07 -07002434 VDBG (1, "VCL<%d>: EPOLL_CTL_DEL: vep_idx %u, sid %u!",
Florin Coras134a9962018-08-28 11:32:04 -07002435 getpid (), vep_handle, session_handle);
2436 vcl_evt (VCL_EVT_EPOLL_CTLDEL, session, vep_sh);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002437 break;
2438
2439 default:
Dave Wallace048b1d62018-01-03 22:24:41 -05002440 clib_warning ("VCL<%d>: ERROR: Invalid operation (%d)!", getpid (), op);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002441 rv = VPPCOM_EINVAL;
2442 }
2443
Florin Coras134a9962018-08-28 11:32:04 -07002444 vep_verify_epoll_chain (wrk, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002445
2446done:
Dave Wallacef7f809c2017-10-03 01:48:42 -04002447 return rv;
2448}
2449
Florin Coras86f04502018-09-12 16:08:01 -07002450static inline void
2451vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
2452 struct epoll_event *events, u32 * num_ev)
Florin Coras54693d22018-07-17 10:46:29 -07002453{
2454 session_disconnected_msg_t *disconnected_msg;
2455 session_connected_msg_t *connected_msg;
2456 session_accepted_msg_t *accepted_msg;
Florin Coras54693d22018-07-17 10:46:29 -07002457 u64 session_evt_data = ~0, handle;
Florin Coras99368312018-08-02 10:45:44 -07002458 u32 sid = ~0, session_events;
Florin Coras54693d22018-07-17 10:46:29 -07002459 vcl_session_msg_t *vcl_msg;
2460 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07002461 u8 add_event = 0;
2462
2463 switch (e->event_type)
2464 {
2465 case FIFO_EVENT_APP_RX:
2466 ASSERT (e->fifo->client_thread_index == vcl_get_worker_index ());
2467 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2468 sid = e->fifo->client_session_index;
2469 session = vcl_session_get (wrk, sid);
2470 session_events = session->vep.ev.events;
Florin Corasaa27eb92018-10-13 12:20:01 -07002471 if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
Florin Coras86f04502018-09-12 16:08:01 -07002472 break;
2473 add_event = 1;
2474 events[*num_ev].events |= EPOLLIN;
2475 session_evt_data = session->vep.ev.data.u64;
Florin Corasaa27eb92018-10-13 12:20:01 -07002476 session->has_rx_evt = 1;
Florin Coras86f04502018-09-12 16:08:01 -07002477 break;
2478 case FIFO_EVENT_APP_TX:
2479 sid = e->fifo->client_session_index;
2480 session = vcl_session_get (wrk, sid);
2481 session_events = session->vep.ev.events;
2482 if (!(EPOLLOUT & session_events))
2483 break;
2484 add_event = 1;
2485 events[*num_ev].events |= EPOLLOUT;
2486 session_evt_data = session->vep.ev.data.u64;
2487 break;
2488 case SESSION_IO_EVT_CT_TX:
2489 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2490 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0);
2491 sid = session->session_index;
2492 session_events = session->vep.ev.events;
Florin Corasaa27eb92018-10-13 12:20:01 -07002493 if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
Florin Coras86f04502018-09-12 16:08:01 -07002494 break;
2495 add_event = 1;
2496 events[*num_ev].events |= EPOLLIN;
2497 session_evt_data = session->vep.ev.data.u64;
Florin Corasaa27eb92018-10-13 12:20:01 -07002498 session->has_rx_evt = 1;
Florin Coras86f04502018-09-12 16:08:01 -07002499 break;
2500 case SESSION_IO_EVT_CT_RX:
2501 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1);
2502 sid = session->session_index;
2503 session_events = session->vep.ev.events;
2504 if (!(EPOLLOUT & session_events))
2505 break;
2506 add_event = 1;
2507 events[*num_ev].events |= EPOLLOUT;
2508 session_evt_data = session->vep.ev.data.u64;
2509 break;
2510 case SESSION_CTRL_EVT_ACCEPTED:
2511 accepted_msg = (session_accepted_msg_t *) e->data;
2512 handle = accepted_msg->listener_handle;
2513 session = vcl_session_table_lookup_listener (wrk, handle);
2514 if (!session)
2515 {
2516 clib_warning ("VCL<%d>: ERROR: couldn't find listen session:"
2517 "listener handle %llx", getpid (), handle);
2518 break;
2519 }
2520
2521 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
2522 vcl_msg->accepted_msg = *accepted_msg;
2523 session_events = session->vep.ev.events;
2524 if (!(EPOLLIN & session_events))
2525 break;
2526
2527 add_event = 1;
2528 events[*num_ev].events |= EPOLLIN;
2529 session_evt_data = session->vep.ev.data.u64;
2530 break;
2531 case SESSION_CTRL_EVT_CONNECTED:
2532 connected_msg = (session_connected_msg_t *) e->data;
2533 vcl_session_connected_handler (wrk, connected_msg);
2534 /* Generate EPOLLOUT because there's no connected event */
2535 sid = vcl_session_index_from_vpp_handle (wrk, connected_msg->handle);
2536 session = vcl_session_get (wrk, sid);
2537 session_events = session->vep.ev.events;
2538 if (EPOLLOUT & session_events)
2539 {
2540 add_event = 1;
2541 events[*num_ev].events |= EPOLLOUT;
2542 session_evt_data = session->vep.ev.data.u64;
2543 }
2544 break;
2545 case SESSION_CTRL_EVT_DISCONNECTED:
2546 disconnected_msg = (session_disconnected_msg_t *) e->data;
2547 sid = vcl_session_index_from_vpp_handle (wrk, disconnected_msg->handle);
2548 if (!(session = vcl_session_get (wrk, sid)))
2549 break;
2550 add_event = 1;
2551 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2552 session_evt_data = session->vep.ev.data.u64;
2553 session_events = session->vep.ev.events;
2554 break;
2555 case SESSION_CTRL_EVT_RESET:
2556 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
2557 if (!(session = vcl_session_get (wrk, sid)))
2558 break;
2559 add_event = 1;
2560 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2561 session_evt_data = session->vep.ev.data.u64;
2562 session_events = session->vep.ev.events;
2563 break;
2564 default:
2565 VDBG (0, "unhandled: %u", e->event_type);
2566 break;
2567 }
2568
2569 if (add_event)
2570 {
2571 events[*num_ev].data.u64 = session_evt_data;
2572 if (EPOLLONESHOT & session_events)
2573 {
2574 session = vcl_session_get (wrk, sid);
2575 session->vep.ev.events = 0;
2576 }
2577 *num_ev += 1;
2578 }
2579}
2580
2581static int
2582vcl_epoll_wait_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
2583 struct epoll_event *events, u32 maxevents,
2584 double wait_for_time, u32 * num_ev)
2585{
Florin Coras99368312018-08-02 10:45:44 -07002586 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07002587 session_event_t *e;
Florin Coras54693d22018-07-17 10:46:29 -07002588 int i;
2589
Florin Coras539663c2018-09-28 14:59:37 -07002590 if (vec_len (wrk->mq_msg_vector) && svm_msg_q_is_empty (mq))
2591 goto handle_dequeued;
2592
Florin Coras54693d22018-07-17 10:46:29 -07002593 svm_msg_q_lock (mq);
2594 if (svm_msg_q_is_empty (mq))
2595 {
2596 if (!wait_for_time)
2597 {
2598 svm_msg_q_unlock (mq);
2599 return 0;
2600 }
2601 else if (wait_for_time < 0)
2602 {
2603 svm_msg_q_wait (mq);
2604 }
2605 else
2606 {
Florin Coras60f1fc12018-08-16 14:57:31 -07002607 if (svm_msg_q_timedwait (mq, wait_for_time / 1e3))
Florin Coras54693d22018-07-17 10:46:29 -07002608 {
2609 svm_msg_q_unlock (mq);
2610 return 0;
2611 }
2612 }
2613 }
Florin Coras134a9962018-08-28 11:32:04 -07002614 vcl_mq_dequeue_batch (wrk, mq);
Florin Coras54693d22018-07-17 10:46:29 -07002615 svm_msg_q_unlock (mq);
2616
Florin Coras539663c2018-09-28 14:59:37 -07002617handle_dequeued:
Florin Coras134a9962018-08-28 11:32:04 -07002618 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07002619 {
Florin Coras134a9962018-08-28 11:32:04 -07002620 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07002621 e = svm_msg_q_msg_data (mq, msg);
Florin Corasaa27eb92018-10-13 12:20:01 -07002622 if (*num_ev < maxevents)
2623 vcl_epoll_wait_handle_mq_event (wrk, e, events, num_ev);
2624 else
2625 vec_add1 (wrk->unhandled_evts_vector, *e);
Florin Coras99368312018-08-02 10:45:44 -07002626 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002627 }
Florin Corasaa27eb92018-10-13 12:20:01 -07002628 vec_reset_length (wrk->mq_msg_vector);
Florin Coras86f04502018-09-12 16:08:01 -07002629
Florin Coras54693d22018-07-17 10:46:29 -07002630 return *num_ev;
2631}
2632
Florin Coras99368312018-08-02 10:45:44 -07002633static int
Florin Coras134a9962018-08-28 11:32:04 -07002634vppcom_epoll_wait_condvar (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002635 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002636{
2637 vcl_cut_through_registration_t *cr;
2638 double total_wait = 0, wait_slice;
Florin Coras99368312018-08-02 10:45:44 -07002639 int rv;
2640
2641 wait_for_time = (wait_for_time == -1) ? (double) 10e9 : wait_for_time;
Florin Coras134a9962018-08-28 11:32:04 -07002642 wait_slice = wrk->cut_through_registrations ? 10e-6 : wait_for_time;
Florin Coras99368312018-08-02 10:45:44 -07002643
2644 do
2645 {
Florin Coras134a9962018-08-28 11:32:04 -07002646 vcl_ct_registration_lock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002647 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002648 pool_foreach (cr, wrk->cut_through_registrations, ({
Florin Coras86f04502018-09-12 16:08:01 -07002649 vcl_epoll_wait_handle_mq (wrk, cr->mq, events, maxevents, 0, &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002650 }));
2651 /* *INDENT-ON* */
Florin Coras134a9962018-08-28 11:32:04 -07002652 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002653
Florin Coras134a9962018-08-28 11:32:04 -07002654 rv = vcl_epoll_wait_handle_mq (wrk, wrk->app_event_queue, events,
Florin Coras86f04502018-09-12 16:08:01 -07002655 maxevents, n_evts ? 0 : wait_slice,
2656 &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002657 if (rv)
2658 total_wait += wait_slice;
Florin Coras86f04502018-09-12 16:08:01 -07002659 if (n_evts)
2660 return n_evts;
Florin Coras99368312018-08-02 10:45:44 -07002661 }
2662 while (total_wait < wait_for_time);
Florin Coras86f04502018-09-12 16:08:01 -07002663 return n_evts;
Florin Coras99368312018-08-02 10:45:44 -07002664}
2665
2666static int
Florin Coras134a9962018-08-28 11:32:04 -07002667vppcom_epoll_wait_eventfd (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002668 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002669{
2670 vcl_mq_evt_conn_t *mqc;
2671 int __clib_unused n_read;
2672 int n_mq_evts, i;
Florin Coras99368312018-08-02 10:45:44 -07002673 u64 buf;
2674
Florin Coras134a9962018-08-28 11:32:04 -07002675 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
Florin Corasa4878ed2018-10-12 13:09:36 -07002676again:
Florin Coras134a9962018-08-28 11:32:04 -07002677 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2678 vec_len (wrk->mq_events), wait_for_time);
Florin Coras99368312018-08-02 10:45:44 -07002679 for (i = 0; i < n_mq_evts; i++)
2680 {
Florin Coras134a9962018-08-28 11:32:04 -07002681 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002682 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002683 vcl_epoll_wait_handle_mq (wrk, mqc->mq, events, maxevents, 0, &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002684 }
Florin Corasa4878ed2018-10-12 13:09:36 -07002685 if (!n_evts && n_mq_evts > 0)
2686 goto again;
Florin Coras99368312018-08-02 10:45:44 -07002687
2688 return (int) n_evts;
2689}
2690
Dave Wallacef7f809c2017-10-03 01:48:42 -04002691int
Florin Coras134a9962018-08-28 11:32:04 -07002692vppcom_epoll_wait (uint32_t vep_handle, struct epoll_event *events,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002693 int maxevents, double wait_for_time)
2694{
Florin Coras134a9962018-08-28 11:32:04 -07002695 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002696 vcl_session_t *vep_session;
Florin Coras86f04502018-09-12 16:08:01 -07002697 u32 n_evts = 0;
2698 int i;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002699
2700 if (PREDICT_FALSE (maxevents <= 0))
2701 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002702 clib_warning ("VCL<%d>: ERROR: Invalid maxevents (%d)!",
Dave Wallace4878cbe2017-11-21 03:45:09 -05002703 getpid (), maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002704 return VPPCOM_EINVAL;
2705 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002706
Florin Coras134a9962018-08-28 11:32:04 -07002707 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras14598772018-09-04 19:47:52 -07002708 if (!vep_session)
2709 return VPPCOM_EBADFD;
2710
Florin Coras54693d22018-07-17 10:46:29 -07002711 if (PREDICT_FALSE (!vep_session->is_vep))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002712 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002713 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
Florin Coras134a9962018-08-28 11:32:04 -07002714 getpid (), vep_handle);
Florin Coras54693d22018-07-17 10:46:29 -07002715 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002716 }
Florin Coras54693d22018-07-17 10:46:29 -07002717
2718 memset (events, 0, sizeof (*events) * maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002719
Florin Coras86f04502018-09-12 16:08:01 -07002720 if (vec_len (wrk->unhandled_evts_vector))
2721 {
2722 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2723 {
2724 vcl_epoll_wait_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i],
2725 events, &n_evts);
2726 if (n_evts == maxevents)
2727 {
2728 i += 1;
2729 break;
2730 }
2731 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002732
Florin Coras86f04502018-09-12 16:08:01 -07002733 vec_delete (wrk->unhandled_evts_vector, i, 0);
2734 }
2735
2736 if (vcm->cfg.use_mq_eventfd)
2737 return vppcom_epoll_wait_eventfd (wrk, events, maxevents, n_evts,
2738 wait_for_time);
2739
2740 return vppcom_epoll_wait_condvar (wrk, events, maxevents, n_evts,
2741 wait_for_time);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002742}
2743
Dave Wallace35830af2017-10-09 01:43:42 -04002744int
Florin Coras134a9962018-08-28 11:32:04 -07002745vppcom_session_attr (uint32_t session_handle, uint32_t op,
Dave Wallace35830af2017-10-09 01:43:42 -04002746 void *buffer, uint32_t * buflen)
2747{
Florin Coras134a9962018-08-28 11:32:04 -07002748 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002749 vcl_session_t *session;
Dave Wallace35830af2017-10-09 01:43:42 -04002750 int rv = VPPCOM_OK;
2751 u32 *flags = buffer;
Steven2199aab2017-10-15 20:18:47 -07002752 vppcom_endpt_t *ep = buffer;
Dave Wallace35830af2017-10-09 01:43:42 -04002753
Florin Coras134a9962018-08-28 11:32:04 -07002754 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002755 if (!session)
2756 return VPPCOM_EBADFD;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002757
Dave Wallace35830af2017-10-09 01:43:42 -04002758 switch (op)
2759 {
2760 case VPPCOM_ATTR_GET_NREAD:
Florin Coras54693d22018-07-17 10:46:29 -07002761 rv = vppcom_session_read_ready (session);
Florin Coras0d427d82018-06-27 03:24:07 -07002762 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d",
2763 getpid (), rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002764 break;
2765
Dave Wallace227867f2017-11-13 21:21:53 -05002766 case VPPCOM_ATTR_GET_NWRITE:
Florin Coras134a9962018-08-28 11:32:04 -07002767 rv = vppcom_session_write_ready (session);
Florin Coras0d427d82018-06-27 03:24:07 -07002768 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d",
Florin Coras134a9962018-08-28 11:32:04 -07002769 getpid (), session_handle, rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002770 break;
2771
2772 case VPPCOM_ATTR_GET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002773 if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002774 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002775 *flags = O_RDWR | (VCL_SESS_ATTR_TEST (session->attr,
2776 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002777 *buflen = sizeof (*flags);
Florin Coras0d427d82018-06-27 03:24:07 -07002778 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_FLAGS: sid %u, flags = 0x%08x, "
2779 "is_nonblocking = %u", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002780 session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07002781 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002782 }
2783 else
2784 rv = VPPCOM_EINVAL;
2785 break;
2786
2787 case VPPCOM_ATTR_SET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002788 if (PREDICT_TRUE (buffer && buflen && (*buflen == sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002789 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002790 if (*flags & O_NONBLOCK)
2791 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
2792 else
2793 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_NONBLOCK);
2794
Florin Coras0d427d82018-06-27 03:24:07 -07002795 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_FLAGS: sid %u, flags = 0x%08x,"
2796 " is_nonblocking = %u",
Florin Coras134a9962018-08-28 11:32:04 -07002797 getpid (), session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07002798 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002799 }
2800 else
2801 rv = VPPCOM_EINVAL;
2802 break;
2803
2804 case VPPCOM_ATTR_GET_PEER_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002805 if (PREDICT_TRUE (buffer && buflen &&
2806 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002807 {
Florin Coras7e12d942018-06-27 14:32:43 -07002808 ep->is_ip4 = session->transport.is_ip4;
2809 ep->port = session->transport.rmt_port;
2810 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05002811 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
2812 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07002813 else
Dave Barach178cf492018-11-13 16:34:13 -05002814 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
2815 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07002816 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07002817 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = %u, "
2818 "addr = %U, port %u", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002819 session_handle, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07002820 &session->transport.rmt_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002821 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2822 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002823 }
2824 else
2825 rv = VPPCOM_EINVAL;
2826 break;
2827
2828 case VPPCOM_ATTR_GET_LCL_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002829 if (PREDICT_TRUE (buffer && buflen &&
2830 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002831 {
Florin Coras7e12d942018-06-27 14:32:43 -07002832 ep->is_ip4 = session->transport.is_ip4;
2833 ep->port = session->transport.lcl_port;
2834 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05002835 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip4,
2836 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07002837 else
Dave Barach178cf492018-11-13 16:34:13 -05002838 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip6,
2839 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07002840 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07002841 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = %u,"
2842 " addr = %U port %d", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002843 session_handle, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07002844 &session->transport.lcl_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002845 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2846 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002847 }
2848 else
2849 rv = VPPCOM_EINVAL;
2850 break;
Stevenb5a11602017-10-11 09:59:30 -07002851
Dave Wallace048b1d62018-01-03 22:24:41 -05002852 case VPPCOM_ATTR_GET_LIBC_EPFD:
2853 rv = session->libc_epfd;
Florin Coras0d427d82018-06-27 03:24:07 -07002854 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d",
2855 getpid (), rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002856 break;
2857
2858 case VPPCOM_ATTR_SET_LIBC_EPFD:
2859 if (PREDICT_TRUE (buffer && buflen &&
2860 (*buflen == sizeof (session->libc_epfd))))
2861 {
2862 session->libc_epfd = *(int *) buffer;
2863 *buflen = sizeof (session->libc_epfd);
2864
Florin Coras0d427d82018-06-27 03:24:07 -07002865 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_LIBC_EPFD: libc_epfd %d, "
2866 "buflen %d", getpid (), session->libc_epfd, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002867 }
2868 else
2869 rv = VPPCOM_EINVAL;
2870 break;
2871
2872 case VPPCOM_ATTR_GET_PROTOCOL:
2873 if (buffer && buflen && (*buflen >= sizeof (int)))
2874 {
Florin Coras7e12d942018-06-27 14:32:43 -07002875 *(int *) buffer = session->session_type;
Dave Wallace048b1d62018-01-03 22:24:41 -05002876 *buflen = sizeof (int);
2877
Florin Coras0d427d82018-06-27 03:24:07 -07002878 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_PROTOCOL: %d (%s), buflen %d",
2879 getpid (), *(int *) buffer, *(int *) buffer ? "UDP" : "TCP",
2880 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002881 }
2882 else
2883 rv = VPPCOM_EINVAL;
2884 break;
2885
2886 case VPPCOM_ATTR_GET_LISTEN:
2887 if (buffer && buflen && (*buflen >= sizeof (int)))
2888 {
2889 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2890 VCL_SESS_ATTR_LISTEN);
2891 *buflen = sizeof (int);
2892
Florin Coras0d427d82018-06-27 03:24:07 -07002893 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LISTEN: %d, buflen %d",
2894 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002895 }
2896 else
2897 rv = VPPCOM_EINVAL;
2898 break;
2899
2900 case VPPCOM_ATTR_GET_ERROR:
2901 if (buffer && buflen && (*buflen >= sizeof (int)))
2902 {
2903 *(int *) buffer = 0;
2904 *buflen = sizeof (int);
2905
Florin Coras0d427d82018-06-27 03:24:07 -07002906 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_ERROR: %d, buflen %d, #VPP-TBD#",
2907 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002908 }
2909 else
2910 rv = VPPCOM_EINVAL;
2911 break;
2912
2913 case VPPCOM_ATTR_GET_TX_FIFO_LEN:
2914 if (buffer && buflen && (*buflen >= sizeof (u32)))
2915 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002916
2917 /* VPP-TBD */
2918 *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002919 session->tx_fifo ? session->tx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05002920 vcm->cfg.tx_fifo_size);
2921 *buflen = sizeof (u32);
2922
Florin Coras0d427d82018-06-27 03:24:07 -07002923 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), "
2924 "buflen %d, #VPP-TBD#", getpid (),
2925 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002926 }
2927 else
2928 rv = VPPCOM_EINVAL;
2929 break;
2930
2931 case VPPCOM_ATTR_SET_TX_FIFO_LEN:
2932 if (buffer && buflen && (*buflen == sizeof (u32)))
2933 {
2934 /* VPP-TBD */
2935 session->sndbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07002936 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), "
2937 "buflen %d, #VPP-TBD#", getpid (),
2938 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002939 }
2940 else
2941 rv = VPPCOM_EINVAL;
2942 break;
2943
2944 case VPPCOM_ATTR_GET_RX_FIFO_LEN:
2945 if (buffer && buflen && (*buflen >= sizeof (u32)))
2946 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002947
2948 /* VPP-TBD */
2949 *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002950 session->rx_fifo ? session->rx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05002951 vcm->cfg.rx_fifo_size);
2952 *buflen = sizeof (u32);
2953
Florin Coras0d427d82018-06-27 03:24:07 -07002954 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_RX_FIFO_LEN: %u (0x%x), "
2955 "buflen %d, #VPP-TBD#", getpid (),
2956 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002957 }
2958 else
2959 rv = VPPCOM_EINVAL;
2960 break;
2961
2962 case VPPCOM_ATTR_SET_RX_FIFO_LEN:
2963 if (buffer && buflen && (*buflen == sizeof (u32)))
2964 {
2965 /* VPP-TBD */
2966 session->rcvbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07002967 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_RX_FIFO_LEN: %u (0x%x), "
2968 "buflen %d, #VPP-TBD#", getpid (),
2969 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002970 }
2971 else
2972 rv = VPPCOM_EINVAL;
2973 break;
2974
2975 case VPPCOM_ATTR_GET_REUSEADDR:
2976 if (buffer && buflen && (*buflen >= sizeof (int)))
2977 {
2978 /* VPP-TBD */
2979 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2980 VCL_SESS_ATTR_REUSEADDR);
2981 *buflen = sizeof (int);
2982
Florin Coras0d427d82018-06-27 03:24:07 -07002983 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEADDR: %d, "
2984 "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002985 }
2986 else
2987 rv = VPPCOM_EINVAL;
2988 break;
2989
Stevenb5a11602017-10-11 09:59:30 -07002990 case VPPCOM_ATTR_SET_REUSEADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002991 if (buffer && buflen && (*buflen == sizeof (int)) &&
2992 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
2993 {
2994 /* VPP-TBD */
2995 if (*(int *) buffer)
2996 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEADDR);
2997 else
2998 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEADDR);
2999
Florin Coras0d427d82018-06-27 03:24:07 -07003000 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEADDR: %d, buflen %d,"
3001 " #VPP-TBD#", getpid (),
3002 VCL_SESS_ATTR_TEST (session->attr,
3003 VCL_SESS_ATTR_REUSEADDR), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003004 }
3005 else
3006 rv = VPPCOM_EINVAL;
3007 break;
3008
3009 case VPPCOM_ATTR_GET_REUSEPORT:
3010 if (buffer && buflen && (*buflen >= sizeof (int)))
3011 {
3012 /* VPP-TBD */
3013 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3014 VCL_SESS_ATTR_REUSEPORT);
3015 *buflen = sizeof (int);
3016
Florin Coras0d427d82018-06-27 03:24:07 -07003017 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEPORT: %d, buflen %d,"
3018 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003019 }
3020 else
3021 rv = VPPCOM_EINVAL;
3022 break;
3023
3024 case VPPCOM_ATTR_SET_REUSEPORT:
3025 if (buffer && buflen && (*buflen == sizeof (int)) &&
3026 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
3027 {
3028 /* VPP-TBD */
3029 if (*(int *) buffer)
3030 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEPORT);
3031 else
3032 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEPORT);
3033
Florin Coras0d427d82018-06-27 03:24:07 -07003034 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEPORT: %d, buflen %d,"
3035 " #VPP-TBD#", getpid (),
3036 VCL_SESS_ATTR_TEST (session->attr,
3037 VCL_SESS_ATTR_REUSEPORT), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003038 }
3039 else
3040 rv = VPPCOM_EINVAL;
3041 break;
3042
3043 case VPPCOM_ATTR_GET_BROADCAST:
3044 if (buffer && buflen && (*buflen >= sizeof (int)))
3045 {
3046 /* VPP-TBD */
3047 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3048 VCL_SESS_ATTR_BROADCAST);
3049 *buflen = sizeof (int);
3050
Florin Coras0d427d82018-06-27 03:24:07 -07003051 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_BROADCAST: %d, buflen %d,"
3052 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003053 }
3054 else
3055 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003056 break;
3057
3058 case VPPCOM_ATTR_SET_BROADCAST:
Dave Wallace048b1d62018-01-03 22:24:41 -05003059 if (buffer && buflen && (*buflen == sizeof (int)))
3060 {
3061 /* VPP-TBD */
3062 if (*(int *) buffer)
3063 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_BROADCAST);
3064 else
3065 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_BROADCAST);
3066
Florin Coras0d427d82018-06-27 03:24:07 -07003067 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_BROADCAST: %d, buflen %d, "
3068 "#VPP-TBD#", getpid (),
3069 VCL_SESS_ATTR_TEST (session->attr,
3070 VCL_SESS_ATTR_BROADCAST), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003071 }
3072 else
3073 rv = VPPCOM_EINVAL;
3074 break;
3075
3076 case VPPCOM_ATTR_GET_V6ONLY:
3077 if (buffer && buflen && (*buflen >= sizeof (int)))
3078 {
3079 /* VPP-TBD */
3080 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3081 VCL_SESS_ATTR_V6ONLY);
3082 *buflen = sizeof (int);
3083
Florin Coras0d427d82018-06-27 03:24:07 -07003084 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_V6ONLY: %d, buflen %d, "
3085 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003086 }
3087 else
3088 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003089 break;
3090
3091 case VPPCOM_ATTR_SET_V6ONLY:
Dave Wallace048b1d62018-01-03 22:24:41 -05003092 if (buffer && buflen && (*buflen == sizeof (int)))
3093 {
3094 /* VPP-TBD */
3095 if (*(int *) buffer)
3096 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_V6ONLY);
3097 else
3098 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_V6ONLY);
3099
Florin Coras0d427d82018-06-27 03:24:07 -07003100 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_V6ONLY: %d, buflen %d, "
3101 "#VPP-TBD#", getpid (),
3102 VCL_SESS_ATTR_TEST (session->attr,
3103 VCL_SESS_ATTR_V6ONLY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003104 }
3105 else
3106 rv = VPPCOM_EINVAL;
3107 break;
3108
3109 case VPPCOM_ATTR_GET_KEEPALIVE:
3110 if (buffer && buflen && (*buflen >= sizeof (int)))
3111 {
3112 /* VPP-TBD */
3113 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3114 VCL_SESS_ATTR_KEEPALIVE);
3115 *buflen = sizeof (int);
3116
Florin Coras0d427d82018-06-27 03:24:07 -07003117 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_KEEPALIVE: %d, buflen %d, "
3118 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003119 }
3120 else
3121 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003122 break;
Stevenbccd3392017-10-12 20:42:21 -07003123
3124 case VPPCOM_ATTR_SET_KEEPALIVE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003125 if (buffer && buflen && (*buflen == sizeof (int)))
3126 {
3127 /* VPP-TBD */
3128 if (*(int *) buffer)
3129 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3130 else
3131 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3132
Florin Coras0d427d82018-06-27 03:24:07 -07003133 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_KEEPALIVE: %d, buflen %d, "
3134 "#VPP-TBD#", getpid (),
3135 VCL_SESS_ATTR_TEST (session->attr,
3136 VCL_SESS_ATTR_KEEPALIVE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003137 }
3138 else
3139 rv = VPPCOM_EINVAL;
3140 break;
3141
3142 case VPPCOM_ATTR_GET_TCP_NODELAY:
3143 if (buffer && buflen && (*buflen >= sizeof (int)))
3144 {
3145 /* VPP-TBD */
3146 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3147 VCL_SESS_ATTR_TCP_NODELAY);
3148 *buflen = sizeof (int);
3149
Florin Coras0d427d82018-06-27 03:24:07 -07003150 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_NODELAY: %d, buflen %d, "
3151 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003152 }
3153 else
3154 rv = VPPCOM_EINVAL;
3155 break;
3156
3157 case VPPCOM_ATTR_SET_TCP_NODELAY:
3158 if (buffer && buflen && (*buflen == sizeof (int)))
3159 {
3160 /* VPP-TBD */
3161 if (*(int *) buffer)
3162 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3163 else
3164 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3165
Florin Coras0d427d82018-06-27 03:24:07 -07003166 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_NODELAY: %d, buflen %d, "
3167 "#VPP-TBD#", getpid (),
3168 VCL_SESS_ATTR_TEST (session->attr,
3169 VCL_SESS_ATTR_TCP_NODELAY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003170 }
3171 else
3172 rv = VPPCOM_EINVAL;
3173 break;
3174
3175 case VPPCOM_ATTR_GET_TCP_KEEPIDLE:
3176 if (buffer && buflen && (*buflen >= sizeof (int)))
3177 {
3178 /* VPP-TBD */
3179 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3180 VCL_SESS_ATTR_TCP_KEEPIDLE);
3181 *buflen = sizeof (int);
3182
Florin Coras0d427d82018-06-27 03:24:07 -07003183 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPIDLE: %d, buflen %d, "
3184 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003185 }
3186 else
3187 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003188 break;
3189
3190 case VPPCOM_ATTR_SET_TCP_KEEPIDLE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003191 if (buffer && buflen && (*buflen == sizeof (int)))
3192 {
3193 /* VPP-TBD */
3194 if (*(int *) buffer)
3195 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3196 else
3197 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3198
Florin Coras0d427d82018-06-27 03:24:07 -07003199 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPIDLE: %d, buflen %d, "
3200 "#VPP-TBD#", getpid (),
3201 VCL_SESS_ATTR_TEST (session->attr,
3202 VCL_SESS_ATTR_TCP_KEEPIDLE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003203 }
3204 else
3205 rv = VPPCOM_EINVAL;
3206 break;
3207
3208 case VPPCOM_ATTR_GET_TCP_KEEPINTVL:
3209 if (buffer && buflen && (*buflen >= sizeof (int)))
3210 {
3211 /* VPP-TBD */
3212 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3213 VCL_SESS_ATTR_TCP_KEEPINTVL);
3214 *buflen = sizeof (int);
3215
Florin Coras0d427d82018-06-27 03:24:07 -07003216 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPINTVL: %d, buflen %d, "
3217 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003218 }
3219 else
3220 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003221 break;
3222
3223 case VPPCOM_ATTR_SET_TCP_KEEPINTVL:
Dave Wallace048b1d62018-01-03 22:24:41 -05003224 if (buffer && buflen && (*buflen == sizeof (int)))
3225 {
3226 /* VPP-TBD */
3227 if (*(int *) buffer)
3228 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3229 else
3230 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3231
Florin Coras0d427d82018-06-27 03:24:07 -07003232 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPINTVL: %d, buflen %d, "
3233 "#VPP-TBD#", getpid (),
3234 VCL_SESS_ATTR_TEST (session->attr,
3235 VCL_SESS_ATTR_TCP_KEEPINTVL), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003236 }
3237 else
3238 rv = VPPCOM_EINVAL;
3239 break;
3240
3241 case VPPCOM_ATTR_GET_TCP_USER_MSS:
3242 if (buffer && buflen && (*buflen >= sizeof (u32)))
3243 {
3244 /* VPP-TBD */
3245 *(u32 *) buffer = session->user_mss;
3246 *buflen = sizeof (int);
3247
Florin Coras0d427d82018-06-27 03:24:07 -07003248 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d,"
3249 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003250 }
3251 else
3252 rv = VPPCOM_EINVAL;
3253 break;
3254
3255 case VPPCOM_ATTR_SET_TCP_USER_MSS:
3256 if (buffer && buflen && (*buflen == sizeof (u32)))
3257 {
3258 /* VPP-TBD */
3259 session->user_mss = *(u32 *) buffer;
3260
Florin Coras0d427d82018-06-27 03:24:07 -07003261 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_USER_MSS: %u, buflen %d, "
3262 "#VPP-TBD#", getpid (), session->user_mss, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003263 }
3264 else
3265 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003266 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003267
Florin Coras47c40e22018-11-26 17:01:36 -08003268 case VPPCOM_ATTR_GET_REFCNT:
3269 rv = vcl_session_get_refcnt (session);
3270 break;
3271
Dave Wallacee22aa742017-10-20 12:30:38 -04003272 default:
3273 rv = VPPCOM_EINVAL;
3274 break;
Dave Wallace35830af2017-10-09 01:43:42 -04003275 }
3276
Dave Wallace35830af2017-10-09 01:43:42 -04003277 return rv;
3278}
3279
Stevenac1f96d2017-10-24 16:03:58 -07003280int
Florin Coras134a9962018-08-28 11:32:04 -07003281vppcom_session_recvfrom (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003282 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3283{
Florin Coras134a9962018-08-28 11:32:04 -07003284 vcl_worker_t *wrk = vcl_worker_get_current ();
Stevenac1f96d2017-10-24 16:03:58 -07003285 int rv = VPPCOM_OK;
Florin Coras7e12d942018-06-27 14:32:43 -07003286 vcl_session_t *session = 0;
Stevenac1f96d2017-10-24 16:03:58 -07003287
3288 if (ep)
3289 {
Florin Coras134a9962018-08-28 11:32:04 -07003290 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07003291 if (PREDICT_FALSE (!session))
Stevenac1f96d2017-10-24 16:03:58 -07003292 {
Florin Coras0d427d82018-06-27 03:24:07 -07003293 VDBG (0, "VCL<%d>: invalid session, sid (%u) has been closed!",
Florin Coras134a9962018-08-28 11:32:04 -07003294 getpid (), session_handle);
Florin Coras460dce62018-07-27 05:45:06 -07003295 return VPPCOM_EBADFD;
Stevenac1f96d2017-10-24 16:03:58 -07003296 }
Florin Coras7e12d942018-06-27 14:32:43 -07003297 ep->is_ip4 = session->transport.is_ip4;
3298 ep->port = session->transport.rmt_port;
Stevenac1f96d2017-10-24 16:03:58 -07003299 }
Steven58f464e2017-10-25 12:33:12 -07003300
3301 if (flags == 0)
Florin Coras134a9962018-08-28 11:32:04 -07003302 rv = vppcom_session_read (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003303 else if (flags & MSG_PEEK)
Florin Coras134a9962018-08-28 11:32:04 -07003304 rv = vppcom_session_peek (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003305 else
3306 {
Dave Wallace048b1d62018-01-03 22:24:41 -05003307 clib_warning ("VCL<%d>: Unsupport flags for recvfrom %d",
3308 getpid (), flags);
Florin Coras460dce62018-07-27 05:45:06 -07003309 return VPPCOM_EAFNOSUPPORT;
Stevenac1f96d2017-10-24 16:03:58 -07003310 }
3311
Florin Coras99368312018-08-02 10:45:44 -07003312 if (ep)
3313 {
3314 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05003315 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
3316 sizeof (ip4_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003317 else
Dave Barach178cf492018-11-13 16:34:13 -05003318 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
3319 sizeof (ip6_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003320 }
Florin Coras460dce62018-07-27 05:45:06 -07003321
Stevenac1f96d2017-10-24 16:03:58 -07003322 return rv;
3323}
3324
3325int
Florin Coras134a9962018-08-28 11:32:04 -07003326vppcom_session_sendto (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003327 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3328{
Dave Wallace617dffa2017-10-26 14:47:06 -04003329 if (!buffer)
3330 return VPPCOM_EINVAL;
3331
3332 if (ep)
3333 {
3334 // TBD
3335 return VPPCOM_EINVAL;
3336 }
3337
3338 if (flags)
3339 {
3340 // TBD check the flags and do the right thing
Florin Coras0d427d82018-06-27 03:24:07 -07003341 VDBG (2, "VCL<%d>: handling flags 0x%u (%d) not implemented yet.",
3342 getpid (), flags, flags);
Dave Wallace617dffa2017-10-26 14:47:06 -04003343 }
3344
Florin Coras134a9962018-08-28 11:32:04 -07003345 return (vppcom_session_write (session_handle, buffer, buflen));
Stevenac1f96d2017-10-24 16:03:58 -07003346}
3347
Dave Wallace048b1d62018-01-03 22:24:41 -05003348int
3349vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time)
3350{
Florin Coras134a9962018-08-28 11:32:04 -07003351 vcl_worker_t *wrk = vcl_worker_get_current ();
3352 f64 timeout = clib_time_now (&wrk->clib_time) + wait_for_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05003353 u32 i, keep_trying = 1;
Florin Coras6917b942018-11-13 22:44:54 -08003354 svm_msg_q_msg_t msg;
3355 session_event_t *e;
Dave Wallace048b1d62018-01-03 22:24:41 -05003356 int rv, num_ev = 0;
3357
Florin Coras0d427d82018-06-27 03:24:07 -07003358 VDBG (3, "VCL<%d>: vp %p, nsids %u, wait_for_time %f",
3359 getpid (), vp, n_sids, wait_for_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05003360
3361 if (!vp)
3362 return VPPCOM_EFAULT;
3363
3364 do
3365 {
Florin Coras7e12d942018-06-27 14:32:43 -07003366 vcl_session_t *session;
Dave Wallace048b1d62018-01-03 22:24:41 -05003367
Florin Coras6917b942018-11-13 22:44:54 -08003368 /* Dequeue all events and drop all unhandled io events */
3369 while (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0) == 0)
3370 {
3371 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
3372 vcl_handle_mq_event (wrk, e);
3373 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
3374 }
3375 vec_reset_length (wrk->unhandled_evts_vector);
3376
Dave Wallace048b1d62018-01-03 22:24:41 -05003377 for (i = 0; i < n_sids; i++)
3378 {
Florin Coras134a9962018-08-28 11:32:04 -07003379 session = vcl_session_get (wrk, vp[i].sid);
Florin Coras070453d2018-08-24 17:04:27 -07003380 if (!session)
Florin Coras6917b942018-11-13 22:44:54 -08003381 {
3382 vp[i].revents = POLLHUP;
3383 num_ev++;
3384 continue;
3385 }
Dave Wallace048b1d62018-01-03 22:24:41 -05003386
Florin Coras6917b942018-11-13 22:44:54 -08003387 vp[i].revents = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003388
3389 if (POLLIN & vp[i].events)
3390 {
Florin Coras54693d22018-07-17 10:46:29 -07003391 rv = vppcom_session_read_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003392 if (rv > 0)
3393 {
Florin Coras6917b942018-11-13 22:44:54 -08003394 vp[i].revents |= POLLIN;
Dave Wallace048b1d62018-01-03 22:24:41 -05003395 num_ev++;
3396 }
3397 else if (rv < 0)
3398 {
3399 switch (rv)
3400 {
3401 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003402 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003403 break;
3404
3405 default:
Florin Coras6917b942018-11-13 22:44:54 -08003406 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003407 break;
3408 }
3409 num_ev++;
3410 }
3411 }
3412
3413 if (POLLOUT & vp[i].events)
3414 {
Florin Coras134a9962018-08-28 11:32:04 -07003415 rv = vppcom_session_write_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003416 if (rv > 0)
3417 {
Florin Coras6917b942018-11-13 22:44:54 -08003418 vp[i].revents |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05003419 num_ev++;
3420 }
3421 else if (rv < 0)
3422 {
3423 switch (rv)
3424 {
3425 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003426 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003427 break;
3428
3429 default:
Florin Coras6917b942018-11-13 22:44:54 -08003430 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003431 break;
3432 }
3433 num_ev++;
3434 }
3435 }
3436
Dave Wallace7e607a72018-06-18 18:41:32 -04003437 if (0) // Note "done:" label used by VCL_SESSION_LOCK_AND_GET()
Dave Wallace048b1d62018-01-03 22:24:41 -05003438 {
Florin Coras6917b942018-11-13 22:44:54 -08003439 vp[i].revents = POLLNVAL;
Dave Wallace048b1d62018-01-03 22:24:41 -05003440 num_ev++;
3441 }
3442 }
3443 if (wait_for_time != -1)
Florin Coras134a9962018-08-28 11:32:04 -07003444 keep_trying = (clib_time_now (&wrk->clib_time) <= timeout) ? 1 : 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003445 }
3446 while ((num_ev == 0) && keep_trying);
3447
3448 if (VPPCOM_DEBUG > 3)
3449 {
3450 clib_warning ("VCL<%d>: returning %d", getpid (), num_ev);
3451 for (i = 0; i < n_sids; i++)
3452 {
3453 clib_warning ("VCL<%d>: vp[%d].sid %d (0x%x), .events 0x%x, "
3454 ".revents 0x%x", getpid (), i, vp[i].sid, vp[i].sid,
Florin Coras6917b942018-11-13 22:44:54 -08003455 vp[i].events, vp[i].revents);
Dave Wallace048b1d62018-01-03 22:24:41 -05003456 }
3457 }
3458 return num_ev;
3459}
3460
Florin Coras99368312018-08-02 10:45:44 -07003461int
3462vppcom_mq_epoll_fd (void)
3463{
Florin Coras134a9962018-08-28 11:32:04 -07003464 vcl_worker_t *wrk = vcl_worker_get_current ();
3465 return wrk->mqs_epfd;
3466}
3467
3468int
3469vppcom_session_index (uint32_t session_handle)
3470{
3471 return session_handle & 0xFFFFFF;
3472}
3473
3474int
Florin Coras30e273b2018-11-27 00:04:59 -08003475vppcom_session_handle (uint32_t session_index)
3476{
Florin Coras47c40e22018-11-26 17:01:36 -08003477 return (vcl_get_worker_index () << 24) | session_index;
Florin Coras30e273b2018-11-27 00:04:59 -08003478}
3479
3480int
Florin Coras134a9962018-08-28 11:32:04 -07003481vppcom_worker_register (void)
3482{
Florin Coras47c40e22018-11-26 17:01:36 -08003483 if (!vcl_worker_alloc_and_init ())
3484 return VPPCOM_EEXIST;
3485
3486 if (vcl_worker_set_bapi ())
3487 return VPPCOM_EEXIST;
3488
3489 if (vcl_worker_register_with_vpp ())
3490 return VPPCOM_EEXIST;
3491
3492 return VPPCOM_OK;
Florin Coras99368312018-08-02 10:45:44 -07003493}
3494
Florin Corasdfe4cf42018-11-28 22:13:45 -08003495int
3496vppcom_worker_index (void)
3497{
3498 return vcl_get_worker_index ();
3499}
3500
Dave Wallacee22aa742017-10-20 12:30:38 -04003501/*
3502 * fd.io coding-style-patch-verification: ON
3503 *
3504 * Local Variables:
3505 * eval: (c-set-style "gnu")
3506 * End:
3507 */