blob: 0eaab6cbd6bc5ca87a301a0e00a864184cc171b3 [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);
Florin Coraseaec2a62018-12-04 16:34:05 -0800740 if (!child_wrk)
741 goto done;
742
743 if (si && si->si_pid != child_wrk->current_pid)
Florin Coras01f3f892018-12-02 12:45:53 -0800744 {
745 VDBG (0, "unexpected child pid %u", si->si_pid);
Florin Coraseaec2a62018-12-04 16:34:05 -0800746 goto done;
Florin Coras01f3f892018-12-02 12:45:53 -0800747 }
Florin Coraseaec2a62018-12-04 16:34:05 -0800748 vcl_cleanup_forked_child (wrk, child_wrk);
Florin Coras01f3f892018-12-02 12:45:53 -0800749
Florin Coraseaec2a62018-12-04 16:34:05 -0800750done:
Florin Coras01f3f892018-12-02 12:45:53 -0800751 if (old_sa.sa_flags & SA_SIGINFO)
752 {
753 void (*fn) (int, siginfo_t *, void *) = old_sa.sa_sigaction;
754 fn (signum, si, uc);
755 }
756 else
757 {
758 void (*fn) (int) = old_sa.sa_handler;
759 if (fn)
760 fn (signum);
761 }
762}
763
764static void
765vcl_incercept_sigchld ()
766{
767 struct sigaction sa;
768 clib_memset (&sa, 0, sizeof (sa));
769 sa.sa_sigaction = vcl_intercept_sigchld_handler;
770 sa.sa_flags = SA_SIGINFO;
771 if (sigaction (SIGCHLD, &sa, &old_sa))
772 {
773 VERR ("couldn't intercept sigchld");
774 exit (-1);
775 }
776}
777
778static void
779vcl_app_pre_fork (void)
780{
781 vcl_incercept_sigchld ();
782}
783
784static void
Florin Coras053a0e42018-11-13 15:52:38 -0800785vcl_app_fork_child_handler (void)
786{
Florin Coras01f3f892018-12-02 12:45:53 -0800787 int rv, parent_wrk_index;
788 vcl_worker_t *parent_wrk;
Florin Coras053a0e42018-11-13 15:52:38 -0800789 u8 *child_name;
Florin Coras053a0e42018-11-13 15:52:38 -0800790
Florin Coras01f3f892018-12-02 12:45:53 -0800791 parent_wrk_index = vcl_get_worker_index ();
792 VDBG (0, "initializing forked child with parent wrk %u", parent_wrk_index);
Florin Coras053a0e42018-11-13 15:52:38 -0800793
Florin Coras47c40e22018-11-26 17:01:36 -0800794 /*
795 * Allocate worker
796 */
Florin Coras47c40e22018-11-26 17:01:36 -0800797 vcl_set_worker_index (~0);
798 if (!vcl_worker_alloc_and_init ())
799 VERR ("couldn't allocate new worker");
800
801 /*
802 * Attach to binary api
803 */
804 child_name = format (0, "%v-child-%u%c", vcm->app_name, getpid (), 0);
Florin Coras053a0e42018-11-13 15:52:38 -0800805 vcl_cleanup_bapi ();
806 vppcom_api_hookup ();
807 vcm->app_state = STATE_APP_START;
808 rv = vppcom_connect_to_vpp ((char *) child_name);
809 vec_free (child_name);
810 if (rv)
811 {
812 VERR ("couldn't connect to VPP!");
813 return;
814 }
815
Florin Coras47c40e22018-11-26 17:01:36 -0800816 /*
817 * Register worker with vpp and share sessions
818 */
819 vcl_worker_register_with_vpp ();
Florin Coras01f3f892018-12-02 12:45:53 -0800820 parent_wrk = vcl_worker_get (parent_wrk_index);
Florin Coras47c40e22018-11-26 17:01:36 -0800821 vcl_worker_share_sessions (parent_wrk);
Florin Coras01f3f892018-12-02 12:45:53 -0800822 parent_wrk->forked_child = vcl_get_worker_index ();
Florin Coras47c40e22018-11-26 17:01:36 -0800823
Florin Coras053a0e42018-11-13 15:52:38 -0800824 VDBG (0, "forked child main worker initialized");
Florin Coras47c40e22018-11-26 17:01:36 -0800825 vcm->forking = 0;
826}
827
Florin Coras01f3f892018-12-02 12:45:53 -0800828static void
Florin Coras47c40e22018-11-26 17:01:36 -0800829vcl_app_fork_parent_handler (void)
830{
831 vcm->forking = 1;
Florin Coras47c40e22018-11-26 17:01:36 -0800832 while (vcm->forking)
833 ;
Florin Coras053a0e42018-11-13 15:52:38 -0800834}
835
Florin Coras940f78f2018-11-30 12:11:20 -0800836/**
837 * Handle app exit
838 *
839 * Notify vpp of the disconnect and mark the worker as free. If we're the
840 * last worker, do a full cleanup otherwise, since we're probably a forked
841 * child, avoid syscalls as much as possible. We might've lost privileges.
842 */
843void
844vppcom_app_exit (void)
845{
846 if (!pool_elts (vcm->workers))
847 return;
Florin Coras01f3f892018-12-02 12:45:53 -0800848 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
849 vcl_set_worker_index (~0);
Florin Coras940f78f2018-11-30 12:11:20 -0800850 vcl_elog_stop (vcm);
851 if (vec_len (vcm->workers) == 1)
852 vl_client_disconnect_from_vlib ();
853 else
Florin Coraseaec2a62018-12-04 16:34:05 -0800854 vl_client_send_disconnect (1 /* vpp should cleanup */ );
Florin Coras940f78f2018-11-30 12:11:20 -0800855}
856
Dave Wallace543852a2017-08-03 02:11:34 -0400857/*
858 * VPPCOM Public API functions
859 */
860int
861vppcom_app_create (char *app_name)
862{
Dave Wallace543852a2017-08-03 02:11:34 -0400863 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
Dave Wallace543852a2017-08-03 02:11:34 -0400864 int rv;
865
Florin Coras47c40e22018-11-26 17:01:36 -0800866 if (vcm->is_init)
Dave Wallace543852a2017-08-03 02:11:34 -0400867 {
Florin Coras955bfbb2018-12-04 13:43:45 -0800868 VDBG (1, "already initialized");
869 return VPPCOM_EEXIST;
Dave Wallace543852a2017-08-03 02:11:34 -0400870 }
871
Florin Coras47c40e22018-11-26 17:01:36 -0800872 vcm->is_init = 1;
873 vppcom_cfg (&vcm->cfg);
874 vcl_cfg = &vcm->cfg;
875
876 vcm->main_cpu = pthread_self ();
877 vcm->main_pid = getpid ();
878 vcm->app_name = format (0, "%s", app_name);
879 vppcom_init_error_string_table ();
Florin Corasadc74d72018-12-02 13:36:00 -0800880 svm_fifo_segment_main_init (&vcm->segment_main, vcl_cfg->segment_baseva,
Florin Coras47c40e22018-11-26 17:01:36 -0800881 20 /* timeout in secs */ );
882 pool_alloc (vcm->workers, vcl_cfg->max_workers);
883 clib_spinlock_init (&vcm->workers_lock);
Florin Corasd85de682018-11-29 17:02:29 -0800884 clib_rwlock_init (&vcm->segment_table_lock);
Florin Coras01f3f892018-12-02 12:45:53 -0800885 pthread_atfork (vcl_app_pre_fork, vcl_app_fork_parent_handler,
Florin Coras47c40e22018-11-26 17:01:36 -0800886 vcl_app_fork_child_handler);
Florin Coras940f78f2018-11-30 12:11:20 -0800887 atexit (vppcom_app_exit);
Florin Coras47c40e22018-11-26 17:01:36 -0800888
889 /* Allocate default worker */
890 vcl_worker_alloc_and_init ();
891
892 /* API hookup and connect to VPP */
893 vppcom_api_hookup ();
894 vcl_elog_init (vcm);
895 vcm->app_state = STATE_APP_START;
896 rv = vppcom_connect_to_vpp (app_name);
897 if (rv)
Dave Wallace543852a2017-08-03 02:11:34 -0400898 {
Florin Coras47c40e22018-11-26 17:01:36 -0800899 VERR ("couldn't connect to VPP!");
900 return rv;
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400901 }
Florin Coras47c40e22018-11-26 17:01:36 -0800902 VDBG (0, "sending session enable");
903 rv = vppcom_app_session_enable ();
904 if (rv)
905 {
906 VERR ("vppcom_app_session_enable() failed!");
907 return rv;
908 }
909
910 VDBG (0, "sending app attach");
911 rv = vppcom_app_attach ();
912 if (rv)
913 {
914 VERR ("vppcom_app_attach() failed!");
915 return rv;
916 }
917
918 VDBG (0, "app_name '%s', my_client_index %d (0x%x)", app_name,
919 vcm->workers[0].my_client_index, vcm->workers[0].my_client_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400920
921 return VPPCOM_OK;
922}
923
924void
925vppcom_app_destroy (void)
926{
Dave Wallace543852a2017-08-03 02:11:34 -0400927 int rv;
Dave Wallacede910062018-03-20 09:22:13 -0400928 f64 orig_app_timeout;
Dave Wallace543852a2017-08-03 02:11:34 -0400929
Florin Coras940f78f2018-11-30 12:11:20 -0800930 if (!pool_elts (vcm->workers))
931 return;
932
Florin Coras0d427d82018-06-27 03:24:07 -0700933 vcl_evt (VCL_EVT_DETACH, vcm);
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -0800934
Florin Coras940f78f2018-11-30 12:11:20 -0800935 if (pool_elts (vcm->workers) == 1)
Florin Coras47c40e22018-11-26 17:01:36 -0800936 {
937 vppcom_app_send_detach ();
938 orig_app_timeout = vcm->cfg.app_timeout;
939 vcm->cfg.app_timeout = 2.0;
940 rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
941 vcm->cfg.app_timeout = orig_app_timeout;
942 if (PREDICT_FALSE (rv))
943 VDBG (0, "application detach timed out! returning %d (%s)", rv,
944 vppcom_retval_str (rv));
Florin Coras940f78f2018-11-30 12:11:20 -0800945 vec_free (vcm->app_name);
Florin Coras01f3f892018-12-02 12:45:53 -0800946 vcl_worker_cleanup (vcl_worker_get_current (), 0 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -0800947 }
948 else
949 {
Florin Coras01f3f892018-12-02 12:45:53 -0800950 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -0800951 }
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -0800952
Florin Coras01f3f892018-12-02 12:45:53 -0800953 vcl_set_worker_index (~0);
Florin Coras0d427d82018-06-27 03:24:07 -0700954 vcl_elog_stop (vcm);
Dave Wallace543852a2017-08-03 02:11:34 -0400955 vl_client_disconnect_from_vlib ();
Dave Wallace543852a2017-08-03 02:11:34 -0400956}
957
958int
Dave Wallacec04cbf12018-02-07 18:14:02 -0500959vppcom_session_create (u8 proto, u8 is_nonblocking)
Dave Wallace543852a2017-08-03 02:11:34 -0400960{
Florin Coras134a9962018-08-28 11:32:04 -0700961 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -0700962 vcl_session_t *session;
Dave Wallace543852a2017-08-03 02:11:34 -0400963
Florin Coras134a9962018-08-28 11:32:04 -0700964 session = vcl_session_alloc (wrk);
Dave Wallace543852a2017-08-03 02:11:34 -0400965
Florin Coras7e12d942018-06-27 14:32:43 -0700966 session->session_type = proto;
967 session->session_state = STATE_START;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500968 session->vpp_handle = ~0;
Florin Coras460dce62018-07-27 05:45:06 -0700969 session->is_dgram = proto == VPPCOM_PROTO_UDP;
Dave Wallace543852a2017-08-03 02:11:34 -0400970
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800971 if (is_nonblocking)
972 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
Dave Wallace543852a2017-08-03 02:11:34 -0400973
Florin Coras7e12d942018-06-27 14:32:43 -0700974 vcl_evt (VCL_EVT_CREATE, session, session_type, session->session_state,
975 is_nonblocking, session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -0800976
Florin Coras053a0e42018-11-13 15:52:38 -0800977 VDBG (0, "created sid %u", session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -0800978
Florin Coras134a9962018-08-28 11:32:04 -0700979 return vcl_session_handle (session);
Dave Wallace543852a2017-08-03 02:11:34 -0400980}
981
982int
Florin Coras134a9962018-08-28 11:32:04 -0700983vppcom_session_close (uint32_t session_handle)
Dave Wallace543852a2017-08-03 02:11:34 -0400984{
Florin Coras134a9962018-08-28 11:32:04 -0700985 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras47c40e22018-11-26 17:01:36 -0800986 u8 is_vep, do_disconnect = 1;
Florin Coras7e12d942018-06-27 14:32:43 -0700987 vcl_session_t *session = 0;
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400988 session_state_t state;
Florin Coras134a9962018-08-28 11:32:04 -0700989 u32 next_sh, vep_sh;
990 int rv = VPPCOM_OK;
991 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400992
Florin Coras134a9962018-08-28 11:32:04 -0700993 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -0700994 if (!session)
995 return VPPCOM_EBADFD;
996
Florin Coras47c40e22018-11-26 17:01:36 -0800997 if (session->shared_index != ~0)
998 do_disconnect = vcl_worker_unshare_session (wrk, session);
999
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001000 is_vep = session->is_vep;
Florin Coras134a9962018-08-28 11:32:04 -07001001 next_sh = session->vep.next_sh;
1002 vep_sh = session->vep.vep_sh;
Florin Coras7e12d942018-06-27 14:32:43 -07001003 state = session->session_state;
Dave Wallaceee45d412017-11-24 21:44:06 -05001004 vpp_handle = session->vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -04001005
Florin Coras47c40e22018-11-26 17:01:36 -08001006 VDBG (0, "Closing session handle %u vpp handle %u", session_handle,
1007 vpp_handle);
Dave Wallace543852a2017-08-03 02:11:34 -04001008
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001009 if (is_vep)
Dave Wallace543852a2017-08-03 02:11:34 -04001010 {
Florin Coras134a9962018-08-28 11:32:04 -07001011 while (next_sh != ~0)
Dave Wallace19481612017-09-15 18:47:44 -04001012 {
Florin Coras134a9962018-08-28 11:32:04 -07001013 rv = vppcom_epoll_ctl (session_handle, EPOLL_CTL_DEL, next_sh, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001014 if (PREDICT_FALSE (rv < 0))
Florin Coras47c40e22018-11-26 17:01:36 -08001015 VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u"
1016 " failed! rv %d (%s)", vpp_handle, next_sh, vep_sh, rv,
1017 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001018
Florin Coras134a9962018-08-28 11:32:04 -07001019 next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001020 }
1021 }
1022 else
1023 {
Florin Coras47c40e22018-11-26 17:01:36 -08001024 if (session->is_vep_session)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001025 {
Florin Coras134a9962018-08-28 11:32:04 -07001026 rv = vppcom_epoll_ctl (vep_sh, EPOLL_CTL_DEL, session_handle, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001027 if (rv < 0)
Florin Coras47c40e22018-11-26 17:01:36 -08001028 VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u "
1029 "failed! rv %d (%s)", vpp_handle, session_handle, vep_sh,
1030 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001031 }
1032
Florin Coras47c40e22018-11-26 17:01:36 -08001033 if (!do_disconnect)
1034 goto cleanup;
1035
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001036 if (state & STATE_LISTEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001037 {
Florin Coras134a9962018-08-28 11:32:04 -07001038 rv = vppcom_session_unbind (session_handle);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001039 if (PREDICT_FALSE (rv < 0))
Florin Coras47c40e22018-11-26 17:01:36 -08001040 VDBG (0, "vpp handle 0x%llx, sid %u: listener unbind failed! "
1041 "rv %d (%s)", vpp_handle, session_handle, rv,
1042 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001043 }
Florin Coras070453d2018-08-24 17:04:27 -07001044 else if (state & STATE_OPEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001045 {
Florin Coras134a9962018-08-28 11:32:04 -07001046 rv = vppcom_session_disconnect (session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001047 if (PREDICT_FALSE (rv < 0))
Dave Wallace048b1d62018-01-03 22:24:41 -05001048 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001049 "session disconnect failed! rv %d (%s)",
Florin Coras134a9962018-08-28 11:32:04 -07001050 getpid (), vpp_handle, session_handle,
Dave Wallaceee45d412017-11-24 21:44:06 -05001051 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001052 }
Dave Wallace19481612017-09-15 18:47:44 -04001053 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001054
Florin Coras47c40e22018-11-26 17:01:36 -08001055cleanup:
1056
Florin Coras99368312018-08-02 10:45:44 -07001057 if (vcl_session_is_ct (session))
1058 {
1059 vcl_cut_through_registration_t *ctr;
1060 uword mq_addr;
1061
1062 mq_addr = pointer_to_uword (session->our_evt_q);
Florin Coras134a9962018-08-28 11:32:04 -07001063 ctr = vcl_ct_registration_lock_and_lookup (wrk, mq_addr);
Florin Coras99368312018-08-02 10:45:44 -07001064 ASSERT (ctr);
1065 if (ctr->epoll_evt_conn_index != ~0)
Florin Coras134a9962018-08-28 11:32:04 -07001066 vcl_mq_epoll_del_evfd (wrk, ctr->epoll_evt_conn_index);
Florin Coras99368312018-08-02 10:45:44 -07001067 VDBG (0, "Removing ct registration %u",
Florin Coras134a9962018-08-28 11:32:04 -07001068 vcl_ct_registration_index (wrk, ctr));
1069 vcl_ct_registration_del (wrk, ctr);
1070 vcl_ct_registration_lookup_del (wrk, mq_addr);
1071 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07001072 }
Florin Coras54693d22018-07-17 10:46:29 -07001073
Dave Wallaceee45d412017-11-24 21:44:06 -05001074 if (vpp_handle != ~0)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001075 {
Florin Coras134a9962018-08-28 11:32:04 -07001076 vcl_session_table_del_vpp_handle (wrk, vpp_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001077 }
Florin Coras134a9962018-08-28 11:32:04 -07001078 vcl_session_free (wrk, session);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001079
Florin Coras47c40e22018-11-26 17:01:36 -08001080 VDBG (0, "session handle %u vpp handle %u removed", session_handle,
1081 vpp_handle);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001082
Florin Coras0d427d82018-06-27 03:24:07 -07001083 vcl_evt (VCL_EVT_CLOSE, session, rv);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001084
Dave Wallace543852a2017-08-03 02:11:34 -04001085 return rv;
1086}
1087
1088int
Florin Coras134a9962018-08-28 11:32:04 -07001089vppcom_session_bind (uint32_t session_handle, vppcom_endpt_t * ep)
Dave Wallace543852a2017-08-03 02:11:34 -04001090{
Florin Coras134a9962018-08-28 11:32:04 -07001091 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001092 vcl_session_t *session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001093
1094 if (!ep || !ep->ip)
1095 return VPPCOM_EINVAL;
1096
Florin Coras134a9962018-08-28 11:32:04 -07001097 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001098 if (!session)
1099 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001100
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001101 if (session->is_vep)
1102 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001103 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
Florin Coras134a9962018-08-28 11:32:04 -07001104 "bind to an epoll session!", getpid (), session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001105 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001106 }
1107
Florin Coras7e12d942018-06-27 14:32:43 -07001108 session->transport.is_ip4 = ep->is_ip4;
Florin Coras54693d22018-07-17 10:46:29 -07001109 if (ep->is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001110 clib_memcpy_fast (&session->transport.lcl_ip.ip4, ep->ip,
1111 sizeof (ip4_address_t));
Florin Coras54693d22018-07-17 10:46:29 -07001112 else
Dave Barach178cf492018-11-13 16:34:13 -05001113 clib_memcpy_fast (&session->transport.lcl_ip.ip6, ep->ip,
1114 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001115 session->transport.lcl_port = ep->port;
Stevenac1f96d2017-10-24 16:03:58 -07001116
Florin Coras0d427d82018-06-27 03:24:07 -07001117 VDBG (0, "VCL<%d>: sid %u: binding to local %s address %U port %u, "
Florin Coras134a9962018-08-28 11:32:04 -07001118 "proto %s", getpid (), session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001119 session->transport.is_ip4 ? "IPv4" : "IPv6",
1120 format_ip46_address, &session->transport.lcl_ip,
1121 session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
1122 clib_net_to_host_u16 (session->transport.lcl_port),
1123 session->session_type ? "UDP" : "TCP");
Florin Coras0d427d82018-06-27 03:24:07 -07001124 vcl_evt (VCL_EVT_BIND, session);
Florin Coras460dce62018-07-27 05:45:06 -07001125
1126 if (session->session_type == VPPCOM_PROTO_UDP)
Florin Coras134a9962018-08-28 11:32:04 -07001127 vppcom_session_listen (session_handle, 10);
Florin Coras460dce62018-07-27 05:45:06 -07001128
Florin Coras070453d2018-08-24 17:04:27 -07001129 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001130}
1131
1132int
Florin Coras134a9962018-08-28 11:32:04 -07001133vppcom_session_listen (uint32_t listen_sh, uint32_t q_len)
Dave Wallace543852a2017-08-03 02:11:34 -04001134{
Florin Coras134a9962018-08-28 11:32:04 -07001135 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001136 vcl_session_t *listen_session = 0;
Dave Wallaceee45d412017-11-24 21:44:06 -05001137 u64 listen_vpp_handle;
Florin Coras070453d2018-08-24 17:04:27 -07001138 int rv;
1139
Florin Coras134a9962018-08-28 11:32:04 -07001140 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras070453d2018-08-24 17:04:27 -07001141 if (!listen_session)
1142 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001143
Keith Burns (alagalah)aba98de2018-02-22 03:23:40 -08001144 if (q_len == 0 || q_len == ~0)
1145 q_len = vcm->cfg.listen_queue_size;
1146
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001147 if (listen_session->is_vep)
1148 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001149 clib_warning ("VCL<%d>: ERROR: sid %u: cannot listen on an "
Florin Coras134a9962018-08-28 11:32:04 -07001150 "epoll session!", getpid (), listen_sh);
Florin Coras070453d2018-08-24 17:04:27 -07001151 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001152 }
1153
Dave Wallaceee45d412017-11-24 21:44:06 -05001154 listen_vpp_handle = listen_session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -07001155 if (listen_session->session_state & STATE_LISTEN)
Dave Wallacee695cb42017-11-02 22:04:42 -04001156 {
Florin Coras0d427d82018-06-27 03:24:07 -07001157 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: already in listen state!",
Florin Coras134a9962018-08-28 11:32:04 -07001158 getpid (), listen_vpp_handle, listen_sh);
Florin Coras070453d2018-08-24 17:04:27 -07001159 return VPPCOM_OK;
Dave Wallacee695cb42017-11-02 22:04:42 -04001160 }
1161
Florin Coras0d427d82018-06-27 03:24:07 -07001162 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: sending VPP bind+listen "
Florin Coras134a9962018-08-28 11:32:04 -07001163 "request...", getpid (), listen_vpp_handle, listen_sh);
Dave Wallace543852a2017-08-03 02:11:34 -04001164
Florin Coras070453d2018-08-24 17:04:27 -07001165 /*
1166 * Send listen request to vpp and wait for reply
1167 */
Florin Coras134a9962018-08-28 11:32:04 -07001168 vppcom_send_bind_sock (listen_session);
1169 rv = vppcom_wait_for_session_state_change (listen_session->session_index,
1170 STATE_LISTEN,
1171 vcm->cfg.session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001172
Florin Coras070453d2018-08-24 17:04:27 -07001173 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001174 {
Florin Coras134a9962018-08-28 11:32:04 -07001175 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras0d427d82018-06-27 03:24:07 -07001176 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: bind+listen failed! "
1177 "returning %d (%s)", getpid (), listen_session->vpp_handle,
Florin Coras134a9962018-08-28 11:32:04 -07001178 listen_sh, rv, vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001179 return rv;
Dave Wallaceee45d412017-11-24 21:44:06 -05001180 }
1181
Florin Coras070453d2018-08-24 17:04:27 -07001182 return VPPCOM_OK;
Keith Burns (alagalah)0d2b0d52018-03-06 15:55:22 -08001183}
1184
Florin Coras134a9962018-08-28 11:32:04 -07001185static int
1186validate_args_session_accept_ (vcl_worker_t * wrk,
1187 vcl_session_t * listen_session)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001188{
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001189 /* Input validation - expects spinlock on sessions_lockp */
1190 if (listen_session->is_vep)
1191 {
1192 clib_warning ("VCL<%d>: ERROR: sid %u: cannot accept on an "
Florin Coras134a9962018-08-28 11:32:04 -07001193 "epoll session!", getpid (),
1194 listen_session->session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001195 return VPPCOM_EBADFD;
1196 }
1197
Florin Coras7e12d942018-06-27 14:32:43 -07001198 if (listen_session->session_state != STATE_LISTEN)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001199 {
1200 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
1201 "not in listen state! state 0x%x (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001202 listen_session->vpp_handle, listen_session->session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001203 listen_session->session_state,
1204 vppcom_session_state_str (listen_session->session_state));
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001205 return VPPCOM_EBADFD;
1206 }
1207 return VPPCOM_OK;
1208}
1209
1210int
Florin Coras134a9962018-08-28 11:32:04 -07001211vppcom_session_accept (uint32_t listen_session_handle, vppcom_endpt_t * ep,
Dave Wallace048b1d62018-01-03 22:24:41 -05001212 uint32_t flags)
Dave Wallace543852a2017-08-03 02:11:34 -04001213{
Florin Coras134a9962018-08-28 11:32:04 -07001214 u32 client_session_index = ~0, listen_session_index;
1215 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001216 session_accepted_msg_t accepted_msg;
Florin Coras7e12d942018-06-27 14:32:43 -07001217 vcl_session_t *listen_session = 0;
1218 vcl_session_t *client_session = 0;
Florin Coras54693d22018-07-17 10:46:29 -07001219 svm_msg_q_t *vpp_evt_q;
1220 vcl_session_msg_t *evt;
Dave Wallaceee45d412017-11-24 21:44:06 -05001221 u64 listen_vpp_handle;
Florin Coras54693d22018-07-17 10:46:29 -07001222 svm_msg_q_msg_t msg;
1223 session_event_t *e;
1224 u8 is_nonblocking;
1225 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001226
Florin Coras134a9962018-08-28 11:32:04 -07001227 listen_session = vcl_session_get_w_handle (wrk, listen_session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001228 if (!listen_session)
1229 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001230
Florin Coras134a9962018-08-28 11:32:04 -07001231 listen_session_index = listen_session->session_index;
1232 if ((rv = validate_args_session_accept_ (wrk, listen_session)))
Florin Coras070453d2018-08-24 17:04:27 -07001233 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001234
Florin Coras54693d22018-07-17 10:46:29 -07001235 if (clib_fifo_elts (listen_session->accept_evts_fifo))
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001236 {
Florin Coras54693d22018-07-17 10:46:29 -07001237 clib_fifo_sub2 (listen_session->accept_evts_fifo, evt);
1238 accepted_msg = evt->accepted_msg;
1239 goto handle;
1240 }
1241
1242 is_nonblocking = VCL_SESS_ATTR_TEST (listen_session->attr,
1243 VCL_SESS_ATTR_NONBLOCK);
Florin Coras134a9962018-08-28 11:32:04 -07001244 if (svm_msg_q_is_empty (wrk->app_event_queue) && is_nonblocking)
Florin Coras54693d22018-07-17 10:46:29 -07001245 return VPPCOM_EAGAIN;
1246
1247 while (1)
1248 {
Florin Coras134a9962018-08-28 11:32:04 -07001249 if (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_WAIT, 0))
Florin Coras54693d22018-07-17 10:46:29 -07001250 return VPPCOM_EAGAIN;
1251
Florin Coras134a9962018-08-28 11:32:04 -07001252 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001253 if (e->event_type != SESSION_CTRL_EVT_ACCEPTED)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001254 {
Florin Coras54693d22018-07-17 10:46:29 -07001255 clib_warning ("discarded event: %u", e->event_type);
Florin Coras134a9962018-08-28 11:32:04 -07001256 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001257 continue;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001258 }
Dave Barach178cf492018-11-13 16:34:13 -05001259 clib_memcpy_fast (&accepted_msg, e->data, sizeof (accepted_msg));
Florin Coras134a9962018-08-28 11:32:04 -07001260 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001261 break;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001262 }
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001263
Florin Coras54693d22018-07-17 10:46:29 -07001264handle:
Keith Burns (alagalah)00f44cc2018-03-07 09:26:38 -08001265
Florin Coras134a9962018-08-28 11:32:04 -07001266 client_session_index = vcl_session_accepted_handler (wrk, &accepted_msg);
1267 listen_session = vcl_session_get (wrk, listen_session_index);
1268 client_session = vcl_session_get (wrk, client_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001269
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001270 if (flags & O_NONBLOCK)
1271 VCL_SESS_ATTR_SET (client_session->attr, VCL_SESS_ATTR_NONBLOCK);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001272
Florin Coras54693d22018-07-17 10:46:29 -07001273 listen_vpp_handle = listen_session->vpp_handle;
Florin Corasdc2e2512018-12-03 17:47:26 -08001274 VDBG (0, "vpp handle 0x%llx, sid %u: Got a client request! "
Florin Coras0d427d82018-06-27 03:24:07 -07001275 "vpp handle 0x%llx, sid %u, flags %d, is_nonblocking %u",
Florin Corasdc2e2512018-12-03 17:47:26 -08001276 listen_vpp_handle, listen_session_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001277 client_session->vpp_handle, client_session_index,
1278 flags, VCL_SESS_ATTR_TEST (client_session->attr,
1279 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace543852a2017-08-03 02:11:34 -04001280
Dave Wallace048b1d62018-01-03 22:24:41 -05001281 if (ep)
1282 {
Florin Coras7e12d942018-06-27 14:32:43 -07001283 ep->is_ip4 = client_session->transport.is_ip4;
1284 ep->port = client_session->transport.rmt_port;
1285 if (client_session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001286 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip4,
1287 sizeof (ip4_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001288 else
Dave Barach178cf492018-11-13 16:34:13 -05001289 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip6,
1290 sizeof (ip6_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001291 }
Dave Wallace60caa062017-11-10 17:07:13 -05001292
Florin Coras54693d22018-07-17 10:46:29 -07001293 if (accepted_msg.server_event_queue_address)
1294 vpp_evt_q = uword_to_pointer (accepted_msg.vpp_event_queue_address,
1295 svm_msg_q_t *);
1296 else
1297 vpp_evt_q = client_session->vpp_evt_q;
Florin Coras99368312018-08-02 10:45:44 -07001298
Florin Coras54693d22018-07-17 10:46:29 -07001299 vcl_send_session_accepted_reply (vpp_evt_q, client_session->client_context,
1300 client_session->vpp_handle, 0);
Dave Wallace60caa062017-11-10 17:07:13 -05001301
Florin Corasdc2e2512018-12-03 17:47:26 -08001302 VDBG (0, "vpp handle 0x%llx, sid %u: accepted vpp handle 0x%llx, "
Florin Coras54693d22018-07-17 10:46:29 -07001303 "sid %u connection from peer %s address %U port %u to local %s "
Florin Corasdc2e2512018-12-03 17:47:26 -08001304 "address %U port %u", listen_vpp_handle,
Florin Coras134a9962018-08-28 11:32:04 -07001305 listen_session_handle, client_session->vpp_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001306 client_session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001307 client_session->transport.is_ip4 ? "IPv4" : "IPv6",
1308 format_ip46_address, &client_session->transport.rmt_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001309 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001310 clib_net_to_host_u16 (client_session->transport.rmt_port),
1311 client_session->transport.is_ip4 ? "IPv4" : "IPv6",
1312 format_ip46_address, &client_session->transport.lcl_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001313 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001314 clib_net_to_host_u16 (client_session->transport.lcl_port));
Florin Coras0d427d82018-06-27 03:24:07 -07001315 vcl_evt (VCL_EVT_ACCEPT, client_session, listen_session,
1316 client_session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001317
Florin Corasab2f6db2018-08-31 14:31:41 -07001318 return vcl_session_handle (client_session);
Dave Wallace543852a2017-08-03 02:11:34 -04001319}
1320
1321int
Florin Coras134a9962018-08-28 11:32:04 -07001322vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep)
Dave Wallace543852a2017-08-03 02:11:34 -04001323{
Florin Coras134a9962018-08-28 11:32:04 -07001324 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001325 vcl_session_t *session = 0;
Florin Coras134a9962018-08-28 11:32:04 -07001326 u32 session_index;
Florin Coras070453d2018-08-24 17:04:27 -07001327 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001328
Florin Coras134a9962018-08-28 11:32:04 -07001329 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001330 if (!session)
1331 return VPPCOM_EBADFD;
Florin Coras134a9962018-08-28 11:32:04 -07001332 session_index = session->session_index;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001333
1334 if (PREDICT_FALSE (session->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001335 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001336 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
Florin Coras134a9962018-08-28 11:32:04 -07001337 "connect on an epoll session!", getpid (),
1338 session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001339 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001340 }
1341
Florin Coras7e12d942018-06-27 14:32:43 -07001342 if (PREDICT_FALSE (session->session_state & CLIENT_STATE_OPEN))
Dave Wallace543852a2017-08-03 02:11:34 -04001343 {
Florin Coras0d427d82018-06-27 03:24:07 -07001344 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: session already "
1345 "connected to %s %U port %d proto %s, state 0x%x (%s)",
Florin Coras134a9962018-08-28 11:32:04 -07001346 getpid (), session->vpp_handle, session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001347 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001348 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001349 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001350 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001351 clib_net_to_host_u16 (session->transport.rmt_port),
1352 session->session_type ? "UDP" : "TCP", session->session_state,
1353 vppcom_session_state_str (session->session_state));
Florin Coras070453d2018-08-24 17:04:27 -07001354 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001355 }
1356
Florin Coras7e12d942018-06-27 14:32:43 -07001357 session->transport.is_ip4 = server_ep->is_ip4;
1358 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001359 clib_memcpy_fast (&session->transport.rmt_ip.ip4, server_ep->ip,
1360 sizeof (ip4_address_t));
Dave Wallaced239f8d2018-06-19 13:37:30 -04001361 else
Dave Barach178cf492018-11-13 16:34:13 -05001362 clib_memcpy_fast (&session->transport.rmt_ip.ip6, server_ep->ip,
1363 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001364 session->transport.rmt_port = server_ep->port;
Dave Wallace543852a2017-08-03 02:11:34 -04001365
Florin Coras0d427d82018-06-27 03:24:07 -07001366 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connecting to server %s %U "
1367 "port %d proto %s",
Florin Coras134a9962018-08-28 11:32:04 -07001368 getpid (), session->vpp_handle, session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001369 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001370 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001371 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001372 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001373 clib_net_to_host_u16 (session->transport.rmt_port),
1374 session->session_type ? "UDP" : "TCP");
Dave Wallace543852a2017-08-03 02:11:34 -04001375
Florin Coras070453d2018-08-24 17:04:27 -07001376 /*
1377 * Send connect request and wait for reply from vpp
1378 */
Florin Coras134a9962018-08-28 11:32:04 -07001379 vppcom_send_connect_sock (session);
Florin Coras070453d2018-08-24 17:04:27 -07001380 rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
1381 vcm->cfg.session_timeout);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001382
Florin Coras134a9962018-08-28 11:32:04 -07001383 session = vcl_session_get (wrk, session_index);
Dave Wallace7876d392017-10-19 03:53:57 -04001384
Florin Coras070453d2018-08-24 17:04:27 -07001385 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001386 {
Dave Wallaceee45d412017-11-24 21:44:06 -05001387 if (VPPCOM_DEBUG > 0)
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001388 {
1389 if (session)
Florin Coras0d427d82018-06-27 03:24:07 -07001390 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connect "
Florin Coras134a9962018-08-28 11:32:04 -07001391 "failed! returning %d (%s)", getpid (),
1392 session->vpp_handle, session_handle, rv,
1393 vppcom_retval_str (rv));
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001394 else
1395 clib_warning ("VCL<%d>: no session for sid %u: connect failed! "
1396 "returning %d (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001397 session_handle, rv, vppcom_retval_str (rv));
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001398 }
Dave Wallaceee45d412017-11-24 21:44:06 -05001399 }
Florin Coras0d427d82018-06-27 03:24:07 -07001400 else
1401 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connected!",
Florin Coras134a9962018-08-28 11:32:04 -07001402 getpid (), session->vpp_handle, session_handle);
Dave Wallaceee45d412017-11-24 21:44:06 -05001403
Dave Wallace4878cbe2017-11-21 03:45:09 -05001404 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001405}
1406
Florin Coras54693d22018-07-17 10:46:29 -07001407static u8
1408vcl_is_rx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1409{
1410 if (!is_ct)
1411 return (e->event_type == FIFO_EVENT_APP_RX
1412 && e->fifo->client_session_index == sid);
1413 else
1414 return (e->event_type == SESSION_IO_EVT_CT_TX);
1415}
1416
Florin Coras460dce62018-07-27 05:45:06 -07001417static inline u8
1418vcl_session_is_readable (vcl_session_t * s)
1419{
1420 return ((s->session_state & STATE_OPEN)
1421 || (s->session_state == STATE_LISTEN
1422 && s->session_type == VPPCOM_PROTO_UDP));
1423}
1424
Steven58f464e2017-10-25 12:33:12 -07001425static inline int
Florin Coras134a9962018-08-28 11:32:04 -07001426vppcom_session_read_internal (uint32_t session_handle, void *buf, int n,
Steven58f464e2017-10-25 12:33:12 -07001427 u8 peek)
Dave Wallace543852a2017-08-03 02:11:34 -04001428{
Florin Coras134a9962018-08-28 11:32:04 -07001429 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001430 int n_read = 0, rv, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001431 vcl_session_t *s = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001432 svm_fifo_t *rx_fifo;
Florin Coras54693d22018-07-17 10:46:29 -07001433 svm_msg_q_msg_t msg;
1434 session_event_t *e;
1435 svm_msg_q_t *mq;
Florin Coras41c9e042018-09-11 00:10:41 -07001436 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001437
Florin Coras070453d2018-08-24 17:04:27 -07001438 if (PREDICT_FALSE (!buf))
1439 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001440
Florin Coras134a9962018-08-28 11:32:04 -07001441 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras2cba8532018-09-11 16:33:36 -07001442 if (PREDICT_FALSE (!s || s->is_vep))
Florin Coras070453d2018-08-24 17:04:27 -07001443 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001444
Florin Coras460dce62018-07-27 05:45:06 -07001445 if (PREDICT_FALSE (!vcl_session_is_readable (s)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001446 {
Florin Coras460dce62018-07-27 05:45:06 -07001447 session_state_t state = s->session_state;
Keith Burns (alagalah)56a0d062018-02-15 07:52:50 -08001448 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001449
Florin Coras0d427d82018-06-27 03:24:07 -07001450 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: %s session is not open! "
1451 "state 0x%x (%s), returning %d (%s)",
Florin Coras134a9962018-08-28 11:32:04 -07001452 getpid (), s->vpp_handle, session_handle, state,
Florin Coras0d427d82018-06-27 03:24:07 -07001453 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001454 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001455 }
1456
Florin Coras2cba8532018-09-11 16:33:36 -07001457 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
Florin Coras41c9e042018-09-11 00:10:41 -07001458 is_ct = vcl_session_is_ct (s);
1459 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
Florin Coras2cba8532018-09-11 16:33:36 -07001460 rx_fifo = s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001461 s->has_rx_evt = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001462
Florin Coras54693d22018-07-17 10:46:29 -07001463 if (svm_fifo_is_empty (rx_fifo))
Dave Wallacef7f809c2017-10-03 01:48:42 -04001464 {
Florin Coras54693d22018-07-17 10:46:29 -07001465 if (is_nonblocking)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001466 {
Florin Coras41c9e042018-09-11 00:10:41 -07001467 svm_fifo_unset_event (rx_fifo);
Florin Corasaa27eb92018-10-13 12:20:01 -07001468 return VPPCOM_EWOULDBLOCK;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001469 }
Florin Coras41c9e042018-09-11 00:10:41 -07001470 while (svm_fifo_is_empty (rx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001471 {
Florin Coras41c9e042018-09-11 00:10:41 -07001472 svm_fifo_unset_event (rx_fifo);
Florin Coras99368312018-08-02 10:45:44 -07001473 svm_msg_q_lock (mq);
Florin Coras54693d22018-07-17 10:46:29 -07001474 if (svm_msg_q_is_empty (mq))
1475 svm_msg_q_wait (mq);
Florin Coras99368312018-08-02 10:45:44 -07001476
Florin Coras54693d22018-07-17 10:46:29 -07001477 svm_msg_q_sub_w_lock (mq, &msg);
1478 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001479 svm_msg_q_unlock (mq);
Florin Coras41c9e042018-09-11 00:10:41 -07001480 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
Florin Coras54693d22018-07-17 10:46:29 -07001481 {
Florin Coras86f04502018-09-12 16:08:01 -07001482 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001483 svm_msg_q_free_msg (mq, &msg);
1484 continue;
1485 }
Florin Coras54693d22018-07-17 10:46:29 -07001486 svm_msg_q_free_msg (mq, &msg);
Florin Coras41c9e042018-09-11 00:10:41 -07001487
Florin Coras60f1fc12018-08-16 14:57:31 -07001488 if (PREDICT_FALSE (s->session_state == STATE_CLOSE_ON_EMPTY))
1489 return 0;
Florin Coras54693d22018-07-17 10:46:29 -07001490 }
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001491 }
Florin Coras54693d22018-07-17 10:46:29 -07001492
Florin Coras460dce62018-07-27 05:45:06 -07001493 if (s->is_dgram)
Florin Coras99368312018-08-02 10:45:44 -07001494 n_read = app_recv_dgram_raw (rx_fifo, buf, n, &s->transport, 0, peek);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001495 else
Florin Coras99368312018-08-02 10:45:44 -07001496 n_read = app_recv_stream_raw (rx_fifo, buf, n, 0, peek);
Florin Coras54693d22018-07-17 10:46:29 -07001497
Florin Coras41c9e042018-09-11 00:10:41 -07001498 if (svm_fifo_is_empty (rx_fifo))
1499 svm_fifo_unset_event (rx_fifo);
1500
Florin Coras58c101a2018-10-06 13:49:16 -07001501 if (is_ct && svm_fifo_want_tx_evt (rx_fifo))
Florin Coras99368312018-08-02 10:45:44 -07001502 {
Florin Coras58c101a2018-10-06 13:49:16 -07001503 svm_fifo_set_want_tx_evt (s->rx_fifo, 0);
1504 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo, SESSION_IO_EVT_CT_RX,
1505 SVM_Q_WAIT);
Florin Coras99368312018-08-02 10:45:44 -07001506 }
Florin Coras54693d22018-07-17 10:46:29 -07001507
Florin Coras2cba8532018-09-11 16:33:36 -07001508 VDBG (2, "VCL<%d>: vpp handle 0x%llx, sid %u: read %d bytes from (%p)",
1509 getpid (), s->vpp_handle, session_handle, n_read, rx_fifo);
1510
Florin Coras54693d22018-07-17 10:46:29 -07001511 return n_read;
Dave Wallace543852a2017-08-03 02:11:34 -04001512}
1513
Steven58f464e2017-10-25 12:33:12 -07001514int
Florin Coras134a9962018-08-28 11:32:04 -07001515vppcom_session_read (uint32_t session_handle, void *buf, size_t n)
Steven58f464e2017-10-25 12:33:12 -07001516{
Florin Coras134a9962018-08-28 11:32:04 -07001517 return (vppcom_session_read_internal (session_handle, buf, n, 0));
Steven58f464e2017-10-25 12:33:12 -07001518}
1519
1520static int
Florin Coras134a9962018-08-28 11:32:04 -07001521vppcom_session_peek (uint32_t session_handle, void *buf, int n)
Steven58f464e2017-10-25 12:33:12 -07001522{
Florin Coras134a9962018-08-28 11:32:04 -07001523 return (vppcom_session_read_internal (session_handle, buf, n, 1));
Steven58f464e2017-10-25 12:33:12 -07001524}
1525
Florin Coras2cba8532018-09-11 16:33:36 -07001526int
1527vppcom_session_read_segments (uint32_t session_handle,
1528 vppcom_data_segments_t ds)
1529{
1530 vcl_worker_t *wrk = vcl_worker_get_current ();
1531 int n_read = 0, rv, is_nonblocking;
1532 vcl_session_t *s = 0;
1533 svm_fifo_t *rx_fifo;
1534 svm_msg_q_msg_t msg;
1535 session_event_t *e;
1536 svm_msg_q_t *mq;
1537 u8 is_ct;
1538
1539 s = vcl_session_get_w_handle (wrk, session_handle);
1540 if (PREDICT_FALSE (!s || s->is_vep))
1541 return VPPCOM_EBADFD;
1542
1543 if (PREDICT_FALSE (!vcl_session_is_readable (s)))
1544 {
1545 session_state_t state = s->session_state;
1546 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1547 return rv;
1548 }
1549
1550 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1551 is_ct = vcl_session_is_ct (s);
1552 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
1553 rx_fifo = s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001554 s->has_rx_evt = 0;
Florin Coras2cba8532018-09-11 16:33:36 -07001555
1556 if (svm_fifo_is_empty (rx_fifo))
1557 {
1558 if (is_nonblocking)
1559 {
1560 svm_fifo_unset_event (rx_fifo);
Florin Corasaa27eb92018-10-13 12:20:01 -07001561 return VPPCOM_EWOULDBLOCK;
Florin Coras2cba8532018-09-11 16:33:36 -07001562 }
1563 while (svm_fifo_is_empty (rx_fifo))
1564 {
1565 svm_fifo_unset_event (rx_fifo);
1566 svm_msg_q_lock (mq);
1567 if (svm_msg_q_is_empty (mq))
1568 svm_msg_q_wait (mq);
1569
1570 svm_msg_q_sub_w_lock (mq, &msg);
1571 e = svm_msg_q_msg_data (mq, &msg);
1572 svm_msg_q_unlock (mq);
1573 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
1574 {
Florin Coras86f04502018-09-12 16:08:01 -07001575 vcl_handle_mq_event (wrk, e);
Florin Coras2cba8532018-09-11 16:33:36 -07001576 svm_msg_q_free_msg (mq, &msg);
1577 continue;
1578 }
1579 svm_msg_q_free_msg (mq, &msg);
1580
1581 if (PREDICT_FALSE (s->session_state == STATE_CLOSE_ON_EMPTY))
1582 return 0;
1583 }
1584 }
1585
1586 n_read = svm_fifo_segments (rx_fifo, (svm_fifo_segment_t *) ds);
1587 svm_fifo_unset_event (rx_fifo);
1588
1589 if (is_ct && n_read + svm_fifo_max_dequeue (rx_fifo) == rx_fifo->nitems)
1590 {
1591 /* If the peer is not polling send notification */
1592 if (!svm_fifo_has_event (s->rx_fifo))
1593 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo,
1594 SESSION_IO_EVT_CT_RX, SVM_Q_WAIT);
1595 }
1596
1597 return n_read;
1598}
1599
1600void
1601vppcom_session_free_segments (uint32_t session_handle,
1602 vppcom_data_segments_t ds)
1603{
1604 vcl_worker_t *wrk = vcl_worker_get_current ();
1605 vcl_session_t *s;
1606
1607 s = vcl_session_get_w_handle (wrk, session_handle);
1608 if (PREDICT_FALSE (!s || s->is_vep))
1609 return;
1610
1611 svm_fifo_segments_free (s->rx_fifo, (svm_fifo_segment_t *) ds);
1612}
1613
Dave Wallace543852a2017-08-03 02:11:34 -04001614static inline int
Florin Coras54693d22018-07-17 10:46:29 -07001615vppcom_session_read_ready (vcl_session_t * session)
Dave Wallace543852a2017-08-03 02:11:34 -04001616{
Dave Wallace543852a2017-08-03 02:11:34 -04001617 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05001618 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001619 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001620 clib_warning ("VCL<%d>: ERROR: sid %u: cannot read from an "
Florin Coras134a9962018-08-28 11:32:04 -07001621 "epoll session!", getpid (), session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -07001622 return VPPCOM_EBADFD;
1623 }
1624
1625 if (PREDICT_FALSE (!(session->session_state & (STATE_OPEN | STATE_LISTEN))))
1626 {
1627 session_state_t state = session->session_state;
1628 int rv;
1629
1630 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1631
1632 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open!"
1633 " state 0x%x (%s), returning %d (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001634 session->vpp_handle, session->session_index, state,
Florin Coras54693d22018-07-17 10:46:29 -07001635 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
1636 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001637 }
Dave Wallace33e002b2017-09-06 01:20:02 -04001638
Florin Coras7e12d942018-06-27 14:32:43 -07001639 if (session->session_state & STATE_LISTEN)
Florin Coras54693d22018-07-17 10:46:29 -07001640 return clib_fifo_elts (session->accept_evts_fifo);
1641
1642 return svm_fifo_max_dequeue (session->rx_fifo);
1643}
1644
Florin Coras2cba8532018-09-11 16:33:36 -07001645int
1646vppcom_data_segment_copy (void *buf, vppcom_data_segments_t ds, u32 max_bytes)
1647{
1648 u32 first_copy = clib_min (ds[0].len, max_bytes);
Dave Barach178cf492018-11-13 16:34:13 -05001649 clib_memcpy_fast (buf, ds[0].data, first_copy);
Florin Coras2cba8532018-09-11 16:33:36 -07001650 if (first_copy < max_bytes)
1651 {
Dave Barach178cf492018-11-13 16:34:13 -05001652 clib_memcpy_fast (buf + first_copy, ds[1].data,
1653 clib_min (ds[1].len, max_bytes - first_copy));
Florin Coras2cba8532018-09-11 16:33:36 -07001654 }
1655 return 0;
1656}
1657
Florin Coras54693d22018-07-17 10:46:29 -07001658static u8
1659vcl_is_tx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1660{
1661 if (!is_ct)
1662 return (e->event_type == FIFO_EVENT_APP_TX
1663 && e->fifo->client_session_index == sid);
Dave Wallace543852a2017-08-03 02:11:34 -04001664 else
Florin Coras54693d22018-07-17 10:46:29 -07001665 return (e->event_type == SESSION_IO_EVT_CT_RX);
Dave Wallace543852a2017-08-03 02:11:34 -04001666}
1667
1668int
Florin Coras134a9962018-08-28 11:32:04 -07001669vppcom_session_write (uint32_t session_handle, void *buf, size_t n)
Dave Wallace543852a2017-08-03 02:11:34 -04001670{
Florin Coras134a9962018-08-28 11:32:04 -07001671 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001672 int rv, n_write, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001673 vcl_session_t *s = 0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001674 svm_fifo_t *tx_fifo = 0;
Florin Coras460dce62018-07-27 05:45:06 -07001675 session_evt_type_t et;
Florin Coras54693d22018-07-17 10:46:29 -07001676 svm_msg_q_msg_t msg;
1677 session_event_t *e;
Florin Coras3c2fed52018-07-04 04:15:05 -07001678 svm_msg_q_t *mq;
Florin Coras0e88e852018-09-17 22:09:02 -07001679 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001680
Florin Coras070453d2018-08-24 17:04:27 -07001681 if (PREDICT_FALSE (!buf))
1682 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001683
Florin Coras134a9962018-08-28 11:32:04 -07001684 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001685 if (PREDICT_FALSE (!s))
1686 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001687
Florin Coras460dce62018-07-27 05:45:06 -07001688 if (PREDICT_FALSE (s->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001689 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001690 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001691 "cannot write to an epoll session!",
Florin Coras134a9962018-08-28 11:32:04 -07001692 getpid (), s->vpp_handle, session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001693
Florin Coras070453d2018-08-24 17:04:27 -07001694 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001695 }
1696
Florin Coras0e88e852018-09-17 22:09:02 -07001697 if (PREDICT_FALSE (!(s->session_state & STATE_OPEN)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001698 {
Florin Coras460dce62018-07-27 05:45:06 -07001699 session_state_t state = s->session_state;
Florin Coras54693d22018-07-17 10:46:29 -07001700 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Florin Coras0d427d82018-06-27 03:24:07 -07001701 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open! "
Florin Coras0e88e852018-09-17 22:09:02 -07001702 "state 0x%x (%s)", getpid (), s->vpp_handle, session_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001703 state, vppcom_session_state_str (state));
Florin Coras070453d2018-08-24 17:04:27 -07001704 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001705 }
1706
Florin Coras0e88e852018-09-17 22:09:02 -07001707 tx_fifo = s->tx_fifo;
1708 is_ct = vcl_session_is_ct (s);
1709 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1710 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
Florin Coras54693d22018-07-17 10:46:29 -07001711 if (svm_fifo_is_full (tx_fifo))
Dave Wallace543852a2017-08-03 02:11:34 -04001712 {
Florin Coras54693d22018-07-17 10:46:29 -07001713 if (is_nonblocking)
1714 {
Florin Coras070453d2018-08-24 17:04:27 -07001715 return VPPCOM_EWOULDBLOCK;
Florin Coras54693d22018-07-17 10:46:29 -07001716 }
Florin Coras60f1fc12018-08-16 14:57:31 -07001717 while (svm_fifo_is_full (tx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001718 {
Florin Coras0e88e852018-09-17 22:09:02 -07001719 svm_fifo_set_want_tx_evt (tx_fifo, 1);
Florin Coras99368312018-08-02 10:45:44 -07001720 svm_msg_q_lock (mq);
Florin Corasaa27eb92018-10-13 12:20:01 -07001721 if (svm_msg_q_is_empty (mq))
1722 svm_msg_q_wait (mq);
Florin Coras0e88e852018-09-17 22:09:02 -07001723
Florin Coras54693d22018-07-17 10:46:29 -07001724 svm_msg_q_sub_w_lock (mq, &msg);
1725 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001726 svm_msg_q_unlock (mq);
1727
Florin Coras0e88e852018-09-17 22:09:02 -07001728 if (!vcl_is_tx_evt_for_session (e, s->session_index, is_ct))
Florin Coras86f04502018-09-12 16:08:01 -07001729 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001730 svm_msg_q_free_msg (mq, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001731 }
Dave Wallace543852a2017-08-03 02:11:34 -04001732 }
Dave Wallace543852a2017-08-03 02:11:34 -04001733
Florin Coras460dce62018-07-27 05:45:06 -07001734 ASSERT (FIFO_EVENT_APP_TX + 1 == SESSION_IO_EVT_CT_TX);
1735 et = FIFO_EVENT_APP_TX + vcl_session_is_ct (s);
1736 if (s->is_dgram)
1737 n_write = app_send_dgram_raw (tx_fifo, &s->transport,
1738 s->vpp_evt_q, buf, n, et, SVM_Q_WAIT);
1739 else
1740 n_write = app_send_stream_raw (tx_fifo, s->vpp_evt_q, buf, n, et,
1741 SVM_Q_WAIT);
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -07001742
Florin Coras460dce62018-07-27 05:45:06 -07001743 ASSERT (n_write > 0);
Dave Wallace543852a2017-08-03 02:11:34 -04001744
Florin Coras0e88e852018-09-17 22:09:02 -07001745 VDBG (2, "VCL<%d>: vpp handle 0x%llx, sid %u: wrote %d bytes", getpid (),
1746 s->vpp_handle, session_handle, n_write);
1747
Florin Coras54693d22018-07-17 10:46:29 -07001748 return n_write;
Dave Wallace543852a2017-08-03 02:11:34 -04001749}
1750
Florin Coras99368312018-08-02 10:45:44 -07001751static vcl_session_t *
Florin Coras134a9962018-08-28 11:32:04 -07001752vcl_ct_session_get_from_fifo (vcl_worker_t * wrk, svm_fifo_t * f, u8 type)
Florin Coras99368312018-08-02 10:45:44 -07001753{
1754 vcl_session_t *s;
Florin Coras134a9962018-08-28 11:32:04 -07001755 s = vcl_session_get (wrk, f->client_session_index);
Florin Coras99368312018-08-02 10:45:44 -07001756 if (s)
1757 {
1758 /* rx fifo */
1759 if (type == 0 && s->rx_fifo == f)
1760 return s;
1761 /* tx fifo */
1762 if (type == 1 && s->tx_fifo == f)
1763 return s;
1764 }
Florin Coras134a9962018-08-28 11:32:04 -07001765 s = vcl_session_get (wrk, f->master_session_index);
Florin Coras99368312018-08-02 10:45:44 -07001766 if (s)
1767 {
1768 if (type == 0 && s->rx_fifo == f)
1769 return s;
1770 if (type == 1 && s->tx_fifo == f)
1771 return s;
1772 }
1773 return 0;
1774}
1775
Dave Wallace543852a2017-08-03 02:11:34 -04001776static inline int
Florin Coras134a9962018-08-28 11:32:04 -07001777vppcom_session_write_ready (vcl_session_t * session)
Dave Wallace543852a2017-08-03 02:11:34 -04001778{
Dave Wallace543852a2017-08-03 02:11:34 -04001779 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05001780 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001781 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001782 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001783 "cannot write to an epoll session!",
Florin Coras134a9962018-08-28 11:32:04 -07001784 getpid (), session->vpp_handle, session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -07001785 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001786 }
1787
Florin Coras7e12d942018-06-27 14:32:43 -07001788 if (PREDICT_FALSE (session->session_state & STATE_LISTEN))
Dave Wallace33e002b2017-09-06 01:20:02 -04001789 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001790 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001791 "cannot write to a listen session!",
Florin Coras134a9962018-08-28 11:32:04 -07001792 getpid (), session->vpp_handle, session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -07001793 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001794 }
1795
Florin Coras54693d22018-07-17 10:46:29 -07001796 if (PREDICT_FALSE (!(session->session_state & STATE_OPEN)))
Dave Wallace4878cbe2017-11-21 03:45:09 -05001797 {
Florin Coras7e12d942018-06-27 14:32:43 -07001798 session_state_t state = session->session_state;
Florin Coras54693d22018-07-17 10:46:29 -07001799 int rv;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001800
Keith Burns (alagalah)56a0d062018-02-15 07:52:50 -08001801 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Dave Wallace048b1d62018-01-03 22:24:41 -05001802 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001803 "session is not open! state 0x%x (%s), "
Dave Wallaceee45d412017-11-24 21:44:06 -05001804 "returning %d (%s)", getpid (), session->vpp_handle,
Florin Coras134a9962018-08-28 11:32:04 -07001805 session->session_index,
Dave Wallace4878cbe2017-11-21 03:45:09 -05001806 state, vppcom_session_state_str (state),
1807 rv, vppcom_retval_str (rv));
Florin Coras54693d22018-07-17 10:46:29 -07001808 return rv;
Dave Wallace33e002b2017-09-06 01:20:02 -04001809 }
1810
Florin Coras0d427d82018-06-27 03:24:07 -07001811 VDBG (3, "VCL<%d>: vpp handle 0x%llx, sid %u: peek %s (%p), ready = %d",
Florin Coras134a9962018-08-28 11:32:04 -07001812 getpid (), session->vpp_handle, session->session_index,
1813 session->tx_fifo, svm_fifo_max_enqueue (session->tx_fifo));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001814
Florin Coras54693d22018-07-17 10:46:29 -07001815 return svm_fifo_max_enqueue (session->tx_fifo);
1816}
1817
Florin Coras99368312018-08-02 10:45:44 -07001818static inline int
Florin Coras134a9962018-08-28 11:32:04 -07001819vcl_mq_dequeue_batch (vcl_worker_t * wrk, svm_msg_q_t * mq)
Florin Coras99368312018-08-02 10:45:44 -07001820{
1821 svm_msg_q_msg_t *msg;
1822 u32 n_msgs;
1823 int i;
1824
1825 n_msgs = svm_msg_q_size (mq);
1826 for (i = 0; i < n_msgs; i++)
1827 {
Florin Coras134a9962018-08-28 11:32:04 -07001828 vec_add2 (wrk->mq_msg_vector, msg, 1);
Florin Coras99368312018-08-02 10:45:44 -07001829 svm_msg_q_sub_w_lock (mq, msg);
1830 }
1831 return n_msgs;
1832}
1833
Florin Coras6d4bb422018-09-04 22:07:27 -07001834#define vcl_fifo_rx_evt_valid_or_break(_fifo) \
1835if (PREDICT_FALSE (svm_fifo_is_empty (_fifo))) \
1836 { \
1837 svm_fifo_unset_event (_fifo); \
1838 if (svm_fifo_is_empty (_fifo)) \
Florin Coras41c9e042018-09-11 00:10:41 -07001839 break; \
Florin Coras6d4bb422018-09-04 22:07:27 -07001840 } \
1841
Florin Coras86f04502018-09-12 16:08:01 -07001842static void
1843vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
1844 unsigned long n_bits, unsigned long *read_map,
1845 unsigned long *write_map,
1846 unsigned long *except_map, u32 * bits_set)
Florin Coras54693d22018-07-17 10:46:29 -07001847{
1848 session_disconnected_msg_t *disconnected_msg;
Florin Coras99368312018-08-02 10:45:44 -07001849 session_connected_msg_t *connected_msg;
Florin Coras54693d22018-07-17 10:46:29 -07001850 session_accepted_msg_t *accepted_msg;
1851 vcl_session_msg_t *vcl_msg;
1852 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07001853 u64 handle;
1854 u32 sid;
1855
1856 switch (e->event_type)
1857 {
1858 case FIFO_EVENT_APP_RX:
1859 vcl_fifo_rx_evt_valid_or_break (e->fifo);
1860 sid = e->fifo->client_session_index;
1861 session = vcl_session_get (wrk, sid);
1862 if (!session)
1863 break;
1864 if (sid < n_bits && read_map)
1865 {
1866 clib_bitmap_set_no_check (read_map, sid, 1);
1867 *bits_set += 1;
1868 }
1869 break;
1870 case FIFO_EVENT_APP_TX:
1871 sid = e->fifo->client_session_index;
1872 session = vcl_session_get (wrk, sid);
1873 if (!session)
1874 break;
1875 if (sid < n_bits && write_map)
1876 {
1877 clib_bitmap_set_no_check (write_map, sid, 1);
1878 *bits_set += 1;
1879 }
1880 break;
1881 case SESSION_IO_EVT_CT_TX:
1882 vcl_fifo_rx_evt_valid_or_break (e->fifo);
1883 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0);
1884 if (!session)
1885 break;
1886 sid = session->session_index;
1887 if (sid < n_bits && read_map)
1888 {
1889 clib_bitmap_set_no_check (read_map, sid, 1);
1890 *bits_set += 1;
1891 }
1892 break;
1893 case SESSION_IO_EVT_CT_RX:
1894 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1);
1895 if (!session)
1896 break;
1897 sid = session->session_index;
1898 if (sid < n_bits && write_map)
1899 {
1900 clib_bitmap_set_no_check (write_map, sid, 1);
1901 *bits_set += 1;
1902 }
1903 break;
1904 case SESSION_CTRL_EVT_ACCEPTED:
1905 accepted_msg = (session_accepted_msg_t *) e->data;
1906 handle = accepted_msg->listener_handle;
1907 session = vcl_session_table_lookup_listener (wrk, handle);
1908 if (!session)
1909 {
1910 clib_warning ("VCL<%d>: ERROR: couldn't find listen session:"
1911 "listener handle %llx", getpid (), handle);
1912 break;
1913 }
1914
1915 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
1916 vcl_msg->accepted_msg = *accepted_msg;
1917 sid = session->session_index;
1918 if (sid < n_bits && read_map)
1919 {
1920 clib_bitmap_set_no_check (read_map, sid, 1);
1921 *bits_set += 1;
1922 }
1923 break;
1924 case SESSION_CTRL_EVT_CONNECTED:
1925 connected_msg = (session_connected_msg_t *) e->data;
1926 vcl_session_connected_handler (wrk, connected_msg);
1927 break;
1928 case SESSION_CTRL_EVT_DISCONNECTED:
1929 disconnected_msg = (session_disconnected_msg_t *) e->data;
1930 sid = vcl_session_index_from_vpp_handle (wrk, disconnected_msg->handle);
1931 if (sid < n_bits && except_map)
1932 {
1933 clib_bitmap_set_no_check (except_map, sid, 1);
1934 *bits_set += 1;
1935 }
1936 break;
1937 case SESSION_CTRL_EVT_RESET:
1938 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
1939 if (sid < n_bits && except_map)
1940 {
1941 clib_bitmap_set_no_check (except_map, sid, 1);
1942 *bits_set += 1;
1943 }
1944 break;
1945 default:
1946 clib_warning ("unhandled: %u", e->event_type);
1947 break;
1948 }
1949}
1950
1951static int
1952vcl_select_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
1953 unsigned long n_bits, unsigned long *read_map,
1954 unsigned long *write_map, unsigned long *except_map,
1955 double time_to_wait, u32 * bits_set)
1956{
Florin Coras99368312018-08-02 10:45:44 -07001957 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07001958 session_event_t *e;
Florin Coras86f04502018-09-12 16:08:01 -07001959 u32 i;
Florin Coras54693d22018-07-17 10:46:29 -07001960
1961 svm_msg_q_lock (mq);
1962 if (svm_msg_q_is_empty (mq))
Dave Wallace4878cbe2017-11-21 03:45:09 -05001963 {
Florin Coras54693d22018-07-17 10:46:29 -07001964 if (*bits_set)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001965 {
Florin Coras54693d22018-07-17 10:46:29 -07001966 svm_msg_q_unlock (mq);
1967 return 0;
1968 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001969
Florin Coras54693d22018-07-17 10:46:29 -07001970 if (!time_to_wait)
1971 {
1972 svm_msg_q_unlock (mq);
1973 return 0;
1974 }
1975 else if (time_to_wait < 0)
1976 {
1977 svm_msg_q_wait (mq);
1978 }
1979 else
1980 {
1981 if (svm_msg_q_timedwait (mq, time_to_wait))
1982 {
1983 svm_msg_q_unlock (mq);
1984 return 0;
1985 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001986 }
1987 }
Florin Coras134a9962018-08-28 11:32:04 -07001988 vcl_mq_dequeue_batch (wrk, mq);
Florin Coras54693d22018-07-17 10:46:29 -07001989 svm_msg_q_unlock (mq);
1990
Florin Coras134a9962018-08-28 11:32:04 -07001991 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07001992 {
Florin Coras134a9962018-08-28 11:32:04 -07001993 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07001994 e = svm_msg_q_msg_data (mq, msg);
Florin Coras86f04502018-09-12 16:08:01 -07001995 vcl_select_handle_mq_event (wrk, e, n_bits, read_map, write_map,
1996 except_map, bits_set);
Florin Coras99368312018-08-02 10:45:44 -07001997 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07001998 }
Florin Coras134a9962018-08-28 11:32:04 -07001999 vec_reset_length (wrk->mq_msg_vector);
Florin Coras54693d22018-07-17 10:46:29 -07002000 return *bits_set;
Dave Wallace543852a2017-08-03 02:11:34 -04002001}
2002
Florin Coras99368312018-08-02 10:45:44 -07002003static int
Florin Coras134a9962018-08-28 11:32:04 -07002004vppcom_select_condvar (vcl_worker_t * wrk, unsigned long n_bits,
2005 unsigned long *read_map, unsigned long *write_map,
2006 unsigned long *except_map, double time_to_wait,
2007 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002008{
2009 double total_wait = 0, wait_slice;
2010 vcl_cut_through_registration_t *cr;
2011
2012 time_to_wait = (time_to_wait == -1) ? 10e9 : time_to_wait;
Florin Coras134a9962018-08-28 11:32:04 -07002013 wait_slice = wrk->cut_through_registrations ? 10e-6 : time_to_wait;
Florin Coras99368312018-08-02 10:45:44 -07002014 do
2015 {
Florin Coras134a9962018-08-28 11:32:04 -07002016 vcl_ct_registration_lock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002017 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002018 pool_foreach (cr, wrk->cut_through_registrations, ({
2019 vcl_select_handle_mq (wrk, cr->mq, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002020 0, bits_set);
2021 }));
2022 /* *INDENT-ON* */
Florin Coras134a9962018-08-28 11:32:04 -07002023 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002024
Florin Coras134a9962018-08-28 11:32:04 -07002025 vcl_select_handle_mq (wrk, wrk->app_event_queue, n_bits, read_map,
2026 write_map, except_map, time_to_wait, bits_set);
Florin Coras99368312018-08-02 10:45:44 -07002027 total_wait += wait_slice;
2028 if (*bits_set)
2029 return *bits_set;
2030 }
2031 while (total_wait < time_to_wait);
2032
2033 return 0;
2034}
2035
2036static int
Florin Coras134a9962018-08-28 11:32:04 -07002037vppcom_select_eventfd (vcl_worker_t * wrk, unsigned long n_bits,
2038 unsigned long *read_map, unsigned long *write_map,
2039 unsigned long *except_map, double time_to_wait,
2040 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002041{
2042 vcl_mq_evt_conn_t *mqc;
2043 int __clib_unused n_read;
2044 int n_mq_evts, i;
2045 u64 buf;
2046
Florin Coras134a9962018-08-28 11:32:04 -07002047 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
2048 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2049 vec_len (wrk->mq_events), time_to_wait);
Florin Coras99368312018-08-02 10:45:44 -07002050 for (i = 0; i < n_mq_evts; i++)
2051 {
Florin Coras134a9962018-08-28 11:32:04 -07002052 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002053 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002054 vcl_select_handle_mq (wrk, mqc->mq, n_bits, read_map, write_map,
Florin Coras99368312018-08-02 10:45:44 -07002055 except_map, 0, bits_set);
2056 }
2057
2058 return (n_mq_evts > 0 ? (int) *bits_set : 0);
2059}
2060
Dave Wallace543852a2017-08-03 02:11:34 -04002061int
2062vppcom_select (unsigned long n_bits, unsigned long *read_map,
2063 unsigned long *write_map, unsigned long *except_map,
2064 double time_to_wait)
2065{
Florin Coras54693d22018-07-17 10:46:29 -07002066 u32 sid, minbits = clib_max (n_bits, BITS (uword)), bits_set = 0;
Florin Coras134a9962018-08-28 11:32:04 -07002067 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002068 vcl_session_t *session = 0;
Florin Coras86f04502018-09-12 16:08:01 -07002069 int rv, i;
Dave Wallace543852a2017-08-03 02:11:34 -04002070
2071 ASSERT (sizeof (clib_bitmap_t) == sizeof (long int));
2072
Dave Wallace7876d392017-10-19 03:53:57 -04002073 if (n_bits && read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002074 {
Florin Coras134a9962018-08-28 11:32:04 -07002075 clib_bitmap_validate (wrk->rd_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002076 clib_memcpy_fast (wrk->rd_bitmap, read_map,
2077 vec_len (wrk->rd_bitmap) * sizeof (clib_bitmap_t));
Florin Coras134a9962018-08-28 11:32:04 -07002078 memset (read_map, 0, vec_len (wrk->rd_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace543852a2017-08-03 02:11:34 -04002079 }
Dave Wallace7876d392017-10-19 03:53:57 -04002080 if (n_bits && write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002081 {
Florin Coras134a9962018-08-28 11:32:04 -07002082 clib_bitmap_validate (wrk->wr_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002083 clib_memcpy_fast (wrk->wr_bitmap, write_map,
2084 vec_len (wrk->wr_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05002085 memset (write_map, 0,
Florin Coras134a9962018-08-28 11:32:04 -07002086 vec_len (wrk->wr_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace543852a2017-08-03 02:11:34 -04002087 }
Dave Wallace7876d392017-10-19 03:53:57 -04002088 if (n_bits && except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002089 {
Florin Coras134a9962018-08-28 11:32:04 -07002090 clib_bitmap_validate (wrk->ex_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002091 clib_memcpy_fast (wrk->ex_bitmap, except_map,
2092 vec_len (wrk->ex_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05002093 memset (except_map, 0,
Florin Coras134a9962018-08-28 11:32:04 -07002094 vec_len (wrk->ex_bitmap) * sizeof (clib_bitmap_t));
Dave Wallace543852a2017-08-03 02:11:34 -04002095 }
2096
Florin Coras54693d22018-07-17 10:46:29 -07002097 if (!n_bits)
2098 return 0;
2099
2100 if (!write_map)
2101 goto check_rd;
2102
2103 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002104 clib_bitmap_foreach (sid, wrk->wr_bitmap, ({
2105 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002106 {
Florin Coras47c40e22018-11-26 17:01:36 -08002107 if (except_map && sid < minbits)
2108 clib_bitmap_set_no_check (except_map, sid, 1);
2109 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002110 }
2111
2112 rv = svm_fifo_is_full (session->tx_fifo);
Florin Coras54693d22018-07-17 10:46:29 -07002113 if (!rv)
2114 {
2115 clib_bitmap_set_no_check (write_map, sid, 1);
2116 bits_set++;
2117 }
2118 }));
2119
2120check_rd:
2121 if (!read_map)
2122 goto check_mq;
Florin Coras99368312018-08-02 10:45:44 -07002123
Florin Coras134a9962018-08-28 11:32:04 -07002124 clib_bitmap_foreach (sid, wrk->rd_bitmap, ({
2125 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002126 {
Florin Coras47c40e22018-11-26 17:01:36 -08002127 if (except_map && sid < minbits)
2128 clib_bitmap_set_no_check (except_map, sid, 1);
2129 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002130 }
2131
2132 rv = vppcom_session_read_ready (session);
Florin Coras54693d22018-07-17 10:46:29 -07002133 if (rv)
2134 {
2135 clib_bitmap_set_no_check (read_map, sid, 1);
2136 bits_set++;
2137 }
2138 }));
2139 /* *INDENT-ON* */
2140
2141check_mq:
Dave Wallace543852a2017-08-03 02:11:34 -04002142
Florin Coras86f04502018-09-12 16:08:01 -07002143 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2144 {
2145 vcl_select_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i], n_bits,
2146 read_map, write_map, except_map, &bits_set);
2147 }
2148 vec_reset_length (wrk->unhandled_evts_vector);
2149
Florin Coras99368312018-08-02 10:45:44 -07002150 if (vcm->cfg.use_mq_eventfd)
Florin Coras134a9962018-08-28 11:32:04 -07002151 vppcom_select_eventfd (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002152 time_to_wait, &bits_set);
2153 else
Florin Coras134a9962018-08-28 11:32:04 -07002154 vppcom_select_condvar (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002155 time_to_wait, &bits_set);
Florin Coras54693d22018-07-17 10:46:29 -07002156
Dave Wallace543852a2017-08-03 02:11:34 -04002157 return (bits_set);
2158}
2159
Dave Wallacef7f809c2017-10-03 01:48:42 -04002160static inline void
Florin Coras134a9962018-08-28 11:32:04 -07002161vep_verify_epoll_chain (vcl_worker_t * wrk, u32 vep_idx)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002162{
Florin Coras7e12d942018-06-27 14:32:43 -07002163 vcl_session_t *session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002164 vppcom_epoll_t *vep;
Dave Wallace498b3a52017-11-09 13:00:34 -05002165 u32 sid = vep_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002166
Dave Wallace498b3a52017-11-09 13:00:34 -05002167 if (VPPCOM_DEBUG <= 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002168 return;
2169
2170 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Florin Coras134a9962018-08-28 11:32:04 -07002171 session = vcl_session_get (wrk, vep_idx);
Florin Coras070453d2018-08-24 17:04:27 -07002172 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002173 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002174 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!",
2175 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002176 goto done;
2177 }
2178 if (PREDICT_FALSE (!session->is_vep))
2179 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002180 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
2181 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002182 goto done;
2183 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002184 vep = &session->vep;
Dave Wallace048b1d62018-01-03 22:24:41 -05002185 clib_warning ("VCL<%d>: vep_idx (%u): Dumping epoll chain\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05002186 "{\n"
2187 " is_vep = %u\n"
2188 " is_vep_session = %u\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05002189 " next_sid = 0x%x (%u)\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05002190 " wait_cont_idx = 0x%x (%u)\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05002191 "}\n", getpid (), vep_idx,
2192 session->is_vep, session->is_vep_session,
Florin Coras134a9962018-08-28 11:32:04 -07002193 vep->next_sh, vep->next_sh,
Dave Wallace498b3a52017-11-09 13:00:34 -05002194 session->wait_cont_idx, session->wait_cont_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002195
Florin Coras134a9962018-08-28 11:32:04 -07002196 for (sid = vep->next_sh; sid != ~0; sid = vep->next_sh)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002197 {
Florin Coras134a9962018-08-28 11:32:04 -07002198 session = vcl_session_get (wrk, sid);
Florin Coras070453d2018-08-24 17:04:27 -07002199 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002200 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002201 clib_warning ("VCL<%d>: ERROR: Invalid sid (%u)!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002202 goto done;
2203 }
2204 if (PREDICT_FALSE (session->is_vep))
Dave Wallace048b1d62018-01-03 22:24:41 -05002205 clib_warning ("VCL<%d>: ERROR: sid (%u) is a vep!",
2206 getpid (), vep_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002207 else if (PREDICT_FALSE (!session->is_vep_session))
2208 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002209 clib_warning ("VCL<%d>: ERROR: session (%u) "
2210 "is not a vep session!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002211 goto done;
2212 }
2213 vep = &session->vep;
Florin Coras134a9962018-08-28 11:32:04 -07002214 if (PREDICT_FALSE (vep->vep_sh != vep_idx))
Dave Wallace048b1d62018-01-03 22:24:41 -05002215 clib_warning ("VCL<%d>: ERROR: session (%u) vep_idx (%u) != "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002216 "vep_idx (%u)!", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002217 sid, session->vep.vep_sh, vep_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002218 if (session->is_vep_session)
2219 {
2220 clib_warning ("vep_idx[%u]: sid 0x%x (%u)\n"
2221 "{\n"
2222 " next_sid = 0x%x (%u)\n"
2223 " prev_sid = 0x%x (%u)\n"
2224 " vep_idx = 0x%x (%u)\n"
2225 " ev.events = 0x%x\n"
2226 " ev.data.u64 = 0x%llx\n"
2227 " et_mask = 0x%x\n"
2228 "}\n",
2229 vep_idx, sid, sid,
Florin Coras134a9962018-08-28 11:32:04 -07002230 vep->next_sh, vep->next_sh,
2231 vep->prev_sh, vep->prev_sh,
2232 vep->vep_sh, vep->vep_sh,
Dave Wallace4878cbe2017-11-21 03:45:09 -05002233 vep->ev.events, vep->ev.data.u64, vep->et_mask);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002234 }
2235 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002236
2237done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002238 clib_warning ("VCL<%d>: vep_idx (%u): Dump complete!\n",
2239 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002240}
2241
2242int
2243vppcom_epoll_create (void)
2244{
Florin Coras134a9962018-08-28 11:32:04 -07002245 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002246 vcl_session_t *vep_session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002247
Florin Coras134a9962018-08-28 11:32:04 -07002248 vep_session = vcl_session_alloc (wrk);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002249
2250 vep_session->is_vep = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002251 vep_session->vep.vep_sh = ~0;
2252 vep_session->vep.next_sh = ~0;
2253 vep_session->vep.prev_sh = ~0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002254 vep_session->wait_cont_idx = ~0;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002255 vep_session->vpp_handle = ~0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002256
Florin Coras134a9962018-08-28 11:32:04 -07002257 vcl_evt (VCL_EVT_EPOLL_CREATE, vep_session, vep_sh);
Florin Coras0d427d82018-06-27 03:24:07 -07002258 VDBG (0, "VCL<%d>: Created vep_idx %u / sid %u!",
Florin Coras134a9962018-08-28 11:32:04 -07002259 getpid (), vep_session->session_index, vep_session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08002260
Florin Corasab2f6db2018-08-31 14:31:41 -07002261 return vcl_session_handle (vep_session);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002262}
2263
2264int
Florin Coras134a9962018-08-28 11:32:04 -07002265vppcom_epoll_ctl (uint32_t vep_handle, int op, uint32_t session_handle,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002266 struct epoll_event *event)
2267{
Florin Coras134a9962018-08-28 11:32:04 -07002268 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002269 vcl_session_t *vep_session;
2270 vcl_session_t *session;
Florin Coras070453d2018-08-24 17:04:27 -07002271 int rv = VPPCOM_OK;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002272
Florin Coras134a9962018-08-28 11:32:04 -07002273 if (vep_handle == session_handle)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002274 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002275 clib_warning ("VCL<%d>: ERROR: vep_idx == session_index (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002276 getpid (), vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002277 return VPPCOM_EINVAL;
2278 }
2279
Florin Coras134a9962018-08-28 11:32:04 -07002280 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002281 if (PREDICT_FALSE (!vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002282 {
Florin Coras134a9962018-08-28 11:32:04 -07002283 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002284 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002285 }
2286 if (PREDICT_FALSE (!vep_session->is_vep))
2287 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002288 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
Florin Coras134a9962018-08-28 11:32:04 -07002289 getpid (), vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002290 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002291 }
2292
Florin Coras134a9962018-08-28 11:32:04 -07002293 ASSERT (vep_session->vep.vep_sh == ~0);
2294 ASSERT (vep_session->vep.prev_sh == ~0);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002295
Florin Coras134a9962018-08-28 11:32:04 -07002296 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002297 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002298 {
Florin Coras134a9962018-08-28 11:32:04 -07002299 VDBG (0, "VCL<%d>: ERROR: Invalid session_handle (%u)!",
2300 getpid (), session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002301 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002302 }
2303 if (PREDICT_FALSE (session->is_vep))
2304 {
Florin Coras134a9962018-08-28 11:32:04 -07002305 clib_warning ("ERROR: session_handle (%u) is a vep!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002306 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002307 }
2308
2309 switch (op)
2310 {
2311 case EPOLL_CTL_ADD:
2312 if (PREDICT_FALSE (!event))
2313 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002314 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002315 "epoll_event structure!", getpid ());
Florin Coras070453d2018-08-24 17:04:27 -07002316 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002317 }
Florin Coras134a9962018-08-28 11:32:04 -07002318 if (vep_session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002319 {
Florin Coras7e12d942018-06-27 14:32:43 -07002320 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002321 next_session = vcl_session_get_w_handle (wrk,
2322 vep_session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002323 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002324 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002325 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: Invalid "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002326 "vep.next_sid (%u) on vep_idx (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002327 getpid (), vep_session->vep.next_sh, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002328 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002329 }
Florin Coras134a9962018-08-28 11:32:04 -07002330 ASSERT (next_session->vep.prev_sh == vep_handle);
2331 next_session->vep.prev_sh = session_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002332 }
Florin Coras134a9962018-08-28 11:32:04 -07002333 session->vep.next_sh = vep_session->vep.next_sh;
2334 session->vep.prev_sh = vep_handle;
2335 session->vep.vep_sh = vep_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002336 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2337 session->vep.ev = *event;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002338 session->is_vep = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002339 session->is_vep_session = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002340 vep_session->vep.next_sh = session_handle;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08002341
Florin Coras070453d2018-08-24 17:04:27 -07002342 VDBG (1, "VCL<%d>: EPOLL_CTL_ADD: vep_idx %u, sid %u, events 0x%x, "
Florin Coras134a9962018-08-28 11:32:04 -07002343 "data 0x%llx!", getpid (), vep_handle, session_handle,
2344 event->events, event->data.u64);
Florin Coras0d427d82018-06-27 03:24:07 -07002345 vcl_evt (VCL_EVT_EPOLL_CTLADD, session, event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002346 break;
2347
2348 case EPOLL_CTL_MOD:
2349 if (PREDICT_FALSE (!event))
2350 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002351 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_MOD: NULL pointer to "
Dave Wallace2e005bb2017-11-07 01:21:39 -05002352 "epoll_event structure!", getpid ());
Dave Wallacef7f809c2017-10-03 01:48:42 -04002353 rv = VPPCOM_EINVAL;
2354 goto done;
2355 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002356 else if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002357 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002358 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: "
Florin Coras134a9962018-08-28 11:32:04 -07002359 "not a vep session!", getpid (), session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002360 rv = VPPCOM_EINVAL;
2361 goto done;
2362 }
Florin Coras134a9962018-08-28 11:32:04 -07002363 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002364 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002365 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002366 "vep_idx (%u) != vep_idx (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002367 getpid (), session_handle,
2368 session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002369 rv = VPPCOM_EINVAL;
2370 goto done;
2371 }
2372 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2373 session->vep.ev = *event;
Florin Coras0d427d82018-06-27 03:24:07 -07002374 VDBG (1, "VCL<%d>: EPOLL_CTL_MOD: vep_idx %u, sid %u, events 0x%x,"
Florin Coras134a9962018-08-28 11:32:04 -07002375 " data 0x%llx!", getpid (), vep_handle, session_handle,
2376 event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002377 break;
2378
2379 case EPOLL_CTL_DEL:
Dave Wallace4878cbe2017-11-21 03:45:09 -05002380 if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002381 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002382 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: "
Florin Coras134a9962018-08-28 11:32:04 -07002383 "not a vep session!", getpid (), session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002384 rv = VPPCOM_EINVAL;
2385 goto done;
2386 }
Florin Coras134a9962018-08-28 11:32:04 -07002387 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002388 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002389 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002390 "vep_idx (%u) != vep_idx (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002391 getpid (), session_handle,
2392 session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002393 rv = VPPCOM_EINVAL;
2394 goto done;
2395 }
2396
2397 vep_session->wait_cont_idx =
Florin Coras134a9962018-08-28 11:32:04 -07002398 (vep_session->wait_cont_idx == session_handle) ?
2399 session->vep.next_sh : vep_session->wait_cont_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002400
Florin Coras134a9962018-08-28 11:32:04 -07002401 if (session->vep.prev_sh == vep_handle)
2402 vep_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002403 else
2404 {
Florin Coras7e12d942018-06-27 14:32:43 -07002405 vcl_session_t *prev_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002406 prev_session = vcl_session_get_w_handle (wrk, session->vep.prev_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002407 if (PREDICT_FALSE (!prev_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002408 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002409 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002410 "vep.prev_sid (%u) on sid (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002411 getpid (), session->vep.prev_sh, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002412 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002413 }
Florin Coras134a9962018-08-28 11:32:04 -07002414 ASSERT (prev_session->vep.next_sh == session_handle);
2415 prev_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002416 }
Florin Coras134a9962018-08-28 11:32:04 -07002417 if (session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002418 {
Florin Coras7e12d942018-06-27 14:32:43 -07002419 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002420 next_session = vcl_session_get_w_handle (wrk, session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002421 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002422 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002423 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002424 "vep.next_sid (%u) on sid (%u)!",
Florin Coras134a9962018-08-28 11:32:04 -07002425 getpid (), session->vep.next_sh, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002426 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002427 }
Florin Coras134a9962018-08-28 11:32:04 -07002428 ASSERT (next_session->vep.prev_sh == session_handle);
2429 next_session->vep.prev_sh = session->vep.prev_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002430 }
2431
2432 memset (&session->vep, 0, sizeof (session->vep));
Florin Coras134a9962018-08-28 11:32:04 -07002433 session->vep.next_sh = ~0;
2434 session->vep.prev_sh = ~0;
2435 session->vep.vep_sh = ~0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002436 session->is_vep_session = 0;
Florin Coras0d427d82018-06-27 03:24:07 -07002437 VDBG (1, "VCL<%d>: EPOLL_CTL_DEL: vep_idx %u, sid %u!",
Florin Coras134a9962018-08-28 11:32:04 -07002438 getpid (), vep_handle, session_handle);
2439 vcl_evt (VCL_EVT_EPOLL_CTLDEL, session, vep_sh);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002440 break;
2441
2442 default:
Dave Wallace048b1d62018-01-03 22:24:41 -05002443 clib_warning ("VCL<%d>: ERROR: Invalid operation (%d)!", getpid (), op);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002444 rv = VPPCOM_EINVAL;
2445 }
2446
Florin Coras134a9962018-08-28 11:32:04 -07002447 vep_verify_epoll_chain (wrk, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002448
2449done:
Dave Wallacef7f809c2017-10-03 01:48:42 -04002450 return rv;
2451}
2452
Florin Coras86f04502018-09-12 16:08:01 -07002453static inline void
2454vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
2455 struct epoll_event *events, u32 * num_ev)
Florin Coras54693d22018-07-17 10:46:29 -07002456{
2457 session_disconnected_msg_t *disconnected_msg;
2458 session_connected_msg_t *connected_msg;
2459 session_accepted_msg_t *accepted_msg;
Florin Coras54693d22018-07-17 10:46:29 -07002460 u64 session_evt_data = ~0, handle;
Florin Coras99368312018-08-02 10:45:44 -07002461 u32 sid = ~0, session_events;
Florin Coras54693d22018-07-17 10:46:29 -07002462 vcl_session_msg_t *vcl_msg;
2463 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07002464 u8 add_event = 0;
2465
2466 switch (e->event_type)
2467 {
2468 case FIFO_EVENT_APP_RX:
2469 ASSERT (e->fifo->client_thread_index == vcl_get_worker_index ());
2470 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2471 sid = e->fifo->client_session_index;
2472 session = vcl_session_get (wrk, sid);
2473 session_events = session->vep.ev.events;
Florin Corasaa27eb92018-10-13 12:20:01 -07002474 if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
Florin Coras86f04502018-09-12 16:08:01 -07002475 break;
2476 add_event = 1;
2477 events[*num_ev].events |= EPOLLIN;
2478 session_evt_data = session->vep.ev.data.u64;
Florin Corasaa27eb92018-10-13 12:20:01 -07002479 session->has_rx_evt = 1;
Florin Coras86f04502018-09-12 16:08:01 -07002480 break;
2481 case FIFO_EVENT_APP_TX:
2482 sid = e->fifo->client_session_index;
2483 session = vcl_session_get (wrk, sid);
2484 session_events = session->vep.ev.events;
2485 if (!(EPOLLOUT & session_events))
2486 break;
2487 add_event = 1;
2488 events[*num_ev].events |= EPOLLOUT;
2489 session_evt_data = session->vep.ev.data.u64;
2490 break;
2491 case SESSION_IO_EVT_CT_TX:
2492 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2493 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0);
2494 sid = session->session_index;
2495 session_events = session->vep.ev.events;
Florin Corasaa27eb92018-10-13 12:20:01 -07002496 if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
Florin Coras86f04502018-09-12 16:08:01 -07002497 break;
2498 add_event = 1;
2499 events[*num_ev].events |= EPOLLIN;
2500 session_evt_data = session->vep.ev.data.u64;
Florin Corasaa27eb92018-10-13 12:20:01 -07002501 session->has_rx_evt = 1;
Florin Coras86f04502018-09-12 16:08:01 -07002502 break;
2503 case SESSION_IO_EVT_CT_RX:
2504 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1);
2505 sid = session->session_index;
2506 session_events = session->vep.ev.events;
2507 if (!(EPOLLOUT & session_events))
2508 break;
2509 add_event = 1;
2510 events[*num_ev].events |= EPOLLOUT;
2511 session_evt_data = session->vep.ev.data.u64;
2512 break;
2513 case SESSION_CTRL_EVT_ACCEPTED:
2514 accepted_msg = (session_accepted_msg_t *) e->data;
2515 handle = accepted_msg->listener_handle;
2516 session = vcl_session_table_lookup_listener (wrk, handle);
2517 if (!session)
2518 {
2519 clib_warning ("VCL<%d>: ERROR: couldn't find listen session:"
2520 "listener handle %llx", getpid (), handle);
2521 break;
2522 }
2523
2524 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
2525 vcl_msg->accepted_msg = *accepted_msg;
2526 session_events = session->vep.ev.events;
2527 if (!(EPOLLIN & session_events))
2528 break;
2529
2530 add_event = 1;
2531 events[*num_ev].events |= EPOLLIN;
2532 session_evt_data = session->vep.ev.data.u64;
2533 break;
2534 case SESSION_CTRL_EVT_CONNECTED:
2535 connected_msg = (session_connected_msg_t *) e->data;
2536 vcl_session_connected_handler (wrk, connected_msg);
2537 /* Generate EPOLLOUT because there's no connected event */
2538 sid = vcl_session_index_from_vpp_handle (wrk, connected_msg->handle);
2539 session = vcl_session_get (wrk, sid);
2540 session_events = session->vep.ev.events;
2541 if (EPOLLOUT & session_events)
2542 {
2543 add_event = 1;
2544 events[*num_ev].events |= EPOLLOUT;
2545 session_evt_data = session->vep.ev.data.u64;
2546 }
2547 break;
2548 case SESSION_CTRL_EVT_DISCONNECTED:
2549 disconnected_msg = (session_disconnected_msg_t *) e->data;
2550 sid = vcl_session_index_from_vpp_handle (wrk, disconnected_msg->handle);
2551 if (!(session = vcl_session_get (wrk, sid)))
2552 break;
2553 add_event = 1;
2554 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2555 session_evt_data = session->vep.ev.data.u64;
2556 session_events = session->vep.ev.events;
2557 break;
2558 case SESSION_CTRL_EVT_RESET:
2559 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
2560 if (!(session = vcl_session_get (wrk, sid)))
2561 break;
2562 add_event = 1;
2563 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2564 session_evt_data = session->vep.ev.data.u64;
2565 session_events = session->vep.ev.events;
2566 break;
2567 default:
2568 VDBG (0, "unhandled: %u", e->event_type);
2569 break;
2570 }
2571
2572 if (add_event)
2573 {
2574 events[*num_ev].data.u64 = session_evt_data;
2575 if (EPOLLONESHOT & session_events)
2576 {
2577 session = vcl_session_get (wrk, sid);
2578 session->vep.ev.events = 0;
2579 }
2580 *num_ev += 1;
2581 }
2582}
2583
2584static int
2585vcl_epoll_wait_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
2586 struct epoll_event *events, u32 maxevents,
2587 double wait_for_time, u32 * num_ev)
2588{
Florin Coras99368312018-08-02 10:45:44 -07002589 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07002590 session_event_t *e;
Florin Coras54693d22018-07-17 10:46:29 -07002591 int i;
2592
Florin Coras539663c2018-09-28 14:59:37 -07002593 if (vec_len (wrk->mq_msg_vector) && svm_msg_q_is_empty (mq))
2594 goto handle_dequeued;
2595
Florin Coras54693d22018-07-17 10:46:29 -07002596 svm_msg_q_lock (mq);
2597 if (svm_msg_q_is_empty (mq))
2598 {
2599 if (!wait_for_time)
2600 {
2601 svm_msg_q_unlock (mq);
2602 return 0;
2603 }
2604 else if (wait_for_time < 0)
2605 {
2606 svm_msg_q_wait (mq);
2607 }
2608 else
2609 {
Florin Coras60f1fc12018-08-16 14:57:31 -07002610 if (svm_msg_q_timedwait (mq, wait_for_time / 1e3))
Florin Coras54693d22018-07-17 10:46:29 -07002611 {
2612 svm_msg_q_unlock (mq);
2613 return 0;
2614 }
2615 }
2616 }
Florin Coras134a9962018-08-28 11:32:04 -07002617 vcl_mq_dequeue_batch (wrk, mq);
Florin Coras54693d22018-07-17 10:46:29 -07002618 svm_msg_q_unlock (mq);
2619
Florin Coras539663c2018-09-28 14:59:37 -07002620handle_dequeued:
Florin Coras134a9962018-08-28 11:32:04 -07002621 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07002622 {
Florin Coras134a9962018-08-28 11:32:04 -07002623 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07002624 e = svm_msg_q_msg_data (mq, msg);
Florin Corasaa27eb92018-10-13 12:20:01 -07002625 if (*num_ev < maxevents)
2626 vcl_epoll_wait_handle_mq_event (wrk, e, events, num_ev);
2627 else
2628 vec_add1 (wrk->unhandled_evts_vector, *e);
Florin Coras99368312018-08-02 10:45:44 -07002629 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002630 }
Florin Corasaa27eb92018-10-13 12:20:01 -07002631 vec_reset_length (wrk->mq_msg_vector);
Florin Coras86f04502018-09-12 16:08:01 -07002632
Florin Coras54693d22018-07-17 10:46:29 -07002633 return *num_ev;
2634}
2635
Florin Coras99368312018-08-02 10:45:44 -07002636static int
Florin Coras134a9962018-08-28 11:32:04 -07002637vppcom_epoll_wait_condvar (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002638 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002639{
2640 vcl_cut_through_registration_t *cr;
2641 double total_wait = 0, wait_slice;
Florin Coras99368312018-08-02 10:45:44 -07002642 int rv;
2643
2644 wait_for_time = (wait_for_time == -1) ? (double) 10e9 : wait_for_time;
Florin Coras134a9962018-08-28 11:32:04 -07002645 wait_slice = wrk->cut_through_registrations ? 10e-6 : wait_for_time;
Florin Coras99368312018-08-02 10:45:44 -07002646
2647 do
2648 {
Florin Coras134a9962018-08-28 11:32:04 -07002649 vcl_ct_registration_lock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002650 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002651 pool_foreach (cr, wrk->cut_through_registrations, ({
Florin Coras86f04502018-09-12 16:08:01 -07002652 vcl_epoll_wait_handle_mq (wrk, cr->mq, events, maxevents, 0, &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002653 }));
2654 /* *INDENT-ON* */
Florin Coras134a9962018-08-28 11:32:04 -07002655 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002656
Florin Coras134a9962018-08-28 11:32:04 -07002657 rv = vcl_epoll_wait_handle_mq (wrk, wrk->app_event_queue, events,
Florin Coras86f04502018-09-12 16:08:01 -07002658 maxevents, n_evts ? 0 : wait_slice,
2659 &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002660 if (rv)
2661 total_wait += wait_slice;
Florin Coras86f04502018-09-12 16:08:01 -07002662 if (n_evts)
2663 return n_evts;
Florin Coras99368312018-08-02 10:45:44 -07002664 }
2665 while (total_wait < wait_for_time);
Florin Coras86f04502018-09-12 16:08:01 -07002666 return n_evts;
Florin Coras99368312018-08-02 10:45:44 -07002667}
2668
2669static int
Florin Coras134a9962018-08-28 11:32:04 -07002670vppcom_epoll_wait_eventfd (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002671 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002672{
2673 vcl_mq_evt_conn_t *mqc;
2674 int __clib_unused n_read;
2675 int n_mq_evts, i;
Florin Coras99368312018-08-02 10:45:44 -07002676 u64 buf;
2677
Florin Coras134a9962018-08-28 11:32:04 -07002678 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
Florin Corasa4878ed2018-10-12 13:09:36 -07002679again:
Florin Coras134a9962018-08-28 11:32:04 -07002680 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2681 vec_len (wrk->mq_events), wait_for_time);
Florin Coras99368312018-08-02 10:45:44 -07002682 for (i = 0; i < n_mq_evts; i++)
2683 {
Florin Coras134a9962018-08-28 11:32:04 -07002684 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002685 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002686 vcl_epoll_wait_handle_mq (wrk, mqc->mq, events, maxevents, 0, &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002687 }
Florin Corasa4878ed2018-10-12 13:09:36 -07002688 if (!n_evts && n_mq_evts > 0)
2689 goto again;
Florin Coras99368312018-08-02 10:45:44 -07002690
2691 return (int) n_evts;
2692}
2693
Dave Wallacef7f809c2017-10-03 01:48:42 -04002694int
Florin Coras134a9962018-08-28 11:32:04 -07002695vppcom_epoll_wait (uint32_t vep_handle, struct epoll_event *events,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002696 int maxevents, double wait_for_time)
2697{
Florin Coras134a9962018-08-28 11:32:04 -07002698 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002699 vcl_session_t *vep_session;
Florin Coras86f04502018-09-12 16:08:01 -07002700 u32 n_evts = 0;
2701 int i;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002702
2703 if (PREDICT_FALSE (maxevents <= 0))
2704 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002705 clib_warning ("VCL<%d>: ERROR: Invalid maxevents (%d)!",
Dave Wallace4878cbe2017-11-21 03:45:09 -05002706 getpid (), maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002707 return VPPCOM_EINVAL;
2708 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002709
Florin Coras134a9962018-08-28 11:32:04 -07002710 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras14598772018-09-04 19:47:52 -07002711 if (!vep_session)
2712 return VPPCOM_EBADFD;
2713
Florin Coras54693d22018-07-17 10:46:29 -07002714 if (PREDICT_FALSE (!vep_session->is_vep))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002715 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002716 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
Florin Coras134a9962018-08-28 11:32:04 -07002717 getpid (), vep_handle);
Florin Coras54693d22018-07-17 10:46:29 -07002718 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002719 }
Florin Coras54693d22018-07-17 10:46:29 -07002720
2721 memset (events, 0, sizeof (*events) * maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002722
Florin Coras86f04502018-09-12 16:08:01 -07002723 if (vec_len (wrk->unhandled_evts_vector))
2724 {
2725 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2726 {
2727 vcl_epoll_wait_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i],
2728 events, &n_evts);
2729 if (n_evts == maxevents)
2730 {
2731 i += 1;
2732 break;
2733 }
2734 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002735
Florin Coras86f04502018-09-12 16:08:01 -07002736 vec_delete (wrk->unhandled_evts_vector, i, 0);
2737 }
2738
2739 if (vcm->cfg.use_mq_eventfd)
2740 return vppcom_epoll_wait_eventfd (wrk, events, maxevents, n_evts,
2741 wait_for_time);
2742
2743 return vppcom_epoll_wait_condvar (wrk, events, maxevents, n_evts,
2744 wait_for_time);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002745}
2746
Dave Wallace35830af2017-10-09 01:43:42 -04002747int
Florin Coras134a9962018-08-28 11:32:04 -07002748vppcom_session_attr (uint32_t session_handle, uint32_t op,
Dave Wallace35830af2017-10-09 01:43:42 -04002749 void *buffer, uint32_t * buflen)
2750{
Florin Coras134a9962018-08-28 11:32:04 -07002751 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002752 vcl_session_t *session;
Dave Wallace35830af2017-10-09 01:43:42 -04002753 int rv = VPPCOM_OK;
2754 u32 *flags = buffer;
Steven2199aab2017-10-15 20:18:47 -07002755 vppcom_endpt_t *ep = buffer;
Dave Wallace35830af2017-10-09 01:43:42 -04002756
Florin Coras134a9962018-08-28 11:32:04 -07002757 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002758 if (!session)
2759 return VPPCOM_EBADFD;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002760
Dave Wallace35830af2017-10-09 01:43:42 -04002761 switch (op)
2762 {
2763 case VPPCOM_ATTR_GET_NREAD:
Florin Coras54693d22018-07-17 10:46:29 -07002764 rv = vppcom_session_read_ready (session);
Florin Coras0d427d82018-06-27 03:24:07 -07002765 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d",
2766 getpid (), rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002767 break;
2768
Dave Wallace227867f2017-11-13 21:21:53 -05002769 case VPPCOM_ATTR_GET_NWRITE:
Florin Coras134a9962018-08-28 11:32:04 -07002770 rv = vppcom_session_write_ready (session);
Florin Coras0d427d82018-06-27 03:24:07 -07002771 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d",
Florin Coras134a9962018-08-28 11:32:04 -07002772 getpid (), session_handle, rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002773 break;
2774
2775 case VPPCOM_ATTR_GET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002776 if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002777 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002778 *flags = O_RDWR | (VCL_SESS_ATTR_TEST (session->attr,
2779 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002780 *buflen = sizeof (*flags);
Florin Coras0d427d82018-06-27 03:24:07 -07002781 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_FLAGS: sid %u, flags = 0x%08x, "
2782 "is_nonblocking = %u", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002783 session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07002784 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002785 }
2786 else
2787 rv = VPPCOM_EINVAL;
2788 break;
2789
2790 case VPPCOM_ATTR_SET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002791 if (PREDICT_TRUE (buffer && buflen && (*buflen == sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002792 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002793 if (*flags & O_NONBLOCK)
2794 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
2795 else
2796 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_NONBLOCK);
2797
Florin Coras0d427d82018-06-27 03:24:07 -07002798 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_FLAGS: sid %u, flags = 0x%08x,"
2799 " is_nonblocking = %u",
Florin Coras134a9962018-08-28 11:32:04 -07002800 getpid (), session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07002801 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002802 }
2803 else
2804 rv = VPPCOM_EINVAL;
2805 break;
2806
2807 case VPPCOM_ATTR_GET_PEER_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002808 if (PREDICT_TRUE (buffer && buflen &&
2809 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002810 {
Florin Coras7e12d942018-06-27 14:32:43 -07002811 ep->is_ip4 = session->transport.is_ip4;
2812 ep->port = session->transport.rmt_port;
2813 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05002814 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
2815 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07002816 else
Dave Barach178cf492018-11-13 16:34:13 -05002817 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
2818 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07002819 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07002820 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = %u, "
2821 "addr = %U, port %u", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002822 session_handle, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07002823 &session->transport.rmt_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002824 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2825 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002826 }
2827 else
2828 rv = VPPCOM_EINVAL;
2829 break;
2830
2831 case VPPCOM_ATTR_GET_LCL_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002832 if (PREDICT_TRUE (buffer && buflen &&
2833 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002834 {
Florin Coras7e12d942018-06-27 14:32:43 -07002835 ep->is_ip4 = session->transport.is_ip4;
2836 ep->port = session->transport.lcl_port;
2837 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05002838 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip4,
2839 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07002840 else
Dave Barach178cf492018-11-13 16:34:13 -05002841 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip6,
2842 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07002843 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07002844 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = %u,"
2845 " addr = %U port %d", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002846 session_handle, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07002847 &session->transport.lcl_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002848 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2849 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002850 }
2851 else
2852 rv = VPPCOM_EINVAL;
2853 break;
Stevenb5a11602017-10-11 09:59:30 -07002854
Dave Wallace048b1d62018-01-03 22:24:41 -05002855 case VPPCOM_ATTR_GET_LIBC_EPFD:
2856 rv = session->libc_epfd;
Florin Coras0d427d82018-06-27 03:24:07 -07002857 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d",
2858 getpid (), rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002859 break;
2860
2861 case VPPCOM_ATTR_SET_LIBC_EPFD:
2862 if (PREDICT_TRUE (buffer && buflen &&
2863 (*buflen == sizeof (session->libc_epfd))))
2864 {
2865 session->libc_epfd = *(int *) buffer;
2866 *buflen = sizeof (session->libc_epfd);
2867
Florin Coras0d427d82018-06-27 03:24:07 -07002868 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_LIBC_EPFD: libc_epfd %d, "
2869 "buflen %d", getpid (), session->libc_epfd, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002870 }
2871 else
2872 rv = VPPCOM_EINVAL;
2873 break;
2874
2875 case VPPCOM_ATTR_GET_PROTOCOL:
2876 if (buffer && buflen && (*buflen >= sizeof (int)))
2877 {
Florin Coras7e12d942018-06-27 14:32:43 -07002878 *(int *) buffer = session->session_type;
Dave Wallace048b1d62018-01-03 22:24:41 -05002879 *buflen = sizeof (int);
2880
Florin Coras0d427d82018-06-27 03:24:07 -07002881 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_PROTOCOL: %d (%s), buflen %d",
2882 getpid (), *(int *) buffer, *(int *) buffer ? "UDP" : "TCP",
2883 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002884 }
2885 else
2886 rv = VPPCOM_EINVAL;
2887 break;
2888
2889 case VPPCOM_ATTR_GET_LISTEN:
2890 if (buffer && buflen && (*buflen >= sizeof (int)))
2891 {
2892 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2893 VCL_SESS_ATTR_LISTEN);
2894 *buflen = sizeof (int);
2895
Florin Coras0d427d82018-06-27 03:24:07 -07002896 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LISTEN: %d, buflen %d",
2897 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002898 }
2899 else
2900 rv = VPPCOM_EINVAL;
2901 break;
2902
2903 case VPPCOM_ATTR_GET_ERROR:
2904 if (buffer && buflen && (*buflen >= sizeof (int)))
2905 {
2906 *(int *) buffer = 0;
2907 *buflen = sizeof (int);
2908
Florin Coras0d427d82018-06-27 03:24:07 -07002909 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_ERROR: %d, buflen %d, #VPP-TBD#",
2910 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002911 }
2912 else
2913 rv = VPPCOM_EINVAL;
2914 break;
2915
2916 case VPPCOM_ATTR_GET_TX_FIFO_LEN:
2917 if (buffer && buflen && (*buflen >= sizeof (u32)))
2918 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002919
2920 /* VPP-TBD */
2921 *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002922 session->tx_fifo ? session->tx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05002923 vcm->cfg.tx_fifo_size);
2924 *buflen = sizeof (u32);
2925
Florin Coras0d427d82018-06-27 03:24:07 -07002926 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), "
2927 "buflen %d, #VPP-TBD#", getpid (),
2928 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002929 }
2930 else
2931 rv = VPPCOM_EINVAL;
2932 break;
2933
2934 case VPPCOM_ATTR_SET_TX_FIFO_LEN:
2935 if (buffer && buflen && (*buflen == sizeof (u32)))
2936 {
2937 /* VPP-TBD */
2938 session->sndbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07002939 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), "
2940 "buflen %d, #VPP-TBD#", getpid (),
2941 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002942 }
2943 else
2944 rv = VPPCOM_EINVAL;
2945 break;
2946
2947 case VPPCOM_ATTR_GET_RX_FIFO_LEN:
2948 if (buffer && buflen && (*buflen >= sizeof (u32)))
2949 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002950
2951 /* VPP-TBD */
2952 *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002953 session->rx_fifo ? session->rx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05002954 vcm->cfg.rx_fifo_size);
2955 *buflen = sizeof (u32);
2956
Florin Coras0d427d82018-06-27 03:24:07 -07002957 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_RX_FIFO_LEN: %u (0x%x), "
2958 "buflen %d, #VPP-TBD#", getpid (),
2959 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002960 }
2961 else
2962 rv = VPPCOM_EINVAL;
2963 break;
2964
2965 case VPPCOM_ATTR_SET_RX_FIFO_LEN:
2966 if (buffer && buflen && (*buflen == sizeof (u32)))
2967 {
2968 /* VPP-TBD */
2969 session->rcvbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07002970 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_RX_FIFO_LEN: %u (0x%x), "
2971 "buflen %d, #VPP-TBD#", getpid (),
2972 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002973 }
2974 else
2975 rv = VPPCOM_EINVAL;
2976 break;
2977
2978 case VPPCOM_ATTR_GET_REUSEADDR:
2979 if (buffer && buflen && (*buflen >= sizeof (int)))
2980 {
2981 /* VPP-TBD */
2982 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2983 VCL_SESS_ATTR_REUSEADDR);
2984 *buflen = sizeof (int);
2985
Florin Coras0d427d82018-06-27 03:24:07 -07002986 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEADDR: %d, "
2987 "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002988 }
2989 else
2990 rv = VPPCOM_EINVAL;
2991 break;
2992
Stevenb5a11602017-10-11 09:59:30 -07002993 case VPPCOM_ATTR_SET_REUSEADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002994 if (buffer && buflen && (*buflen == sizeof (int)) &&
2995 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
2996 {
2997 /* VPP-TBD */
2998 if (*(int *) buffer)
2999 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEADDR);
3000 else
3001 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEADDR);
3002
Florin Coras0d427d82018-06-27 03:24:07 -07003003 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEADDR: %d, buflen %d,"
3004 " #VPP-TBD#", getpid (),
3005 VCL_SESS_ATTR_TEST (session->attr,
3006 VCL_SESS_ATTR_REUSEADDR), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003007 }
3008 else
3009 rv = VPPCOM_EINVAL;
3010 break;
3011
3012 case VPPCOM_ATTR_GET_REUSEPORT:
3013 if (buffer && buflen && (*buflen >= sizeof (int)))
3014 {
3015 /* VPP-TBD */
3016 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3017 VCL_SESS_ATTR_REUSEPORT);
3018 *buflen = sizeof (int);
3019
Florin Coras0d427d82018-06-27 03:24:07 -07003020 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEPORT: %d, buflen %d,"
3021 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003022 }
3023 else
3024 rv = VPPCOM_EINVAL;
3025 break;
3026
3027 case VPPCOM_ATTR_SET_REUSEPORT:
3028 if (buffer && buflen && (*buflen == sizeof (int)) &&
3029 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
3030 {
3031 /* VPP-TBD */
3032 if (*(int *) buffer)
3033 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEPORT);
3034 else
3035 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEPORT);
3036
Florin Coras0d427d82018-06-27 03:24:07 -07003037 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEPORT: %d, buflen %d,"
3038 " #VPP-TBD#", getpid (),
3039 VCL_SESS_ATTR_TEST (session->attr,
3040 VCL_SESS_ATTR_REUSEPORT), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003041 }
3042 else
3043 rv = VPPCOM_EINVAL;
3044 break;
3045
3046 case VPPCOM_ATTR_GET_BROADCAST:
3047 if (buffer && buflen && (*buflen >= sizeof (int)))
3048 {
3049 /* VPP-TBD */
3050 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3051 VCL_SESS_ATTR_BROADCAST);
3052 *buflen = sizeof (int);
3053
Florin Coras0d427d82018-06-27 03:24:07 -07003054 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_BROADCAST: %d, buflen %d,"
3055 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003056 }
3057 else
3058 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003059 break;
3060
3061 case VPPCOM_ATTR_SET_BROADCAST:
Dave Wallace048b1d62018-01-03 22:24:41 -05003062 if (buffer && buflen && (*buflen == sizeof (int)))
3063 {
3064 /* VPP-TBD */
3065 if (*(int *) buffer)
3066 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_BROADCAST);
3067 else
3068 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_BROADCAST);
3069
Florin Coras0d427d82018-06-27 03:24:07 -07003070 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_BROADCAST: %d, buflen %d, "
3071 "#VPP-TBD#", getpid (),
3072 VCL_SESS_ATTR_TEST (session->attr,
3073 VCL_SESS_ATTR_BROADCAST), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003074 }
3075 else
3076 rv = VPPCOM_EINVAL;
3077 break;
3078
3079 case VPPCOM_ATTR_GET_V6ONLY:
3080 if (buffer && buflen && (*buflen >= sizeof (int)))
3081 {
3082 /* VPP-TBD */
3083 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3084 VCL_SESS_ATTR_V6ONLY);
3085 *buflen = sizeof (int);
3086
Florin Coras0d427d82018-06-27 03:24:07 -07003087 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_V6ONLY: %d, buflen %d, "
3088 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003089 }
3090 else
3091 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003092 break;
3093
3094 case VPPCOM_ATTR_SET_V6ONLY:
Dave Wallace048b1d62018-01-03 22:24:41 -05003095 if (buffer && buflen && (*buflen == sizeof (int)))
3096 {
3097 /* VPP-TBD */
3098 if (*(int *) buffer)
3099 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_V6ONLY);
3100 else
3101 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_V6ONLY);
3102
Florin Coras0d427d82018-06-27 03:24:07 -07003103 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_V6ONLY: %d, buflen %d, "
3104 "#VPP-TBD#", getpid (),
3105 VCL_SESS_ATTR_TEST (session->attr,
3106 VCL_SESS_ATTR_V6ONLY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003107 }
3108 else
3109 rv = VPPCOM_EINVAL;
3110 break;
3111
3112 case VPPCOM_ATTR_GET_KEEPALIVE:
3113 if (buffer && buflen && (*buflen >= sizeof (int)))
3114 {
3115 /* VPP-TBD */
3116 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3117 VCL_SESS_ATTR_KEEPALIVE);
3118 *buflen = sizeof (int);
3119
Florin Coras0d427d82018-06-27 03:24:07 -07003120 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_KEEPALIVE: %d, buflen %d, "
3121 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003122 }
3123 else
3124 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003125 break;
Stevenbccd3392017-10-12 20:42:21 -07003126
3127 case VPPCOM_ATTR_SET_KEEPALIVE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003128 if (buffer && buflen && (*buflen == sizeof (int)))
3129 {
3130 /* VPP-TBD */
3131 if (*(int *) buffer)
3132 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3133 else
3134 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3135
Florin Coras0d427d82018-06-27 03:24:07 -07003136 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_KEEPALIVE: %d, buflen %d, "
3137 "#VPP-TBD#", getpid (),
3138 VCL_SESS_ATTR_TEST (session->attr,
3139 VCL_SESS_ATTR_KEEPALIVE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003140 }
3141 else
3142 rv = VPPCOM_EINVAL;
3143 break;
3144
3145 case VPPCOM_ATTR_GET_TCP_NODELAY:
3146 if (buffer && buflen && (*buflen >= sizeof (int)))
3147 {
3148 /* VPP-TBD */
3149 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3150 VCL_SESS_ATTR_TCP_NODELAY);
3151 *buflen = sizeof (int);
3152
Florin Coras0d427d82018-06-27 03:24:07 -07003153 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_NODELAY: %d, buflen %d, "
3154 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003155 }
3156 else
3157 rv = VPPCOM_EINVAL;
3158 break;
3159
3160 case VPPCOM_ATTR_SET_TCP_NODELAY:
3161 if (buffer && buflen && (*buflen == sizeof (int)))
3162 {
3163 /* VPP-TBD */
3164 if (*(int *) buffer)
3165 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3166 else
3167 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3168
Florin Coras0d427d82018-06-27 03:24:07 -07003169 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_NODELAY: %d, buflen %d, "
3170 "#VPP-TBD#", getpid (),
3171 VCL_SESS_ATTR_TEST (session->attr,
3172 VCL_SESS_ATTR_TCP_NODELAY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003173 }
3174 else
3175 rv = VPPCOM_EINVAL;
3176 break;
3177
3178 case VPPCOM_ATTR_GET_TCP_KEEPIDLE:
3179 if (buffer && buflen && (*buflen >= sizeof (int)))
3180 {
3181 /* VPP-TBD */
3182 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3183 VCL_SESS_ATTR_TCP_KEEPIDLE);
3184 *buflen = sizeof (int);
3185
Florin Coras0d427d82018-06-27 03:24:07 -07003186 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPIDLE: %d, buflen %d, "
3187 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003188 }
3189 else
3190 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003191 break;
3192
3193 case VPPCOM_ATTR_SET_TCP_KEEPIDLE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003194 if (buffer && buflen && (*buflen == sizeof (int)))
3195 {
3196 /* VPP-TBD */
3197 if (*(int *) buffer)
3198 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3199 else
3200 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3201
Florin Coras0d427d82018-06-27 03:24:07 -07003202 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPIDLE: %d, buflen %d, "
3203 "#VPP-TBD#", getpid (),
3204 VCL_SESS_ATTR_TEST (session->attr,
3205 VCL_SESS_ATTR_TCP_KEEPIDLE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003206 }
3207 else
3208 rv = VPPCOM_EINVAL;
3209 break;
3210
3211 case VPPCOM_ATTR_GET_TCP_KEEPINTVL:
3212 if (buffer && buflen && (*buflen >= sizeof (int)))
3213 {
3214 /* VPP-TBD */
3215 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3216 VCL_SESS_ATTR_TCP_KEEPINTVL);
3217 *buflen = sizeof (int);
3218
Florin Coras0d427d82018-06-27 03:24:07 -07003219 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPINTVL: %d, buflen %d, "
3220 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003221 }
3222 else
3223 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003224 break;
3225
3226 case VPPCOM_ATTR_SET_TCP_KEEPINTVL:
Dave Wallace048b1d62018-01-03 22:24:41 -05003227 if (buffer && buflen && (*buflen == sizeof (int)))
3228 {
3229 /* VPP-TBD */
3230 if (*(int *) buffer)
3231 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3232 else
3233 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3234
Florin Coras0d427d82018-06-27 03:24:07 -07003235 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPINTVL: %d, buflen %d, "
3236 "#VPP-TBD#", getpid (),
3237 VCL_SESS_ATTR_TEST (session->attr,
3238 VCL_SESS_ATTR_TCP_KEEPINTVL), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003239 }
3240 else
3241 rv = VPPCOM_EINVAL;
3242 break;
3243
3244 case VPPCOM_ATTR_GET_TCP_USER_MSS:
3245 if (buffer && buflen && (*buflen >= sizeof (u32)))
3246 {
3247 /* VPP-TBD */
3248 *(u32 *) buffer = session->user_mss;
3249 *buflen = sizeof (int);
3250
Florin Coras0d427d82018-06-27 03:24:07 -07003251 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d,"
3252 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003253 }
3254 else
3255 rv = VPPCOM_EINVAL;
3256 break;
3257
3258 case VPPCOM_ATTR_SET_TCP_USER_MSS:
3259 if (buffer && buflen && (*buflen == sizeof (u32)))
3260 {
3261 /* VPP-TBD */
3262 session->user_mss = *(u32 *) buffer;
3263
Florin Coras0d427d82018-06-27 03:24:07 -07003264 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_USER_MSS: %u, buflen %d, "
3265 "#VPP-TBD#", getpid (), session->user_mss, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003266 }
3267 else
3268 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003269 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003270
Florin Coras47c40e22018-11-26 17:01:36 -08003271 case VPPCOM_ATTR_GET_REFCNT:
3272 rv = vcl_session_get_refcnt (session);
3273 break;
3274
Dave Wallacee22aa742017-10-20 12:30:38 -04003275 default:
3276 rv = VPPCOM_EINVAL;
3277 break;
Dave Wallace35830af2017-10-09 01:43:42 -04003278 }
3279
Dave Wallace35830af2017-10-09 01:43:42 -04003280 return rv;
3281}
3282
Stevenac1f96d2017-10-24 16:03:58 -07003283int
Florin Coras134a9962018-08-28 11:32:04 -07003284vppcom_session_recvfrom (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003285 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3286{
Florin Coras134a9962018-08-28 11:32:04 -07003287 vcl_worker_t *wrk = vcl_worker_get_current ();
Stevenac1f96d2017-10-24 16:03:58 -07003288 int rv = VPPCOM_OK;
Florin Coras7e12d942018-06-27 14:32:43 -07003289 vcl_session_t *session = 0;
Stevenac1f96d2017-10-24 16:03:58 -07003290
3291 if (ep)
3292 {
Florin Coras134a9962018-08-28 11:32:04 -07003293 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07003294 if (PREDICT_FALSE (!session))
Stevenac1f96d2017-10-24 16:03:58 -07003295 {
Florin Coras0d427d82018-06-27 03:24:07 -07003296 VDBG (0, "VCL<%d>: invalid session, sid (%u) has been closed!",
Florin Coras134a9962018-08-28 11:32:04 -07003297 getpid (), session_handle);
Florin Coras460dce62018-07-27 05:45:06 -07003298 return VPPCOM_EBADFD;
Stevenac1f96d2017-10-24 16:03:58 -07003299 }
Florin Coras7e12d942018-06-27 14:32:43 -07003300 ep->is_ip4 = session->transport.is_ip4;
3301 ep->port = session->transport.rmt_port;
Stevenac1f96d2017-10-24 16:03:58 -07003302 }
Steven58f464e2017-10-25 12:33:12 -07003303
3304 if (flags == 0)
Florin Coras134a9962018-08-28 11:32:04 -07003305 rv = vppcom_session_read (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003306 else if (flags & MSG_PEEK)
Florin Coras134a9962018-08-28 11:32:04 -07003307 rv = vppcom_session_peek (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003308 else
3309 {
Dave Wallace048b1d62018-01-03 22:24:41 -05003310 clib_warning ("VCL<%d>: Unsupport flags for recvfrom %d",
3311 getpid (), flags);
Florin Coras460dce62018-07-27 05:45:06 -07003312 return VPPCOM_EAFNOSUPPORT;
Stevenac1f96d2017-10-24 16:03:58 -07003313 }
3314
Florin Coras99368312018-08-02 10:45:44 -07003315 if (ep)
3316 {
3317 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05003318 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
3319 sizeof (ip4_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003320 else
Dave Barach178cf492018-11-13 16:34:13 -05003321 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
3322 sizeof (ip6_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003323 }
Florin Coras460dce62018-07-27 05:45:06 -07003324
Stevenac1f96d2017-10-24 16:03:58 -07003325 return rv;
3326}
3327
3328int
Florin Coras134a9962018-08-28 11:32:04 -07003329vppcom_session_sendto (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003330 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3331{
Dave Wallace617dffa2017-10-26 14:47:06 -04003332 if (!buffer)
3333 return VPPCOM_EINVAL;
3334
3335 if (ep)
3336 {
3337 // TBD
3338 return VPPCOM_EINVAL;
3339 }
3340
3341 if (flags)
3342 {
3343 // TBD check the flags and do the right thing
Florin Coras0d427d82018-06-27 03:24:07 -07003344 VDBG (2, "VCL<%d>: handling flags 0x%u (%d) not implemented yet.",
3345 getpid (), flags, flags);
Dave Wallace617dffa2017-10-26 14:47:06 -04003346 }
3347
Florin Coras134a9962018-08-28 11:32:04 -07003348 return (vppcom_session_write (session_handle, buffer, buflen));
Stevenac1f96d2017-10-24 16:03:58 -07003349}
3350
Dave Wallace048b1d62018-01-03 22:24:41 -05003351int
3352vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time)
3353{
Florin Coras134a9962018-08-28 11:32:04 -07003354 vcl_worker_t *wrk = vcl_worker_get_current ();
3355 f64 timeout = clib_time_now (&wrk->clib_time) + wait_for_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05003356 u32 i, keep_trying = 1;
Florin Coras6917b942018-11-13 22:44:54 -08003357 svm_msg_q_msg_t msg;
3358 session_event_t *e;
Dave Wallace048b1d62018-01-03 22:24:41 -05003359 int rv, num_ev = 0;
3360
Florin Coras0d427d82018-06-27 03:24:07 -07003361 VDBG (3, "VCL<%d>: vp %p, nsids %u, wait_for_time %f",
3362 getpid (), vp, n_sids, wait_for_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05003363
3364 if (!vp)
3365 return VPPCOM_EFAULT;
3366
3367 do
3368 {
Florin Coras7e12d942018-06-27 14:32:43 -07003369 vcl_session_t *session;
Dave Wallace048b1d62018-01-03 22:24:41 -05003370
Florin Coras6917b942018-11-13 22:44:54 -08003371 /* Dequeue all events and drop all unhandled io events */
3372 while (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0) == 0)
3373 {
3374 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
3375 vcl_handle_mq_event (wrk, e);
3376 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
3377 }
3378 vec_reset_length (wrk->unhandled_evts_vector);
3379
Dave Wallace048b1d62018-01-03 22:24:41 -05003380 for (i = 0; i < n_sids; i++)
3381 {
Florin Coras134a9962018-08-28 11:32:04 -07003382 session = vcl_session_get (wrk, vp[i].sid);
Florin Coras070453d2018-08-24 17:04:27 -07003383 if (!session)
Florin Coras6917b942018-11-13 22:44:54 -08003384 {
3385 vp[i].revents = POLLHUP;
3386 num_ev++;
3387 continue;
3388 }
Dave Wallace048b1d62018-01-03 22:24:41 -05003389
Florin Coras6917b942018-11-13 22:44:54 -08003390 vp[i].revents = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003391
3392 if (POLLIN & vp[i].events)
3393 {
Florin Coras54693d22018-07-17 10:46:29 -07003394 rv = vppcom_session_read_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003395 if (rv > 0)
3396 {
Florin Coras6917b942018-11-13 22:44:54 -08003397 vp[i].revents |= POLLIN;
Dave Wallace048b1d62018-01-03 22:24:41 -05003398 num_ev++;
3399 }
3400 else if (rv < 0)
3401 {
3402 switch (rv)
3403 {
3404 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003405 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003406 break;
3407
3408 default:
Florin Coras6917b942018-11-13 22:44:54 -08003409 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003410 break;
3411 }
3412 num_ev++;
3413 }
3414 }
3415
3416 if (POLLOUT & vp[i].events)
3417 {
Florin Coras134a9962018-08-28 11:32:04 -07003418 rv = vppcom_session_write_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003419 if (rv > 0)
3420 {
Florin Coras6917b942018-11-13 22:44:54 -08003421 vp[i].revents |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05003422 num_ev++;
3423 }
3424 else if (rv < 0)
3425 {
3426 switch (rv)
3427 {
3428 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003429 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003430 break;
3431
3432 default:
Florin Coras6917b942018-11-13 22:44:54 -08003433 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003434 break;
3435 }
3436 num_ev++;
3437 }
3438 }
3439
Dave Wallace7e607a72018-06-18 18:41:32 -04003440 if (0) // Note "done:" label used by VCL_SESSION_LOCK_AND_GET()
Dave Wallace048b1d62018-01-03 22:24:41 -05003441 {
Florin Coras6917b942018-11-13 22:44:54 -08003442 vp[i].revents = POLLNVAL;
Dave Wallace048b1d62018-01-03 22:24:41 -05003443 num_ev++;
3444 }
3445 }
3446 if (wait_for_time != -1)
Florin Coras134a9962018-08-28 11:32:04 -07003447 keep_trying = (clib_time_now (&wrk->clib_time) <= timeout) ? 1 : 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003448 }
3449 while ((num_ev == 0) && keep_trying);
3450
3451 if (VPPCOM_DEBUG > 3)
3452 {
3453 clib_warning ("VCL<%d>: returning %d", getpid (), num_ev);
3454 for (i = 0; i < n_sids; i++)
3455 {
3456 clib_warning ("VCL<%d>: vp[%d].sid %d (0x%x), .events 0x%x, "
3457 ".revents 0x%x", getpid (), i, vp[i].sid, vp[i].sid,
Florin Coras6917b942018-11-13 22:44:54 -08003458 vp[i].events, vp[i].revents);
Dave Wallace048b1d62018-01-03 22:24:41 -05003459 }
3460 }
3461 return num_ev;
3462}
3463
Florin Coras99368312018-08-02 10:45:44 -07003464int
3465vppcom_mq_epoll_fd (void)
3466{
Florin Coras134a9962018-08-28 11:32:04 -07003467 vcl_worker_t *wrk = vcl_worker_get_current ();
3468 return wrk->mqs_epfd;
3469}
3470
3471int
3472vppcom_session_index (uint32_t session_handle)
3473{
3474 return session_handle & 0xFFFFFF;
3475}
3476
3477int
Florin Coras30e273b2018-11-27 00:04:59 -08003478vppcom_session_handle (uint32_t session_index)
3479{
Florin Coras47c40e22018-11-26 17:01:36 -08003480 return (vcl_get_worker_index () << 24) | session_index;
Florin Coras30e273b2018-11-27 00:04:59 -08003481}
3482
3483int
Florin Coras134a9962018-08-28 11:32:04 -07003484vppcom_worker_register (void)
3485{
Florin Coras47c40e22018-11-26 17:01:36 -08003486 if (!vcl_worker_alloc_and_init ())
3487 return VPPCOM_EEXIST;
3488
3489 if (vcl_worker_set_bapi ())
3490 return VPPCOM_EEXIST;
3491
3492 if (vcl_worker_register_with_vpp ())
3493 return VPPCOM_EEXIST;
3494
3495 return VPPCOM_OK;
Florin Coras99368312018-08-02 10:45:44 -07003496}
3497
Florin Corasdfe4cf42018-11-28 22:13:45 -08003498int
3499vppcom_worker_index (void)
3500{
3501 return vcl_get_worker_index ();
3502}
3503
Dave Wallacee22aa742017-10-20 12:30:38 -04003504/*
3505 * fd.io coding-style-patch-verification: ON
3506 *
3507 * Local Variables:
3508 * eval: (c-set-style "gnu")
3509 * End:
3510 */