blob: fc7d194bc124f0469bd8acafeaf5a0120e16be1f [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 Corasd85de682018-11-29 17:02:29 -080025static int
26vcl_wait_for_segment (u64 segment_handle)
Florin Coras54693d22018-07-17 10:46:29 -070027{
Florin Corasd85de682018-11-29 17:02:29 -080028 vcl_worker_t *wrk = vcl_worker_get_current ();
29 u32 wait_for_seconds = 10, segment_index;
30 f64 timeout;
Florin Coras54693d22018-07-17 10:46:29 -070031
Florin Corasd85de682018-11-29 17:02:29 -080032 if (segment_handle == VCL_INVALID_SEGMENT_HANDLE)
Florin Coras5f45e012019-01-23 09:21:30 -080033 return 0;
Florin Coras54693d22018-07-17 10:46:29 -070034
Florin Corasd85de682018-11-29 17:02:29 -080035 timeout = clib_time_now (&wrk->clib_time) + wait_for_seconds;
36 while (clib_time_now (&wrk->clib_time) < timeout)
Florin Coras54693d22018-07-17 10:46:29 -070037 {
Florin Corasd85de682018-11-29 17:02:29 -080038 segment_index = vcl_segment_table_lookup (segment_handle);
39 if (segment_index != VCL_INVALID_SEGMENT_INDEX)
40 return 0;
41 usleep (10);
Florin Coras54693d22018-07-17 10:46:29 -070042 }
Florin Corasd85de682018-11-29 17:02:29 -080043 return 1;
Florin Coras54693d22018-07-17 10:46:29 -070044}
45
Florin Coras30e79c22019-01-02 19:31:22 -080046static inline int
47vcl_mq_dequeue_batch (vcl_worker_t * wrk, svm_msg_q_t * mq)
48{
49 svm_msg_q_msg_t *msg;
50 u32 n_msgs;
51 int i;
52
53 n_msgs = svm_msg_q_size (mq);
54 for (i = 0; i < n_msgs; i++)
55 {
56 vec_add2 (wrk->mq_msg_vector, msg, 1);
57 svm_msg_q_sub_w_lock (mq, msg);
58 }
59 return n_msgs;
60}
61
Florin Coras697faea2018-06-27 17:10:49 -070062const char *
Dave Wallace543852a2017-08-03 02:11:34 -040063vppcom_session_state_str (session_state_t state)
64{
65 char *st;
66
67 switch (state)
68 {
69 case STATE_START:
70 st = "STATE_START";
71 break;
72
73 case STATE_CONNECT:
74 st = "STATE_CONNECT";
75 break;
76
77 case STATE_LISTEN:
78 st = "STATE_LISTEN";
79 break;
80
81 case STATE_ACCEPT:
82 st = "STATE_ACCEPT";
83 break;
84
Florin Coras3c7d4f92018-12-14 11:28:43 -080085 case STATE_VPP_CLOSING:
86 st = "STATE_VPP_CLOSING";
Dave Wallace4878cbe2017-11-21 03:45:09 -050087 break;
88
Dave Wallace543852a2017-08-03 02:11:34 -040089 case STATE_DISCONNECT:
90 st = "STATE_DISCONNECT";
91 break;
92
93 case STATE_FAILED:
94 st = "STATE_FAILED";
95 break;
96
97 default:
98 st = "UNKNOWN_STATE";
99 break;
100 }
101
102 return st;
103}
104
Dave Wallace543852a2017-08-03 02:11:34 -0400105u8 *
106format_ip4_address (u8 * s, va_list * args)
107{
108 u8 *a = va_arg (*args, u8 *);
109 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
110}
111
112u8 *
113format_ip6_address (u8 * s, va_list * args)
114{
115 ip6_address_t *a = va_arg (*args, ip6_address_t *);
116 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
117
118 i_max_n_zero = ARRAY_LEN (a->as_u16);
119 max_n_zeros = 0;
120 i_first_zero = i_max_n_zero;
121 n_zeros = 0;
122 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
123 {
124 u32 is_zero = a->as_u16[i] == 0;
125 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
126 {
127 i_first_zero = i;
128 n_zeros = 0;
129 }
130 n_zeros += is_zero;
131 if ((!is_zero && n_zeros > max_n_zeros)
132 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
133 {
134 i_max_n_zero = i_first_zero;
135 max_n_zeros = n_zeros;
136 i_first_zero = ARRAY_LEN (a->as_u16);
137 n_zeros = 0;
138 }
139 }
140
141 last_double_colon = 0;
142 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
143 {
144 if (i == i_max_n_zero && max_n_zeros > 1)
145 {
146 s = format (s, "::");
147 i += max_n_zeros - 1;
148 last_double_colon = 1;
149 }
150 else
151 {
152 s = format (s, "%s%x",
153 (last_double_colon || i == 0) ? "" : ":",
154 clib_net_to_host_u16 (a->as_u16[i]));
155 last_double_colon = 0;
156 }
157 }
158
159 return s;
160}
161
162/* Format an IP46 address. */
163u8 *
164format_ip46_address (u8 * s, va_list * args)
165{
166 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
167 ip46_type_t type = va_arg (*args, ip46_type_t);
168 int is_ip4 = 1;
169
170 switch (type)
171 {
172 case IP46_TYPE_ANY:
173 is_ip4 = ip46_address_is_ip4 (ip46);
174 break;
175 case IP46_TYPE_IP4:
176 is_ip4 = 1;
177 break;
178 case IP46_TYPE_IP6:
179 is_ip4 = 0;
180 break;
181 }
182
183 return is_ip4 ?
184 format (s, "%U", format_ip4_address, &ip46->ip4) :
185 format (s, "%U", format_ip6_address, &ip46->ip6);
186}
187
Florin Coras697faea2018-06-27 17:10:49 -0700188/*
189 * VPPCOM Utility Functions
190 */
191
Florin Coras697faea2018-06-27 17:10:49 -0700192
Florin Coras54693d22018-07-17 10:46:29 -0700193static void
194vcl_send_session_accepted_reply (svm_msg_q_t * mq, u32 context,
195 session_handle_t handle, int retval)
196{
197 app_session_evt_t _app_evt, *app_evt = &_app_evt;
198 session_accepted_reply_msg_t *rmp;
199 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_ACCEPTED_REPLY);
200 rmp = (session_accepted_reply_msg_t *) app_evt->evt->data;
201 rmp->handle = handle;
202 rmp->context = context;
203 rmp->retval = retval;
204 app_send_ctrl_evt_to_vpp (mq, app_evt);
205}
206
Florin Coras99368312018-08-02 10:45:44 -0700207static void
208vcl_send_session_disconnected_reply (svm_msg_q_t * mq, u32 context,
209 session_handle_t handle, int retval)
210{
211 app_session_evt_t _app_evt, *app_evt = &_app_evt;
212 session_disconnected_reply_msg_t *rmp;
213 app_alloc_ctrl_evt_to_vpp (mq, app_evt,
214 SESSION_CTRL_EVT_DISCONNECTED_REPLY);
215 rmp = (session_disconnected_reply_msg_t *) app_evt->evt->data;
216 rmp->handle = handle;
217 rmp->context = context;
218 rmp->retval = retval;
219 app_send_ctrl_evt_to_vpp (mq, app_evt);
220}
221
Florin Corasc9fbd662018-08-24 12:59:56 -0700222static void
223vcl_send_session_reset_reply (svm_msg_q_t * mq, u32 context,
224 session_handle_t handle, int retval)
225{
226 app_session_evt_t _app_evt, *app_evt = &_app_evt;
227 session_reset_reply_msg_t *rmp;
228 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_RESET_REPLY);
229 rmp = (session_reset_reply_msg_t *) app_evt->evt->data;
230 rmp->handle = handle;
231 rmp->context = context;
232 rmp->retval = retval;
233 app_send_ctrl_evt_to_vpp (mq, app_evt);
234}
235
Florin Coras30e79c22019-01-02 19:31:22 -0800236void
237vcl_send_session_worker_update (vcl_worker_t * wrk, vcl_session_t * s,
238 u32 wrk_index)
239{
240 app_session_evt_t _app_evt, *app_evt = &_app_evt;
241 session_worker_update_msg_t *mp;
242 svm_msg_q_t *mq;
243
244 mq = vcl_session_vpp_evt_q (wrk, s);
245 app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_WORKER_UPDATE);
246 mp = (session_worker_update_msg_t *) app_evt->evt->data;
247 mp->client_index = wrk->my_client_index;
248 mp->handle = s->vpp_handle;
249 mp->req_wrk_index = wrk->vpp_wrk_index;
250 mp->wrk_index = wrk_index;
251 app_send_ctrl_evt_to_vpp (mq, app_evt);
252}
253
Florin Coras54693d22018-07-17 10:46:29 -0700254static u32
Florin Coras134a9962018-08-28 11:32:04 -0700255vcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp)
Florin Coras54693d22018-07-17 10:46:29 -0700256{
257 vcl_session_t *session, *listen_session;
258 svm_fifo_t *rx_fifo, *tx_fifo;
Florin Coras134a9962018-08-28 11:32:04 -0700259 u32 vpp_wrk_index;
Florin Coras99368312018-08-02 10:45:44 -0700260 svm_msg_q_t *evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700261
Florin Coras134a9962018-08-28 11:32:04 -0700262 session = vcl_session_alloc (wrk);
Florin Coras99368312018-08-02 10:45:44 -0700263
Florin Coras134a9962018-08-28 11:32:04 -0700264 listen_session = vcl_session_table_lookup_listener (wrk,
265 mp->listener_handle);
Florin Coras54693d22018-07-17 10:46:29 -0700266 if (!listen_session)
267 {
268 svm_msg_q_t *evt_q;
269 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
270 clib_warning ("VCL<%d>: ERROR: couldn't find listen session: "
271 "unknown vpp listener handle %llx",
272 getpid (), mp->listener_handle);
273 vcl_send_session_accepted_reply (evt_q, mp->context, mp->handle,
274 VNET_API_ERROR_INVALID_ARGUMENT);
Florin Coras134a9962018-08-28 11:32:04 -0700275 vcl_session_free (wrk, session);
Florin Coras54693d22018-07-17 10:46:29 -0700276 return VCL_INVALID_SESSION_INDEX;
277 }
278
Florin Coras54693d22018-07-17 10:46:29 -0700279 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
280 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
281
282 if (mp->server_event_queue_address)
283 {
284 session->vpp_evt_q = uword_to_pointer (mp->client_event_queue_address,
285 svm_msg_q_t *);
286 session->our_evt_q = uword_to_pointer (mp->server_event_queue_address,
287 svm_msg_q_t *);
Florin Corasd85de682018-11-29 17:02:29 -0800288 if (vcl_wait_for_segment (mp->segment_handle))
289 {
290 clib_warning ("segment for session %u couldn't be mounted!",
291 session->session_index);
292 return VCL_INVALID_SESSION_INDEX;
293 }
Florin Coras134a9962018-08-28 11:32:04 -0700294 rx_fifo->master_session_index = session->session_index;
295 tx_fifo->master_session_index = session->session_index;
Florin Coras21795132018-09-09 09:40:51 -0700296 rx_fifo->master_thread_index = vcl_get_worker_index ();
297 tx_fifo->master_thread_index = vcl_get_worker_index ();
Florin Coras134a9962018-08-28 11:32:04 -0700298 vec_validate (wrk->vpp_event_queues, 0);
Florin Coras99368312018-08-02 10:45:44 -0700299 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
Florin Coras134a9962018-08-28 11:32:04 -0700300 wrk->vpp_event_queues[0] = evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700301 }
302 else
303 {
304 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
305 svm_msg_q_t *);
Florin Coras134a9962018-08-28 11:32:04 -0700306 rx_fifo->client_session_index = session->session_index;
307 tx_fifo->client_session_index = session->session_index;
Florin Coras21795132018-09-09 09:40:51 -0700308 rx_fifo->client_thread_index = vcl_get_worker_index ();
309 tx_fifo->client_thread_index = vcl_get_worker_index ();
Florin Coras99368312018-08-02 10:45:44 -0700310 vpp_wrk_index = tx_fifo->master_thread_index;
Florin Coras134a9962018-08-28 11:32:04 -0700311 vec_validate (wrk->vpp_event_queues, vpp_wrk_index);
312 wrk->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700313 }
314
315 session->vpp_handle = mp->handle;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800316 session->vpp_thread_index = rx_fifo->master_thread_index;
Florin Coras54693d22018-07-17 10:46:29 -0700317 session->client_context = mp->context;
318 session->rx_fifo = rx_fifo;
319 session->tx_fifo = tx_fifo;
320
321 session->session_state = STATE_ACCEPT;
322 session->transport.rmt_port = mp->port;
323 session->transport.is_ip4 = mp->is_ip4;
Dave Barach178cf492018-11-13 16:34:13 -0500324 clib_memcpy_fast (&session->transport.rmt_ip, mp->ip,
325 sizeof (ip46_address_t));
Florin Coras54693d22018-07-17 10:46:29 -0700326
Florin Coras134a9962018-08-28 11:32:04 -0700327 vcl_session_table_add_vpp_handle (wrk, mp->handle, session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -0700328 session->transport.lcl_port = listen_session->transport.lcl_port;
329 session->transport.lcl_ip = listen_session->transport.lcl_ip;
Florin Coras460dce62018-07-27 05:45:06 -0700330 session->session_type = listen_session->session_type;
331 session->is_dgram = session->session_type == VPPCOM_PROTO_UDP;
Florin Coras54693d22018-07-17 10:46:29 -0700332
333 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: client accept request from %s"
Florin Coras134a9962018-08-28 11:32:04 -0700334 " address %U port %d queue %p!", getpid (), mp->handle,
335 session->session_index,
Florin Coras54693d22018-07-17 10:46:29 -0700336 mp->is_ip4 ? "IPv4" : "IPv6", format_ip46_address, &mp->ip,
337 mp->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
338 clib_net_to_host_u16 (mp->port), session->vpp_evt_q);
339 vcl_evt (VCL_EVT_ACCEPT, session, listen_session, session_index);
340
Florin Coras134a9962018-08-28 11:32:04 -0700341 return session->session_index;
Florin Coras54693d22018-07-17 10:46:29 -0700342}
343
344static u32
Florin Coras134a9962018-08-28 11:32:04 -0700345vcl_session_connected_handler (vcl_worker_t * wrk,
346 session_connected_msg_t * mp)
Florin Coras54693d22018-07-17 10:46:29 -0700347{
Florin Coras99368312018-08-02 10:45:44 -0700348 u32 session_index, vpp_wrk_index;
Florin Coras54693d22018-07-17 10:46:29 -0700349 svm_fifo_t *rx_fifo, *tx_fifo;
Florin Coras99368312018-08-02 10:45:44 -0700350 vcl_session_t *session = 0;
351 svm_msg_q_t *evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700352
353 session_index = mp->context;
Florin Coras134a9962018-08-28 11:32:04 -0700354 session = vcl_session_get (wrk, session_index);
Florin Coras070453d2018-08-24 17:04:27 -0700355 if (!session)
356 {
357 clib_warning ("[%s] ERROR: vpp handle 0x%llx, sid %u: "
358 "Invalid session index (%u)!",
359 getpid (), mp->handle, session_index);
360 return VCL_INVALID_SESSION_INDEX;
361 }
Florin Coras54693d22018-07-17 10:46:29 -0700362 if (mp->retval)
363 {
Florin Coras070453d2018-08-24 17:04:27 -0700364 clib_warning ("VCL<%d>: ERROR: sid %u: connect failed! %U", getpid (),
Florin Coras21795132018-09-09 09:40:51 -0700365 session_index, format_api_error, ntohl (mp->retval));
Florin Coras070453d2018-08-24 17:04:27 -0700366 session->session_state = STATE_FAILED;
367 session->vpp_handle = mp->handle;
368 return session_index;
Florin Coras54693d22018-07-17 10:46:29 -0700369 }
370
Florin Coras460dce62018-07-27 05:45:06 -0700371 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
372 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
Florin Corasd85de682018-11-29 17:02:29 -0800373 if (vcl_wait_for_segment (mp->segment_handle))
374 {
375 clib_warning ("segment for session %u couldn't be mounted!",
376 session->session_index);
377 return VCL_INVALID_SESSION_INDEX;
378 }
379
Florin Coras460dce62018-07-27 05:45:06 -0700380 rx_fifo->client_session_index = session_index;
381 tx_fifo->client_session_index = session_index;
Florin Coras21795132018-09-09 09:40:51 -0700382 rx_fifo->client_thread_index = vcl_get_worker_index ();
383 tx_fifo->client_thread_index = vcl_get_worker_index ();
Florin Coras460dce62018-07-27 05:45:06 -0700384
Florin Coras54693d22018-07-17 10:46:29 -0700385 if (mp->client_event_queue_address)
386 {
387 session->vpp_evt_q = uword_to_pointer (mp->server_event_queue_address,
388 svm_msg_q_t *);
389 session->our_evt_q = uword_to_pointer (mp->client_event_queue_address,
390 svm_msg_q_t *);
Florin Coras99368312018-08-02 10:45:44 -0700391
Florin Coras134a9962018-08-28 11:32:04 -0700392 vec_validate (wrk->vpp_event_queues, 0);
Florin Coras99368312018-08-02 10:45:44 -0700393 evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
Florin Coras134a9962018-08-28 11:32:04 -0700394 wrk->vpp_event_queues[0] = evt_q;
Florin Coras54693d22018-07-17 10:46:29 -0700395 }
396 else
Florin Coras99368312018-08-02 10:45:44 -0700397 {
398 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
399 svm_msg_q_t *);
400 vpp_wrk_index = tx_fifo->master_thread_index;
Florin Coras134a9962018-08-28 11:32:04 -0700401 vec_validate (wrk->vpp_event_queues, vpp_wrk_index);
402 wrk->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
Florin Coras99368312018-08-02 10:45:44 -0700403 }
Florin Coras54693d22018-07-17 10:46:29 -0700404
Florin Coras54693d22018-07-17 10:46:29 -0700405 session->rx_fifo = rx_fifo;
406 session->tx_fifo = tx_fifo;
407 session->vpp_handle = mp->handle;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800408 session->vpp_thread_index = rx_fifo->master_thread_index;
Florin Coras54693d22018-07-17 10:46:29 -0700409 session->transport.is_ip4 = mp->is_ip4;
Dave Barach178cf492018-11-13 16:34:13 -0500410 clib_memcpy_fast (&session->transport.lcl_ip, mp->lcl_ip,
411 sizeof (session->transport.lcl_ip));
Florin Coras54693d22018-07-17 10:46:29 -0700412 session->transport.lcl_port = mp->lcl_port;
413 session->session_state = STATE_CONNECT;
414
415 /* Add it to lookup table */
Florin Coras3c7d4f92018-12-14 11:28:43 -0800416 vcl_session_table_add_vpp_handle (wrk, mp->handle, session_index);
Florin Coras54693d22018-07-17 10:46:29 -0700417
418 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: connect succeeded! "
419 "session_rx_fifo %p, refcnt %d, session_tx_fifo %p, refcnt %d",
420 getpid (), mp->handle, session_index, session->rx_fifo,
421 session->rx_fifo->refcnt, session->tx_fifo, session->tx_fifo->refcnt);
Florin Coras070453d2018-08-24 17:04:27 -0700422
Florin Coras54693d22018-07-17 10:46:29 -0700423 return session_index;
424}
425
Florin Coras3c7d4f92018-12-14 11:28:43 -0800426static int
427vcl_flag_accepted_session (vcl_session_t * session, u64 handle, u32 flags)
428{
429 vcl_session_msg_t *accepted_msg;
430 int i;
431
432 for (i = 0; i < vec_len (session->accept_evts_fifo); i++)
433 {
434 accepted_msg = &session->accept_evts_fifo[i];
435 if (accepted_msg->accepted_msg.handle == handle)
436 {
Florin Corasb0f662f2018-12-27 14:51:46 -0800437 accepted_msg->flags |= flags;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800438 return 1;
439 }
440 }
441 return 0;
442}
443
Florin Corasc9fbd662018-08-24 12:59:56 -0700444static u32
Florin Coras134a9962018-08-28 11:32:04 -0700445vcl_session_reset_handler (vcl_worker_t * wrk,
446 session_reset_msg_t * reset_msg)
Florin Corasc9fbd662018-08-24 12:59:56 -0700447{
448 vcl_session_t *session;
449 u32 sid;
450
Florin Coras134a9962018-08-28 11:32:04 -0700451 sid = vcl_session_index_from_vpp_handle (wrk, reset_msg->handle);
452 session = vcl_session_get (wrk, sid);
Florin Corasc9fbd662018-08-24 12:59:56 -0700453 if (!session)
454 {
455 VDBG (0, "request to reset unknown handle 0x%llx", reset_msg->handle);
456 return VCL_INVALID_SESSION_INDEX;
457 }
Florin Coras3c7d4f92018-12-14 11:28:43 -0800458
459 /* Caught a reset before actually accepting the session */
460 if (session->session_state == STATE_LISTEN)
461 {
462
463 if (!vcl_flag_accepted_session (session, reset_msg->handle,
464 VCL_ACCEPTED_F_RESET))
465 VDBG (0, "session was not accepted!");
466 return VCL_INVALID_SESSION_INDEX;
467 }
468
469 session->session_state = STATE_DISCONNECT;
470 VDBG (0, "reset session %u [0x%llx]", sid, reset_msg->handle);
Florin Corasc9fbd662018-08-24 12:59:56 -0700471 return sid;
472}
473
Florin Coras60116992018-08-27 09:52:18 -0700474static u32
Florin Coras134a9962018-08-28 11:32:04 -0700475vcl_session_bound_handler (vcl_worker_t * wrk, session_bound_msg_t * mp)
Florin Coras60116992018-08-27 09:52:18 -0700476{
477 vcl_session_t *session;
478 u32 sid = mp->context;
479
Florin Coras134a9962018-08-28 11:32:04 -0700480 session = vcl_session_get (wrk, sid);
Florin Coras60116992018-08-27 09:52:18 -0700481 if (mp->retval)
482 {
Florin Corasd85de682018-11-29 17:02:29 -0800483 VERR ("vpp handle 0x%llx, sid %u: bind failed: %U", mp->handle, sid,
484 format_api_error, mp->retval);
Florin Coras60116992018-08-27 09:52:18 -0700485 if (session)
486 {
487 session->session_state = STATE_FAILED;
488 session->vpp_handle = mp->handle;
489 return sid;
490 }
491 else
492 {
493 clib_warning ("[%s] ERROR: vpp handle 0x%llx, sid %u: "
494 "Invalid session index (%u)!",
495 getpid (), mp->handle, sid);
496 return VCL_INVALID_SESSION_INDEX;
497 }
498 }
499
500 session->vpp_handle = mp->handle;
501 session->transport.is_ip4 = mp->lcl_is_ip4;
Dave Barach178cf492018-11-13 16:34:13 -0500502 clib_memcpy_fast (&session->transport.lcl_ip, mp->lcl_ip,
503 sizeof (ip46_address_t));
Florin Coras60116992018-08-27 09:52:18 -0700504 session->transport.lcl_port = mp->lcl_port;
Florin Coras134a9962018-08-28 11:32:04 -0700505 vcl_session_table_add_listener (wrk, mp->handle, sid);
Florin Coras60116992018-08-27 09:52:18 -0700506 session->session_state = STATE_LISTEN;
507
Florin Coras5f45e012019-01-23 09:21:30 -0800508 session->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
509 vec_validate (wrk->vpp_event_queues, 0);
510 wrk->vpp_event_queues[0] = session->vpp_evt_q;
511
Florin Coras60116992018-08-27 09:52:18 -0700512 if (session->is_dgram)
513 {
514 svm_fifo_t *rx_fifo, *tx_fifo;
515 session->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
516 rx_fifo = uword_to_pointer (mp->rx_fifo, svm_fifo_t *);
517 rx_fifo->client_session_index = sid;
518 tx_fifo = uword_to_pointer (mp->tx_fifo, svm_fifo_t *);
519 tx_fifo->client_session_index = sid;
520 session->rx_fifo = rx_fifo;
521 session->tx_fifo = tx_fifo;
522 }
523
Florin Coras05ecfcc2018-12-12 18:19:39 -0800524 VDBG (0, "session %u [0x%llx]: listen succeeded!", sid, mp->handle);
Florin Coras60116992018-08-27 09:52:18 -0700525 return sid;
526}
527
Florin Coras3c7d4f92018-12-14 11:28:43 -0800528static vcl_session_t *
529vcl_session_accepted (vcl_worker_t * wrk, session_accepted_msg_t * msg)
530{
531 vcl_session_msg_t *vcl_msg;
532 vcl_session_t *session;
533
534 session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
535 if (PREDICT_FALSE (session != 0))
Florin Corasb0f662f2018-12-27 14:51:46 -0800536 VWRN ("session overlap handle %lu state %u!", msg->handle,
537 session->session_state);
Florin Coras3c7d4f92018-12-14 11:28:43 -0800538
539 session = vcl_session_table_lookup_listener (wrk, msg->listener_handle);
540 if (!session)
541 {
542 VERR ("couldn't find listen session: listener handle %llx",
543 msg->listener_handle);
544 return 0;
545 }
546
547 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
548 vcl_msg->accepted_msg = *msg;
549 /* Session handle points to listener until fully accepted by app */
550 vcl_session_table_add_vpp_handle (wrk, msg->handle, session->session_index);
551
552 return session;
553}
554
555static vcl_session_t *
556vcl_session_disconnected_handler (vcl_worker_t * wrk,
557 session_disconnected_msg_t * msg)
558{
559 vcl_session_t *session;
560
561 session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
562 if (!session)
563 {
564 VDBG (0, "request to disconnect unknown handle 0x%llx", msg->handle);
565 return 0;
566 }
567
568 /* Caught a disconnect before actually accepting the session */
569 if (session->session_state == STATE_LISTEN)
570 {
Florin Coras3c7d4f92018-12-14 11:28:43 -0800571 if (!vcl_flag_accepted_session (session, msg->handle,
572 VCL_ACCEPTED_F_CLOSED))
573 VDBG (0, "session was not accepted!");
574 return 0;
575 }
576
577 session->session_state = STATE_VPP_CLOSING;
578 return session;
579}
580
Florin Coras30e79c22019-01-02 19:31:22 -0800581static void
582vcl_session_req_worker_update_handler (vcl_worker_t * wrk, void *data)
583{
584 session_req_worker_update_msg_t *msg;
585 vcl_session_t *s;
586
587 msg = (session_req_worker_update_msg_t *) data;
588 s = vcl_session_get_w_vpp_handle (wrk, msg->session_handle);
589 if (!s)
590 return;
591
592 vec_add1 (wrk->pending_session_wrk_updates, s->session_index);
593}
594
595static void
596vcl_session_worker_update_reply_handler (vcl_worker_t * wrk, void *data)
597{
598 session_worker_update_reply_msg_t *msg;
599 vcl_session_t *s;
600
601 msg = (session_worker_update_reply_msg_t *) data;
602 s = vcl_session_get_w_vpp_handle (wrk, msg->handle);
603 if (!s)
604 {
605 VDBG (0, "unknown handle 0x%llx", msg->handle);
606 return;
607 }
608 if (vcl_wait_for_segment (msg->segment_handle))
609 {
610 clib_warning ("segment for session %u couldn't be mounted!",
611 s->session_index);
612 return;
613 }
Florin Coras30e79c22019-01-02 19:31:22 -0800614
Florin Coras5f45e012019-01-23 09:21:30 -0800615 if (s->rx_fifo)
616 {
617 s->rx_fifo = uword_to_pointer (msg->rx_fifo, svm_fifo_t *);
618 s->tx_fifo = uword_to_pointer (msg->tx_fifo, svm_fifo_t *);
619 s->rx_fifo->client_session_index = s->session_index;
620 s->tx_fifo->client_session_index = s->session_index;
621 s->rx_fifo->client_thread_index = wrk->wrk_index;
622 s->tx_fifo->client_thread_index = wrk->wrk_index;
623 }
Florin Coras30e79c22019-01-02 19:31:22 -0800624 s->session_state = STATE_UPDATED;
625
Florin Coras30e79c22019-01-02 19:31:22 -0800626 VDBG (0, "session %u[0x%llx] moved to worker %u", s->session_index,
627 s->vpp_handle, wrk->wrk_index);
628}
629
Florin Coras86f04502018-09-12 16:08:01 -0700630static int
631vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e)
Florin Coras54693d22018-07-17 10:46:29 -0700632{
Florin Coras54693d22018-07-17 10:46:29 -0700633 session_disconnected_msg_t *disconnected_msg;
Florin Coras54693d22018-07-17 10:46:29 -0700634 vcl_session_t *session;
Florin Coras54693d22018-07-17 10:46:29 -0700635
636 switch (e->event_type)
637 {
638 case FIFO_EVENT_APP_RX:
Florin Coras86f04502018-09-12 16:08:01 -0700639 case FIFO_EVENT_APP_TX:
640 case SESSION_IO_EVT_CT_RX:
641 case SESSION_IO_EVT_CT_TX:
642 vec_add1 (wrk->unhandled_evts_vector, *e);
Florin Coras54693d22018-07-17 10:46:29 -0700643 break;
644 case SESSION_CTRL_EVT_ACCEPTED:
Florin Coras3c7d4f92018-12-14 11:28:43 -0800645 vcl_session_accepted (wrk, (session_accepted_msg_t *) e->data);
Florin Coras54693d22018-07-17 10:46:29 -0700646 break;
647 case SESSION_CTRL_EVT_CONNECTED:
Florin Coras134a9962018-08-28 11:32:04 -0700648 vcl_session_connected_handler (wrk,
649 (session_connected_msg_t *) e->data);
Florin Coras54693d22018-07-17 10:46:29 -0700650 break;
651 case SESSION_CTRL_EVT_DISCONNECTED:
652 disconnected_msg = (session_disconnected_msg_t *) e->data;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800653 session = vcl_session_disconnected_handler (wrk, disconnected_msg);
Florin Corasc9fbd662018-08-24 12:59:56 -0700654 if (!session)
Florin Coras3c7d4f92018-12-14 11:28:43 -0800655 break;
Florin Coras54693d22018-07-17 10:46:29 -0700656 session->session_state = STATE_DISCONNECT;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800657 VDBG (0, "disconnected session %u [0x%llx]", session->session_index,
658 session->vpp_handle);
Florin Corasc9fbd662018-08-24 12:59:56 -0700659 break;
660 case SESSION_CTRL_EVT_RESET:
Florin Coras134a9962018-08-28 11:32:04 -0700661 vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
Florin Coras60116992018-08-27 09:52:18 -0700662 break;
663 case SESSION_CTRL_EVT_BOUND:
Florin Coras134a9962018-08-28 11:32:04 -0700664 vcl_session_bound_handler (wrk, (session_bound_msg_t *) e->data);
Florin Coras54693d22018-07-17 10:46:29 -0700665 break;
Florin Coras30e79c22019-01-02 19:31:22 -0800666 case SESSION_CTRL_EVT_REQ_WORKER_UPDATE:
667 vcl_session_req_worker_update_handler (wrk, e->data);
668 break;
669 case SESSION_CTRL_EVT_WORKER_UPDATE_REPLY:
670 vcl_session_worker_update_reply_handler (wrk, e->data);
671 break;
Florin Coras54693d22018-07-17 10:46:29 -0700672 default:
673 clib_warning ("unhandled %u", e->event_type);
674 }
675 return VPPCOM_OK;
676}
677
Florin Coras30e79c22019-01-02 19:31:22 -0800678static int
Florin Coras697faea2018-06-27 17:10:49 -0700679vppcom_wait_for_session_state_change (u32 session_index,
680 session_state_t state,
681 f64 wait_for_time)
682{
Florin Coras134a9962018-08-28 11:32:04 -0700683 vcl_worker_t *wrk = vcl_worker_get_current ();
684 f64 timeout = clib_time_now (&wrk->clib_time) + wait_for_time;
Florin Coras697faea2018-06-27 17:10:49 -0700685 vcl_session_t *volatile session;
Florin Coras54693d22018-07-17 10:46:29 -0700686 svm_msg_q_msg_t msg;
687 session_event_t *e;
Dave Wallace543852a2017-08-03 02:11:34 -0400688
Florin Coras697faea2018-06-27 17:10:49 -0700689 do
Dave Wallace543852a2017-08-03 02:11:34 -0400690 {
Florin Coras134a9962018-08-28 11:32:04 -0700691 session = vcl_session_get (wrk, session_index);
Florin Coras070453d2018-08-24 17:04:27 -0700692 if (PREDICT_FALSE (!session))
Florin Coras697faea2018-06-27 17:10:49 -0700693 {
Florin Coras070453d2018-08-24 17:04:27 -0700694 return VPPCOM_EBADFD;
Florin Coras697faea2018-06-27 17:10:49 -0700695 }
696 if (session->session_state & state)
697 {
Florin Coras697faea2018-06-27 17:10:49 -0700698 return VPPCOM_OK;
699 }
700 if (session->session_state & STATE_FAILED)
701 {
Florin Coras697faea2018-06-27 17:10:49 -0700702 return VPPCOM_ECONNREFUSED;
703 }
Florin Coras54693d22018-07-17 10:46:29 -0700704
Florin Coras134a9962018-08-28 11:32:04 -0700705 if (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0))
Florin Corasdc2e2512018-12-03 17:47:26 -0800706 {
707 usleep (100);
708 continue;
709 }
Florin Coras134a9962018-08-28 11:32:04 -0700710 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
Florin Coras86f04502018-09-12 16:08:01 -0700711 vcl_handle_mq_event (wrk, e);
Florin Coras134a9962018-08-28 11:32:04 -0700712 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Corasdcf55ce2017-11-16 15:32:50 -0800713 }
Florin Coras134a9962018-08-28 11:32:04 -0700714 while (clib_time_now (&wrk->clib_time) < timeout);
Florin Corasdcf55ce2017-11-16 15:32:50 -0800715
Florin Coras05ecfcc2018-12-12 18:19:39 -0800716 VDBG (0, "timeout waiting for state 0x%x (%s)", state,
Florin Coras697faea2018-06-27 17:10:49 -0700717 vppcom_session_state_str (state));
718 vcl_evt (VCL_EVT_SESSION_TIMEOUT, session, session_state);
Dave Wallace543852a2017-08-03 02:11:34 -0400719
Florin Coras697faea2018-06-27 17:10:49 -0700720 return VPPCOM_ETIMEDOUT;
Dave Wallace60caa062017-11-10 17:07:13 -0500721}
722
Florin Coras30e79c22019-01-02 19:31:22 -0800723static void
724vcl_handle_pending_wrk_updates (vcl_worker_t * wrk)
725{
726 session_state_t state;
727 vcl_session_t *s;
728 u32 *sip;
729
730 if (PREDICT_TRUE (vec_len (wrk->pending_session_wrk_updates) == 0))
731 return;
732
733 vec_foreach (sip, wrk->pending_session_wrk_updates)
734 {
735 s = vcl_session_get (wrk, *sip);
736 vcl_send_session_worker_update (wrk, s, wrk->wrk_index);
737 state = s->session_state;
738 vppcom_wait_for_session_state_change (s->session_index, STATE_UPDATED, 5);
739 s->session_state = state;
740 }
741 vec_reset_length (wrk->pending_session_wrk_updates);
742}
743
Florin Corasf9240dc2019-01-15 08:03:17 -0800744void
Florin Coras30e79c22019-01-02 19:31:22 -0800745vcl_flush_mq_events (void)
746{
747 vcl_worker_t *wrk = vcl_worker_get_current ();
748 svm_msg_q_msg_t *msg;
749 session_event_t *e;
750 svm_msg_q_t *mq;
751 int i;
752
753 mq = wrk->app_event_queue;
754 svm_msg_q_lock (mq);
755 vcl_mq_dequeue_batch (wrk, mq);
756 svm_msg_q_unlock (mq);
757
758 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
759 {
760 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
761 e = svm_msg_q_msg_data (mq, msg);
762 vcl_handle_mq_event (wrk, e);
763 svm_msg_q_free_msg (mq, msg);
764 }
765 vec_reset_length (wrk->mq_msg_vector);
766 vcl_handle_pending_wrk_updates (wrk);
767}
768
Florin Coras697faea2018-06-27 17:10:49 -0700769static int
770vppcom_app_session_enable (void)
Dave Wallace543852a2017-08-03 02:11:34 -0400771{
Florin Coras697faea2018-06-27 17:10:49 -0700772 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -0400773
Florin Coras697faea2018-06-27 17:10:49 -0700774 if (vcm->app_state != STATE_APP_ENABLED)
775 {
776 vppcom_send_session_enable_disable (1 /* is_enabled == TRUE */ );
Florin Coras134a9962018-08-28 11:32:04 -0700777 rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
Florin Coras697faea2018-06-27 17:10:49 -0700778 if (PREDICT_FALSE (rv))
779 {
780 VDBG (0, "VCL<%d>: application session enable timed out! "
781 "returning %d (%s)", getpid (), rv, vppcom_retval_str (rv));
782 return rv;
783 }
784 }
785 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400786}
787
Florin Coras697faea2018-06-27 17:10:49 -0700788static int
789vppcom_app_attach (void)
Dave Wallace543852a2017-08-03 02:11:34 -0400790{
Florin Coras697faea2018-06-27 17:10:49 -0700791 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -0400792
Florin Coras697faea2018-06-27 17:10:49 -0700793 vppcom_app_send_attach ();
Florin Coras134a9962018-08-28 11:32:04 -0700794 rv = vcl_wait_for_app_state_change (STATE_APP_ATTACHED);
Florin Coras697faea2018-06-27 17:10:49 -0700795 if (PREDICT_FALSE (rv))
796 {
797 VDBG (0, "VCL<%d>: application attach timed out! returning %d (%s)",
798 getpid (), rv, vppcom_retval_str (rv));
799 return rv;
800 }
Dave Wallace543852a2017-08-03 02:11:34 -0400801
Florin Coras697faea2018-06-27 17:10:49 -0700802 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400803}
804
805static int
Florin Corasab2f6db2018-08-31 14:31:41 -0700806vppcom_session_unbind (u32 session_handle)
Dave Wallace543852a2017-08-03 02:11:34 -0400807{
Florin Coras134a9962018-08-28 11:32:04 -0700808 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -0700809 vcl_session_t *session = 0;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500810 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400811
Florin Corasab2f6db2018-08-31 14:31:41 -0700812 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -0700813 if (!session)
814 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500815
816 vpp_handle = session->vpp_handle;
Florin Coras134a9962018-08-28 11:32:04 -0700817 vcl_session_table_del_listener (wrk, vpp_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500818 session->vpp_handle = ~0;
Florin Coras7e12d942018-06-27 14:32:43 -0700819 session->session_state = STATE_DISCONNECT;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500820
Florin Coras0d427d82018-06-27 03:24:07 -0700821 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending unbind msg! new state"
Florin Corasab2f6db2018-08-31 14:31:41 -0700822 " 0x%x (%s)", getpid (), vpp_handle, session_handle, STATE_DISCONNECT,
Florin Coras0d427d82018-06-27 03:24:07 -0700823 vppcom_session_state_str (STATE_DISCONNECT));
824 vcl_evt (VCL_EVT_UNBIND, session);
Dave Wallace4878cbe2017-11-21 03:45:09 -0500825 vppcom_send_unbind_sock (vpp_handle);
826
Florin Coras070453d2018-08-24 17:04:27 -0700827 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400828}
829
Florin Coras697faea2018-06-27 17:10:49 -0700830static int
Florin Corasab2f6db2018-08-31 14:31:41 -0700831vppcom_session_disconnect (u32 session_handle)
Dave Wallace543852a2017-08-03 02:11:34 -0400832{
Florin Coras134a9962018-08-28 11:32:04 -0700833 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras99368312018-08-02 10:45:44 -0700834 svm_msg_q_t *vpp_evt_q;
Florin Coras7e12d942018-06-27 14:32:43 -0700835 vcl_session_t *session;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500836 session_state_t state;
Florin Coras99368312018-08-02 10:45:44 -0700837 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -0400838
Florin Corasab2f6db2018-08-31 14:31:41 -0700839 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras21795132018-09-09 09:40:51 -0700840 if (!session)
841 return VPPCOM_EBADFD;
842
Dave Wallace4878cbe2017-11-21 03:45:09 -0500843 vpp_handle = session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -0700844 state = session->session_state;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500845
Florin Coras0d427d82018-06-27 03:24:07 -0700846 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u state 0x%x (%s)", getpid (),
Florin Corasab2f6db2018-08-31 14:31:41 -0700847 vpp_handle, session_handle, state, vppcom_session_state_str (state));
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400848
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -0800849 if (PREDICT_FALSE (state & STATE_LISTEN))
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400850 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500851 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -0500852 "Cannot disconnect a listen socket!",
Florin Corasab2f6db2018-08-31 14:31:41 -0700853 getpid (), vpp_handle, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -0700854 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -0500855 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400856
Florin Coras3c7d4f92018-12-14 11:28:43 -0800857 if (state & STATE_VPP_CLOSING)
Dave Wallace4878cbe2017-11-21 03:45:09 -0500858 {
Florin Coras134a9962018-08-28 11:32:04 -0700859 vpp_evt_q = vcl_session_vpp_evt_q (wrk, session);
Florin Coras47c40e22018-11-26 17:01:36 -0800860 vcl_send_session_disconnected_reply (vpp_evt_q, wrk->my_client_index,
Florin Coras99368312018-08-02 10:45:44 -0700861 vpp_handle, 0);
Florin Coras0d427d82018-06-27 03:24:07 -0700862 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect "
Florin Corasab2f6db2018-08-31 14:31:41 -0700863 "REPLY...", getpid (), vpp_handle, session_handle);
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400864 }
865 else
Dave Wallace227867f2017-11-13 21:21:53 -0500866 {
Florin Coras0d427d82018-06-27 03:24:07 -0700867 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect...",
Florin Corasab2f6db2018-08-31 14:31:41 -0700868 getpid (), vpp_handle, session_handle);
869 vppcom_send_disconnect_session (vpp_handle);
Dave Wallace227867f2017-11-13 21:21:53 -0500870 }
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400871
Florin Coras070453d2018-08-24 17:04:27 -0700872 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -0400873}
874
Florin Coras940f78f2018-11-30 12:11:20 -0800875/**
876 * Handle app exit
877 *
878 * Notify vpp of the disconnect and mark the worker as free. If we're the
879 * last worker, do a full cleanup otherwise, since we're probably a forked
880 * child, avoid syscalls as much as possible. We might've lost privileges.
881 */
882void
883vppcom_app_exit (void)
884{
885 if (!pool_elts (vcm->workers))
886 return;
Florin Coras01f3f892018-12-02 12:45:53 -0800887 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
888 vcl_set_worker_index (~0);
Florin Coras940f78f2018-11-30 12:11:20 -0800889 vcl_elog_stop (vcm);
890 if (vec_len (vcm->workers) == 1)
891 vl_client_disconnect_from_vlib ();
892 else
Florin Coraseaec2a62018-12-04 16:34:05 -0800893 vl_client_send_disconnect (1 /* vpp should cleanup */ );
Florin Coras940f78f2018-11-30 12:11:20 -0800894}
895
Dave Wallace543852a2017-08-03 02:11:34 -0400896/*
897 * VPPCOM Public API functions
898 */
899int
900vppcom_app_create (char *app_name)
901{
Dave Wallace543852a2017-08-03 02:11:34 -0400902 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
Dave Wallace543852a2017-08-03 02:11:34 -0400903 int rv;
904
Florin Coras47c40e22018-11-26 17:01:36 -0800905 if (vcm->is_init)
Dave Wallace543852a2017-08-03 02:11:34 -0400906 {
Florin Coras955bfbb2018-12-04 13:43:45 -0800907 VDBG (1, "already initialized");
908 return VPPCOM_EEXIST;
Dave Wallace543852a2017-08-03 02:11:34 -0400909 }
910
Florin Coras47c40e22018-11-26 17:01:36 -0800911 vcm->is_init = 1;
912 vppcom_cfg (&vcm->cfg);
913 vcl_cfg = &vcm->cfg;
914
915 vcm->main_cpu = pthread_self ();
916 vcm->main_pid = getpid ();
917 vcm->app_name = format (0, "%s", app_name);
918 vppcom_init_error_string_table ();
Florin Corasadc74d72018-12-02 13:36:00 -0800919 svm_fifo_segment_main_init (&vcm->segment_main, vcl_cfg->segment_baseva,
Florin Coras47c40e22018-11-26 17:01:36 -0800920 20 /* timeout in secs */ );
921 pool_alloc (vcm->workers, vcl_cfg->max_workers);
922 clib_spinlock_init (&vcm->workers_lock);
Florin Corasd85de682018-11-29 17:02:29 -0800923 clib_rwlock_init (&vcm->segment_table_lock);
Florin Coras940f78f2018-11-30 12:11:20 -0800924 atexit (vppcom_app_exit);
Florin Coras47c40e22018-11-26 17:01:36 -0800925
926 /* Allocate default worker */
927 vcl_worker_alloc_and_init ();
928
929 /* API hookup and connect to VPP */
930 vppcom_api_hookup ();
931 vcl_elog_init (vcm);
932 vcm->app_state = STATE_APP_START;
933 rv = vppcom_connect_to_vpp (app_name);
934 if (rv)
Dave Wallace543852a2017-08-03 02:11:34 -0400935 {
Florin Coras47c40e22018-11-26 17:01:36 -0800936 VERR ("couldn't connect to VPP!");
937 return rv;
Dave Wallace66cf6eb2017-10-26 02:51:07 -0400938 }
Florin Coras47c40e22018-11-26 17:01:36 -0800939 VDBG (0, "sending session enable");
940 rv = vppcom_app_session_enable ();
941 if (rv)
942 {
943 VERR ("vppcom_app_session_enable() failed!");
944 return rv;
945 }
946
947 VDBG (0, "sending app attach");
948 rv = vppcom_app_attach ();
949 if (rv)
950 {
951 VERR ("vppcom_app_attach() failed!");
952 return rv;
953 }
954
955 VDBG (0, "app_name '%s', my_client_index %d (0x%x)", app_name,
956 vcm->workers[0].my_client_index, vcm->workers[0].my_client_index);
Dave Wallace543852a2017-08-03 02:11:34 -0400957
958 return VPPCOM_OK;
959}
960
961void
962vppcom_app_destroy (void)
963{
Dave Wallace543852a2017-08-03 02:11:34 -0400964 int rv;
Dave Wallacede910062018-03-20 09:22:13 -0400965 f64 orig_app_timeout;
Dave Wallace543852a2017-08-03 02:11:34 -0400966
Florin Coras940f78f2018-11-30 12:11:20 -0800967 if (!pool_elts (vcm->workers))
968 return;
969
Florin Coras0d427d82018-06-27 03:24:07 -0700970 vcl_evt (VCL_EVT_DETACH, vcm);
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -0800971
Florin Coras940f78f2018-11-30 12:11:20 -0800972 if (pool_elts (vcm->workers) == 1)
Florin Coras47c40e22018-11-26 17:01:36 -0800973 {
974 vppcom_app_send_detach ();
975 orig_app_timeout = vcm->cfg.app_timeout;
976 vcm->cfg.app_timeout = 2.0;
977 rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
978 vcm->cfg.app_timeout = orig_app_timeout;
979 if (PREDICT_FALSE (rv))
980 VDBG (0, "application detach timed out! returning %d (%s)", rv,
981 vppcom_retval_str (rv));
Florin Coras940f78f2018-11-30 12:11:20 -0800982 vec_free (vcm->app_name);
Florin Coras01f3f892018-12-02 12:45:53 -0800983 vcl_worker_cleanup (vcl_worker_get_current (), 0 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -0800984 }
985 else
986 {
Florin Coras01f3f892018-12-02 12:45:53 -0800987 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -0800988 }
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -0800989
Florin Coras01f3f892018-12-02 12:45:53 -0800990 vcl_set_worker_index (~0);
Florin Coras0d427d82018-06-27 03:24:07 -0700991 vcl_elog_stop (vcm);
Dave Wallace543852a2017-08-03 02:11:34 -0400992 vl_client_disconnect_from_vlib ();
Dave Wallace543852a2017-08-03 02:11:34 -0400993}
994
995int
Dave Wallacec04cbf12018-02-07 18:14:02 -0500996vppcom_session_create (u8 proto, u8 is_nonblocking)
Dave Wallace543852a2017-08-03 02:11:34 -0400997{
Florin Coras134a9962018-08-28 11:32:04 -0700998 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -0700999 vcl_session_t *session;
Dave Wallace543852a2017-08-03 02:11:34 -04001000
Florin Coras134a9962018-08-28 11:32:04 -07001001 session = vcl_session_alloc (wrk);
Dave Wallace543852a2017-08-03 02:11:34 -04001002
Florin Coras7e12d942018-06-27 14:32:43 -07001003 session->session_type = proto;
1004 session->session_state = STATE_START;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001005 session->vpp_handle = ~0;
Florin Coras460dce62018-07-27 05:45:06 -07001006 session->is_dgram = proto == VPPCOM_PROTO_UDP;
Dave Wallace543852a2017-08-03 02:11:34 -04001007
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001008 if (is_nonblocking)
1009 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
Dave Wallace543852a2017-08-03 02:11:34 -04001010
Florin Coras7e12d942018-06-27 14:32:43 -07001011 vcl_evt (VCL_EVT_CREATE, session, session_type, session->session_state,
1012 is_nonblocking, session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001013
Florin Coras053a0e42018-11-13 15:52:38 -08001014 VDBG (0, "created sid %u", session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001015
Florin Coras134a9962018-08-28 11:32:04 -07001016 return vcl_session_handle (session);
Dave Wallace543852a2017-08-03 02:11:34 -04001017}
1018
1019int
Florin Corasf9240dc2019-01-15 08:03:17 -08001020vcl_session_cleanup (vcl_worker_t * wrk, vcl_session_t * session,
1021 vcl_session_handle_t sh, u8 do_disconnect)
Dave Wallace543852a2017-08-03 02:11:34 -04001022{
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001023 session_state_t state;
Florin Coras134a9962018-08-28 11:32:04 -07001024 u32 next_sh, vep_sh;
1025 int rv = VPPCOM_OK;
1026 u64 vpp_handle;
Florin Corasf9240dc2019-01-15 08:03:17 -08001027 u8 is_vep;
Florin Coras47c40e22018-11-26 17:01:36 -08001028
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001029 is_vep = session->is_vep;
Florin Coras134a9962018-08-28 11:32:04 -07001030 next_sh = session->vep.next_sh;
1031 vep_sh = session->vep.vep_sh;
Florin Coras7e12d942018-06-27 14:32:43 -07001032 state = session->session_state;
Dave Wallaceee45d412017-11-24 21:44:06 -05001033 vpp_handle = session->vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -04001034
Florin Corasf9240dc2019-01-15 08:03:17 -08001035 VDBG (1, "session %u [0x%llx] closing", session->session_index, vpp_handle);
Dave Wallace543852a2017-08-03 02:11:34 -04001036
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001037 if (is_vep)
Dave Wallace543852a2017-08-03 02:11:34 -04001038 {
Florin Coras134a9962018-08-28 11:32:04 -07001039 while (next_sh != ~0)
Dave Wallace19481612017-09-15 18:47:44 -04001040 {
Florin Corasf9240dc2019-01-15 08:03:17 -08001041 rv = vppcom_epoll_ctl (sh, EPOLL_CTL_DEL, next_sh, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001042 if (PREDICT_FALSE (rv < 0))
Florin Coras47c40e22018-11-26 17:01:36 -08001043 VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u"
1044 " failed! rv %d (%s)", vpp_handle, next_sh, vep_sh, rv,
1045 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001046
Florin Coras134a9962018-08-28 11:32:04 -07001047 next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001048 }
1049 }
1050 else
1051 {
Florin Coras47c40e22018-11-26 17:01:36 -08001052 if (session->is_vep_session)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001053 {
Florin Corasf9240dc2019-01-15 08:03:17 -08001054 rv = vppcom_epoll_ctl (vep_sh, EPOLL_CTL_DEL, sh, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001055 if (rv < 0)
Florin Corasf9240dc2019-01-15 08:03:17 -08001056 VDBG (0, "session %u [0x%llx]: EPOLL_CTL_DEL vep_idx %u "
1057 "failed! rv %d (%s)", session->session_index, vpp_handle,
1058 vep_sh, rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001059 }
1060
Florin Coras47c40e22018-11-26 17:01:36 -08001061 if (!do_disconnect)
Florin Coras30e79c22019-01-02 19:31:22 -08001062 {
Florin Coras0ef8ef22019-01-18 08:37:13 -08001063 VDBG (1, "session %u [0x%llx] disconnect skipped",
Florin Corasf9240dc2019-01-15 08:03:17 -08001064 session->session_index, vpp_handle);
Florin Coras30e79c22019-01-02 19:31:22 -08001065 goto cleanup;
1066 }
Florin Coras47c40e22018-11-26 17:01:36 -08001067
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001068 if (state & STATE_LISTEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001069 {
Florin Corasf9240dc2019-01-15 08:03:17 -08001070 rv = vppcom_session_unbind (sh);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001071 if (PREDICT_FALSE (rv < 0))
Florin Corasf9240dc2019-01-15 08:03:17 -08001072 VDBG (0, "session %u [0x%llx]: listener unbind failed! "
1073 "rv %d (%s)", session->session_index, vpp_handle, rv,
Florin Coras47c40e22018-11-26 17:01:36 -08001074 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001075 }
Florin Coras070453d2018-08-24 17:04:27 -07001076 else if (state & STATE_OPEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001077 {
Florin Corasf9240dc2019-01-15 08:03:17 -08001078 rv = vppcom_session_disconnect (sh);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001079 if (PREDICT_FALSE (rv < 0))
Florin Corasf9240dc2019-01-15 08:03:17 -08001080 VDBG (0, "ERROR: session %u [0x%llx]: disconnect failed!"
1081 " rv %d (%s)", session->session_index, vpp_handle,
1082 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001083 }
Florin Corasb0f662f2018-12-27 14:51:46 -08001084 else if (state == STATE_DISCONNECT)
1085 {
1086 svm_msg_q_t *mq = vcl_session_vpp_evt_q (wrk, session);
1087 vcl_send_session_reset_reply (mq, wrk->my_client_index,
1088 session->vpp_handle, 0);
1089 }
Dave Wallace19481612017-09-15 18:47:44 -04001090 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001091
Florin Coras99368312018-08-02 10:45:44 -07001092 if (vcl_session_is_ct (session))
1093 {
1094 vcl_cut_through_registration_t *ctr;
1095 uword mq_addr;
1096
1097 mq_addr = pointer_to_uword (session->our_evt_q);
Florin Coras134a9962018-08-28 11:32:04 -07001098 ctr = vcl_ct_registration_lock_and_lookup (wrk, mq_addr);
Florin Coras99368312018-08-02 10:45:44 -07001099 ASSERT (ctr);
1100 if (ctr->epoll_evt_conn_index != ~0)
Florin Coras134a9962018-08-28 11:32:04 -07001101 vcl_mq_epoll_del_evfd (wrk, ctr->epoll_evt_conn_index);
Florin Coras99368312018-08-02 10:45:44 -07001102 VDBG (0, "Removing ct registration %u",
Florin Coras134a9962018-08-28 11:32:04 -07001103 vcl_ct_registration_index (wrk, ctr));
1104 vcl_ct_registration_del (wrk, ctr);
1105 vcl_ct_registration_lookup_del (wrk, mq_addr);
1106 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07001107 }
Florin Coras54693d22018-07-17 10:46:29 -07001108
Florin Coras0ef8ef22019-01-18 08:37:13 -08001109 VDBG (0, "session %u [0x%llx] removed", session->session_index, vpp_handle);
1110
Florin Corasf9240dc2019-01-15 08:03:17 -08001111cleanup:
Florin Coras30e79c22019-01-02 19:31:22 -08001112 vcl_session_table_del_vpp_handle (wrk, vpp_handle);
Florin Coras134a9962018-08-28 11:32:04 -07001113 vcl_session_free (wrk, session);
Florin Coras0d427d82018-06-27 03:24:07 -07001114 vcl_evt (VCL_EVT_CLOSE, session, rv);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001115
Dave Wallace543852a2017-08-03 02:11:34 -04001116 return rv;
1117}
1118
1119int
Florin Corasf9240dc2019-01-15 08:03:17 -08001120vppcom_session_close (uint32_t session_handle)
1121{
1122 vcl_worker_t *wrk = vcl_worker_get_current ();
1123 vcl_session_t *session;
1124
1125 session = vcl_session_get_w_handle (wrk, session_handle);
1126 if (!session)
1127 return VPPCOM_EBADFD;
1128 return vcl_session_cleanup (wrk, session, session_handle,
1129 1 /* do_disconnect */ );
1130}
1131
1132int
Florin Coras134a9962018-08-28 11:32:04 -07001133vppcom_session_bind (uint32_t session_handle, vppcom_endpt_t * ep)
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 *session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001137
1138 if (!ep || !ep->ip)
1139 return VPPCOM_EINVAL;
1140
Florin Coras134a9962018-08-28 11:32:04 -07001141 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001142 if (!session)
1143 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001144
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001145 if (session->is_vep)
1146 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001147 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
Florin Coras134a9962018-08-28 11:32:04 -07001148 "bind to an epoll session!", getpid (), session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001149 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001150 }
1151
Florin Coras7e12d942018-06-27 14:32:43 -07001152 session->transport.is_ip4 = ep->is_ip4;
Florin Coras54693d22018-07-17 10:46:29 -07001153 if (ep->is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001154 clib_memcpy_fast (&session->transport.lcl_ip.ip4, ep->ip,
1155 sizeof (ip4_address_t));
Florin Coras54693d22018-07-17 10:46:29 -07001156 else
Dave Barach178cf492018-11-13 16:34:13 -05001157 clib_memcpy_fast (&session->transport.lcl_ip.ip6, ep->ip,
1158 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001159 session->transport.lcl_port = ep->port;
Stevenac1f96d2017-10-24 16:03:58 -07001160
Florin Coras0d427d82018-06-27 03:24:07 -07001161 VDBG (0, "VCL<%d>: sid %u: binding to local %s address %U port %u, "
Florin Coras134a9962018-08-28 11:32:04 -07001162 "proto %s", getpid (), session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001163 session->transport.is_ip4 ? "IPv4" : "IPv6",
1164 format_ip46_address, &session->transport.lcl_ip,
1165 session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
1166 clib_net_to_host_u16 (session->transport.lcl_port),
Ping Yu34a3a082018-11-30 19:16:17 -05001167 vppcom_proto_str (session->session_type));
Florin Coras0d427d82018-06-27 03:24:07 -07001168 vcl_evt (VCL_EVT_BIND, session);
Florin Coras460dce62018-07-27 05:45:06 -07001169
1170 if (session->session_type == VPPCOM_PROTO_UDP)
Florin Coras134a9962018-08-28 11:32:04 -07001171 vppcom_session_listen (session_handle, 10);
Florin Coras460dce62018-07-27 05:45:06 -07001172
Florin Coras070453d2018-08-24 17:04:27 -07001173 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001174}
1175
1176int
Florin Coras134a9962018-08-28 11:32:04 -07001177vppcom_session_listen (uint32_t listen_sh, uint32_t q_len)
Dave Wallace543852a2017-08-03 02:11:34 -04001178{
Florin Coras134a9962018-08-28 11:32:04 -07001179 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001180 vcl_session_t *listen_session = 0;
Dave Wallaceee45d412017-11-24 21:44:06 -05001181 u64 listen_vpp_handle;
Florin Coras070453d2018-08-24 17:04:27 -07001182 int rv;
1183
Florin Coras134a9962018-08-28 11:32:04 -07001184 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001185 if (!listen_session || listen_session->is_vep)
Florin Coras070453d2018-08-24 17:04:27 -07001186 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001187
Keith Burns (alagalah)aba98de2018-02-22 03:23:40 -08001188 if (q_len == 0 || q_len == ~0)
1189 q_len = vcm->cfg.listen_queue_size;
1190
Dave Wallaceee45d412017-11-24 21:44:06 -05001191 listen_vpp_handle = listen_session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -07001192 if (listen_session->session_state & STATE_LISTEN)
Dave Wallacee695cb42017-11-02 22:04:42 -04001193 {
Florin Coras05ecfcc2018-12-12 18:19:39 -08001194 VDBG (0, "session %u [0x%llx]: already in listen state!",
1195 listen_sh, listen_vpp_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001196 return VPPCOM_OK;
Dave Wallacee695cb42017-11-02 22:04:42 -04001197 }
1198
Florin Coras05ecfcc2018-12-12 18:19:39 -08001199 VDBG (0, "session %u [0x%llx]: sending vpp listen request...",
1200 listen_sh, listen_vpp_handle);
Dave Wallace543852a2017-08-03 02:11:34 -04001201
Florin Coras070453d2018-08-24 17:04:27 -07001202 /*
1203 * Send listen request to vpp and wait for reply
1204 */
Florin Coras134a9962018-08-28 11:32:04 -07001205 vppcom_send_bind_sock (listen_session);
1206 rv = vppcom_wait_for_session_state_change (listen_session->session_index,
1207 STATE_LISTEN,
1208 vcm->cfg.session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001209
Florin Coras070453d2018-08-24 17:04:27 -07001210 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001211 {
Florin Coras134a9962018-08-28 11:32:04 -07001212 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001213 VDBG (0, "session %u [0x%llx]: listen failed! returning %d (%s)",
1214 listen_sh, listen_session->vpp_handle, rv,
1215 vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001216 return rv;
Dave Wallaceee45d412017-11-24 21:44:06 -05001217 }
1218
Florin Coras070453d2018-08-24 17:04:27 -07001219 return VPPCOM_OK;
Keith Burns (alagalah)0d2b0d52018-03-06 15:55:22 -08001220}
1221
Ping Yu34a3a082018-11-30 19:16:17 -05001222int
1223vppcom_session_tls_add_cert (uint32_t session_handle, char *cert,
1224 uint32_t cert_len)
1225{
1226
1227 vcl_worker_t *wrk = vcl_worker_get_current ();
1228 vcl_session_t *session = 0;
1229
1230 session = vcl_session_get_w_handle (wrk, session_handle);
1231 if (!session)
1232 return VPPCOM_EBADFD;
1233
1234 if (cert_len == 0 || cert_len == ~0)
1235 return VPPCOM_EBADFD;
1236
1237 /*
1238 * Send listen request to vpp and wait for reply
1239 */
1240 vppcom_send_application_tls_cert_add (session, cert, cert_len);
1241
1242 return VPPCOM_OK;
1243
1244}
1245
1246int
1247vppcom_session_tls_add_key (uint32_t session_handle, char *key,
1248 uint32_t key_len)
1249{
1250
1251 vcl_worker_t *wrk = vcl_worker_get_current ();
1252 vcl_session_t *session = 0;
1253
1254 session = vcl_session_get_w_handle (wrk, session_handle);
1255 if (!session)
1256 return VPPCOM_EBADFD;
1257
1258 if (key_len == 0 || key_len == ~0)
1259 return VPPCOM_EBADFD;
1260
1261 /*
1262 * Send listen request to vpp and wait for reply
1263 */
1264 vppcom_send_application_tls_key_add (session, key, key_len);
1265
1266 return VPPCOM_OK;
1267
1268
1269}
1270
Florin Coras134a9962018-08-28 11:32:04 -07001271static int
1272validate_args_session_accept_ (vcl_worker_t * wrk,
1273 vcl_session_t * listen_session)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001274{
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001275 /* Input validation - expects spinlock on sessions_lockp */
1276 if (listen_session->is_vep)
1277 {
1278 clib_warning ("VCL<%d>: ERROR: sid %u: cannot accept on an "
Florin Coras134a9962018-08-28 11:32:04 -07001279 "epoll session!", getpid (),
1280 listen_session->session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001281 return VPPCOM_EBADFD;
1282 }
1283
Florin Coras7e12d942018-06-27 14:32:43 -07001284 if (listen_session->session_state != STATE_LISTEN)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001285 {
1286 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
1287 "not in listen state! state 0x%x (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001288 listen_session->vpp_handle, listen_session->session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001289 listen_session->session_state,
1290 vppcom_session_state_str (listen_session->session_state));
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001291 return VPPCOM_EBADFD;
1292 }
1293 return VPPCOM_OK;
1294}
1295
1296int
Florin Coras134a9962018-08-28 11:32:04 -07001297vppcom_session_accept (uint32_t listen_session_handle, vppcom_endpt_t * ep,
Dave Wallace048b1d62018-01-03 22:24:41 -05001298 uint32_t flags)
Dave Wallace543852a2017-08-03 02:11:34 -04001299{
Florin Coras3c7d4f92018-12-14 11:28:43 -08001300 u32 client_session_index = ~0, listen_session_index, accept_flags = 0;
Florin Coras134a9962018-08-28 11:32:04 -07001301 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001302 session_accepted_msg_t accepted_msg;
Florin Coras7e12d942018-06-27 14:32:43 -07001303 vcl_session_t *listen_session = 0;
1304 vcl_session_t *client_session = 0;
Florin Coras54693d22018-07-17 10:46:29 -07001305 svm_msg_q_t *vpp_evt_q;
1306 vcl_session_msg_t *evt;
Dave Wallaceee45d412017-11-24 21:44:06 -05001307 u64 listen_vpp_handle;
Florin Coras54693d22018-07-17 10:46:29 -07001308 svm_msg_q_msg_t msg;
1309 session_event_t *e;
1310 u8 is_nonblocking;
1311 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001312
Florin Coras134a9962018-08-28 11:32:04 -07001313 listen_session = vcl_session_get_w_handle (wrk, listen_session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001314 if (!listen_session)
1315 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001316
Florin Coras134a9962018-08-28 11:32:04 -07001317 listen_session_index = listen_session->session_index;
1318 if ((rv = validate_args_session_accept_ (wrk, listen_session)))
Florin Coras070453d2018-08-24 17:04:27 -07001319 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001320
Florin Coras54693d22018-07-17 10:46:29 -07001321 if (clib_fifo_elts (listen_session->accept_evts_fifo))
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001322 {
Florin Coras54693d22018-07-17 10:46:29 -07001323 clib_fifo_sub2 (listen_session->accept_evts_fifo, evt);
Florin Coras3c7d4f92018-12-14 11:28:43 -08001324 accept_flags = evt->flags;
Florin Coras54693d22018-07-17 10:46:29 -07001325 accepted_msg = evt->accepted_msg;
1326 goto handle;
1327 }
1328
1329 is_nonblocking = VCL_SESS_ATTR_TEST (listen_session->attr,
1330 VCL_SESS_ATTR_NONBLOCK);
Florin Coras134a9962018-08-28 11:32:04 -07001331 if (svm_msg_q_is_empty (wrk->app_event_queue) && is_nonblocking)
Florin Coras54693d22018-07-17 10:46:29 -07001332 return VPPCOM_EAGAIN;
1333
1334 while (1)
1335 {
Florin Coras134a9962018-08-28 11:32:04 -07001336 if (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_WAIT, 0))
Florin Coras54693d22018-07-17 10:46:29 -07001337 return VPPCOM_EAGAIN;
1338
Florin Coras134a9962018-08-28 11:32:04 -07001339 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001340 if (e->event_type != SESSION_CTRL_EVT_ACCEPTED)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001341 {
Florin Coras54693d22018-07-17 10:46:29 -07001342 clib_warning ("discarded event: %u", e->event_type);
Florin Coras134a9962018-08-28 11:32:04 -07001343 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001344 continue;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001345 }
Dave Barach178cf492018-11-13 16:34:13 -05001346 clib_memcpy_fast (&accepted_msg, e->data, sizeof (accepted_msg));
Florin Coras134a9962018-08-28 11:32:04 -07001347 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001348 break;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001349 }
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001350
Florin Coras54693d22018-07-17 10:46:29 -07001351handle:
Keith Burns (alagalah)00f44cc2018-03-07 09:26:38 -08001352
Florin Coras134a9962018-08-28 11:32:04 -07001353 client_session_index = vcl_session_accepted_handler (wrk, &accepted_msg);
1354 listen_session = vcl_session_get (wrk, listen_session_index);
1355 client_session = vcl_session_get (wrk, client_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001356
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001357 if (flags & O_NONBLOCK)
1358 VCL_SESS_ATTR_SET (client_session->attr, VCL_SESS_ATTR_NONBLOCK);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001359
Florin Coras54693d22018-07-17 10:46:29 -07001360 listen_vpp_handle = listen_session->vpp_handle;
Florin Coras05ecfcc2018-12-12 18:19:39 -08001361 VDBG (1, "vpp handle 0x%llx, sid %u: Got a client request! "
Florin Coras0d427d82018-06-27 03:24:07 -07001362 "vpp handle 0x%llx, sid %u, flags %d, is_nonblocking %u",
Florin Corasdc2e2512018-12-03 17:47:26 -08001363 listen_vpp_handle, listen_session_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001364 client_session->vpp_handle, client_session_index,
1365 flags, VCL_SESS_ATTR_TEST (client_session->attr,
1366 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace543852a2017-08-03 02:11:34 -04001367
Dave Wallace048b1d62018-01-03 22:24:41 -05001368 if (ep)
1369 {
Florin Coras7e12d942018-06-27 14:32:43 -07001370 ep->is_ip4 = client_session->transport.is_ip4;
1371 ep->port = client_session->transport.rmt_port;
1372 if (client_session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001373 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip4,
1374 sizeof (ip4_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001375 else
Dave Barach178cf492018-11-13 16:34:13 -05001376 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip6,
1377 sizeof (ip6_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001378 }
Dave Wallace60caa062017-11-10 17:07:13 -05001379
Florin Coras54693d22018-07-17 10:46:29 -07001380 if (accepted_msg.server_event_queue_address)
1381 vpp_evt_q = uword_to_pointer (accepted_msg.vpp_event_queue_address,
1382 svm_msg_q_t *);
1383 else
1384 vpp_evt_q = client_session->vpp_evt_q;
Florin Coras99368312018-08-02 10:45:44 -07001385
Florin Coras54693d22018-07-17 10:46:29 -07001386 vcl_send_session_accepted_reply (vpp_evt_q, client_session->client_context,
1387 client_session->vpp_handle, 0);
Dave Wallace60caa062017-11-10 17:07:13 -05001388
Florin Coras05ecfcc2018-12-12 18:19:39 -08001389 VDBG (0, "listener %u [0x%llx] accepted %u [0x%llx] peer: %U:%u "
1390 "local: %U:%u", listen_session_handle, listen_vpp_handle,
1391 client_session_index, client_session->vpp_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001392 format_ip46_address, &client_session->transport.rmt_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001393 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001394 clib_net_to_host_u16 (client_session->transport.rmt_port),
Florin Coras7e12d942018-06-27 14:32:43 -07001395 format_ip46_address, &client_session->transport.lcl_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001396 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001397 clib_net_to_host_u16 (client_session->transport.lcl_port));
Florin Coras0d427d82018-06-27 03:24:07 -07001398 vcl_evt (VCL_EVT_ACCEPT, client_session, listen_session,
1399 client_session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001400
Florin Coras3c7d4f92018-12-14 11:28:43 -08001401 /*
1402 * Session might have been closed already
1403 */
1404 if (accept_flags)
1405 {
Florin Coras3c7d4f92018-12-14 11:28:43 -08001406 if (accept_flags & VCL_ACCEPTED_F_CLOSED)
Florin Corasb0f662f2018-12-27 14:51:46 -08001407 client_session->session_state = STATE_VPP_CLOSING;
Florin Coras3c7d4f92018-12-14 11:28:43 -08001408 else if (accept_flags & VCL_ACCEPTED_F_RESET)
Florin Corasb0f662f2018-12-27 14:51:46 -08001409 client_session->session_state = STATE_DISCONNECT;
Florin Coras3c7d4f92018-12-14 11:28:43 -08001410 }
Florin Corasab2f6db2018-08-31 14:31:41 -07001411 return vcl_session_handle (client_session);
Dave Wallace543852a2017-08-03 02:11:34 -04001412}
1413
1414int
Florin Coras134a9962018-08-28 11:32:04 -07001415vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep)
Dave Wallace543852a2017-08-03 02:11:34 -04001416{
Florin Coras134a9962018-08-28 11:32:04 -07001417 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001418 vcl_session_t *session = 0;
Florin Coras134a9962018-08-28 11:32:04 -07001419 u32 session_index;
Florin Coras070453d2018-08-24 17:04:27 -07001420 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001421
Florin Coras134a9962018-08-28 11:32:04 -07001422 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001423 if (!session)
1424 return VPPCOM_EBADFD;
Florin Coras134a9962018-08-28 11:32:04 -07001425 session_index = session->session_index;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001426
1427 if (PREDICT_FALSE (session->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001428 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001429 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
Florin Coras134a9962018-08-28 11:32:04 -07001430 "connect on an epoll session!", getpid (),
1431 session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001432 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001433 }
1434
Florin Coras7e12d942018-06-27 14:32:43 -07001435 if (PREDICT_FALSE (session->session_state & CLIENT_STATE_OPEN))
Dave Wallace543852a2017-08-03 02:11:34 -04001436 {
Florin Coras7baeb712019-01-04 17:05:43 -08001437 VDBG (0, "session handle %u [0x%llx]: session already "
Florin Coras0d427d82018-06-27 03:24:07 -07001438 "connected to %s %U port %d proto %s, state 0x%x (%s)",
Florin Coras7baeb712019-01-04 17:05:43 -08001439 session_handle, session->vpp_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001440 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001441 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001442 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001443 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001444 clib_net_to_host_u16 (session->transport.rmt_port),
Ping Yu34a3a082018-11-30 19:16:17 -05001445 vppcom_proto_str (session->session_type), session->session_state,
Florin Coras7e12d942018-06-27 14:32:43 -07001446 vppcom_session_state_str (session->session_state));
Florin Coras070453d2018-08-24 17:04:27 -07001447 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001448 }
1449
Florin Coras7e12d942018-06-27 14:32:43 -07001450 session->transport.is_ip4 = server_ep->is_ip4;
1451 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001452 clib_memcpy_fast (&session->transport.rmt_ip.ip4, server_ep->ip,
1453 sizeof (ip4_address_t));
Dave Wallaced239f8d2018-06-19 13:37:30 -04001454 else
Dave Barach178cf492018-11-13 16:34:13 -05001455 clib_memcpy_fast (&session->transport.rmt_ip.ip6, server_ep->ip,
1456 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001457 session->transport.rmt_port = server_ep->port;
Dave Wallace543852a2017-08-03 02:11:34 -04001458
Florin Coras7baeb712019-01-04 17:05:43 -08001459 VDBG (0, "session handle %u [0x%llx]: connecting to server %s %U "
1460 "port %d proto %s", session_handle, session->vpp_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001461 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001462 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001463 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001464 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001465 clib_net_to_host_u16 (session->transport.rmt_port),
Ping Yu34a3a082018-11-30 19:16:17 -05001466 vppcom_proto_str (session->session_type));
Dave Wallace543852a2017-08-03 02:11:34 -04001467
Florin Coras070453d2018-08-24 17:04:27 -07001468 /*
1469 * Send connect request and wait for reply from vpp
1470 */
Florin Coras134a9962018-08-28 11:32:04 -07001471 vppcom_send_connect_sock (session);
Florin Coras070453d2018-08-24 17:04:27 -07001472 rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
1473 vcm->cfg.session_timeout);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001474
Florin Coras134a9962018-08-28 11:32:04 -07001475 session = vcl_session_get (wrk, session_index);
Dave Wallace7876d392017-10-19 03:53:57 -04001476
Florin Coras070453d2018-08-24 17:04:27 -07001477 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001478 {
Dave Wallaceee45d412017-11-24 21:44:06 -05001479 if (VPPCOM_DEBUG > 0)
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001480 {
1481 if (session)
Florin Coras0d427d82018-06-27 03:24:07 -07001482 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connect "
Florin Coras134a9962018-08-28 11:32:04 -07001483 "failed! returning %d (%s)", getpid (),
1484 session->vpp_handle, session_handle, rv,
1485 vppcom_retval_str (rv));
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001486 else
1487 clib_warning ("VCL<%d>: no session for sid %u: connect failed! "
1488 "returning %d (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001489 session_handle, rv, vppcom_retval_str (rv));
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001490 }
Dave Wallaceee45d412017-11-24 21:44:06 -05001491 }
Florin Coras0d427d82018-06-27 03:24:07 -07001492 else
1493 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connected!",
Florin Coras134a9962018-08-28 11:32:04 -07001494 getpid (), session->vpp_handle, session_handle);
Dave Wallaceee45d412017-11-24 21:44:06 -05001495
Dave Wallace4878cbe2017-11-21 03:45:09 -05001496 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001497}
1498
Florin Coras54693d22018-07-17 10:46:29 -07001499static u8
1500vcl_is_rx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1501{
1502 if (!is_ct)
1503 return (e->event_type == FIFO_EVENT_APP_RX
1504 && e->fifo->client_session_index == sid);
1505 else
1506 return (e->event_type == SESSION_IO_EVT_CT_TX);
1507}
1508
Florin Coras460dce62018-07-27 05:45:06 -07001509static inline u8
1510vcl_session_is_readable (vcl_session_t * s)
1511{
1512 return ((s->session_state & STATE_OPEN)
1513 || (s->session_state == STATE_LISTEN
1514 && s->session_type == VPPCOM_PROTO_UDP));
1515}
1516
Steven58f464e2017-10-25 12:33:12 -07001517static inline int
Florin Coras134a9962018-08-28 11:32:04 -07001518vppcom_session_read_internal (uint32_t session_handle, void *buf, int n,
Steven58f464e2017-10-25 12:33:12 -07001519 u8 peek)
Dave Wallace543852a2017-08-03 02:11:34 -04001520{
Florin Coras134a9962018-08-28 11:32:04 -07001521 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001522 int n_read = 0, rv, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001523 vcl_session_t *s = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001524 svm_fifo_t *rx_fifo;
Florin Coras54693d22018-07-17 10:46:29 -07001525 svm_msg_q_msg_t msg;
1526 session_event_t *e;
1527 svm_msg_q_t *mq;
Florin Coras41c9e042018-09-11 00:10:41 -07001528 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001529
Florin Coras070453d2018-08-24 17:04:27 -07001530 if (PREDICT_FALSE (!buf))
1531 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001532
Florin Coras134a9962018-08-28 11:32:04 -07001533 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras2cba8532018-09-11 16:33:36 -07001534 if (PREDICT_FALSE (!s || s->is_vep))
Florin Coras070453d2018-08-24 17:04:27 -07001535 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001536
Florin Coras460dce62018-07-27 05:45:06 -07001537 if (PREDICT_FALSE (!vcl_session_is_readable (s)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001538 {
Florin Coras460dce62018-07-27 05:45:06 -07001539 session_state_t state = s->session_state;
Keith Burns (alagalah)56a0d062018-02-15 07:52:50 -08001540 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001541
Florin Corasb0f662f2018-12-27 14:51:46 -08001542 VDBG (0, "session handle %u[0x%llx] is not open! state 0x%x (%s),"
1543 " returning %d (%s)", session_handle, s->vpp_handle, state,
Florin Coras0d427d82018-06-27 03:24:07 -07001544 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001545 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001546 }
1547
Florin Coras2cba8532018-09-11 16:33:36 -07001548 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
Florin Coras41c9e042018-09-11 00:10:41 -07001549 is_ct = vcl_session_is_ct (s);
1550 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
Florin Coras2cba8532018-09-11 16:33:36 -07001551 rx_fifo = s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001552 s->has_rx_evt = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001553
Florin Coras54693d22018-07-17 10:46:29 -07001554 if (svm_fifo_is_empty (rx_fifo))
Dave Wallacef7f809c2017-10-03 01:48:42 -04001555 {
Florin Coras54693d22018-07-17 10:46:29 -07001556 if (is_nonblocking)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001557 {
Florin Coras41c9e042018-09-11 00:10:41 -07001558 svm_fifo_unset_event (rx_fifo);
Florin Corasaa27eb92018-10-13 12:20:01 -07001559 return VPPCOM_EWOULDBLOCK;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001560 }
Florin Coras41c9e042018-09-11 00:10:41 -07001561 while (svm_fifo_is_empty (rx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001562 {
Florin Coras41c9e042018-09-11 00:10:41 -07001563 svm_fifo_unset_event (rx_fifo);
Florin Coras99368312018-08-02 10:45:44 -07001564 svm_msg_q_lock (mq);
Florin Coras54693d22018-07-17 10:46:29 -07001565 if (svm_msg_q_is_empty (mq))
1566 svm_msg_q_wait (mq);
Florin Coras99368312018-08-02 10:45:44 -07001567
Florin Coras54693d22018-07-17 10:46:29 -07001568 svm_msg_q_sub_w_lock (mq, &msg);
1569 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001570 svm_msg_q_unlock (mq);
Florin Coras41c9e042018-09-11 00:10:41 -07001571 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
Florin Coras05ce4b82018-12-15 18:30:43 -08001572 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001573 svm_msg_q_free_msg (mq, &msg);
Florin Coras41c9e042018-09-11 00:10:41 -07001574
Florin Coras05ce4b82018-12-15 18:30:43 -08001575 if (PREDICT_FALSE (s->session_state == STATE_DISCONNECT))
1576 return VPPCOM_ECONNRESET;
Florin Coras54693d22018-07-17 10:46:29 -07001577 }
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001578 }
Florin Coras54693d22018-07-17 10:46:29 -07001579
Florin Coras460dce62018-07-27 05:45:06 -07001580 if (s->is_dgram)
Florin Coras99368312018-08-02 10:45:44 -07001581 n_read = app_recv_dgram_raw (rx_fifo, buf, n, &s->transport, 0, peek);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001582 else
Florin Coras99368312018-08-02 10:45:44 -07001583 n_read = app_recv_stream_raw (rx_fifo, buf, n, 0, peek);
Florin Coras54693d22018-07-17 10:46:29 -07001584
Florin Coras41c9e042018-09-11 00:10:41 -07001585 if (svm_fifo_is_empty (rx_fifo))
1586 svm_fifo_unset_event (rx_fifo);
1587
Florin Coras1bcad5c2019-01-09 20:04:38 -08001588 if (is_ct && svm_fifo_needs_tx_ntf (rx_fifo, n_read))
Florin Coras99368312018-08-02 10:45:44 -07001589 {
Florin Coras1bcad5c2019-01-09 20:04:38 -08001590 svm_fifo_clear_tx_ntf (s->rx_fifo);
Florin Coras58c101a2018-10-06 13:49:16 -07001591 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo, SESSION_IO_EVT_CT_RX,
1592 SVM_Q_WAIT);
Florin Coras99368312018-08-02 10:45:44 -07001593 }
Florin Coras54693d22018-07-17 10:46:29 -07001594
Florin Corasa7a1a222018-12-30 17:11:31 -08001595 VDBG (2, "vpp handle 0x%llx, sid %u: read %d bytes from (%p)",
1596 s->vpp_handle, session_handle, n_read, rx_fifo);
Florin Coras2cba8532018-09-11 16:33:36 -07001597
Florin Coras54693d22018-07-17 10:46:29 -07001598 return n_read;
Dave Wallace543852a2017-08-03 02:11:34 -04001599}
1600
Steven58f464e2017-10-25 12:33:12 -07001601int
Florin Coras134a9962018-08-28 11:32:04 -07001602vppcom_session_read (uint32_t session_handle, void *buf, size_t n)
Steven58f464e2017-10-25 12:33:12 -07001603{
Florin Coras134a9962018-08-28 11:32:04 -07001604 return (vppcom_session_read_internal (session_handle, buf, n, 0));
Steven58f464e2017-10-25 12:33:12 -07001605}
1606
1607static int
Florin Coras134a9962018-08-28 11:32:04 -07001608vppcom_session_peek (uint32_t session_handle, void *buf, int n)
Steven58f464e2017-10-25 12:33:12 -07001609{
Florin Coras134a9962018-08-28 11:32:04 -07001610 return (vppcom_session_read_internal (session_handle, buf, n, 1));
Steven58f464e2017-10-25 12:33:12 -07001611}
1612
Florin Coras2cba8532018-09-11 16:33:36 -07001613int
1614vppcom_session_read_segments (uint32_t session_handle,
1615 vppcom_data_segments_t ds)
1616{
1617 vcl_worker_t *wrk = vcl_worker_get_current ();
1618 int n_read = 0, rv, is_nonblocking;
1619 vcl_session_t *s = 0;
1620 svm_fifo_t *rx_fifo;
1621 svm_msg_q_msg_t msg;
1622 session_event_t *e;
1623 svm_msg_q_t *mq;
1624 u8 is_ct;
1625
1626 s = vcl_session_get_w_handle (wrk, session_handle);
1627 if (PREDICT_FALSE (!s || s->is_vep))
1628 return VPPCOM_EBADFD;
1629
1630 if (PREDICT_FALSE (!vcl_session_is_readable (s)))
1631 {
1632 session_state_t state = s->session_state;
1633 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1634 return rv;
1635 }
1636
1637 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1638 is_ct = vcl_session_is_ct (s);
1639 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
1640 rx_fifo = s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001641 s->has_rx_evt = 0;
Florin Coras2cba8532018-09-11 16:33:36 -07001642
1643 if (svm_fifo_is_empty (rx_fifo))
1644 {
1645 if (is_nonblocking)
1646 {
1647 svm_fifo_unset_event (rx_fifo);
Florin Corasaa27eb92018-10-13 12:20:01 -07001648 return VPPCOM_EWOULDBLOCK;
Florin Coras2cba8532018-09-11 16:33:36 -07001649 }
1650 while (svm_fifo_is_empty (rx_fifo))
1651 {
1652 svm_fifo_unset_event (rx_fifo);
1653 svm_msg_q_lock (mq);
1654 if (svm_msg_q_is_empty (mq))
1655 svm_msg_q_wait (mq);
1656
1657 svm_msg_q_sub_w_lock (mq, &msg);
1658 e = svm_msg_q_msg_data (mq, &msg);
1659 svm_msg_q_unlock (mq);
1660 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
Florin Coras05ce4b82018-12-15 18:30:43 -08001661 vcl_handle_mq_event (wrk, e);
Florin Coras2cba8532018-09-11 16:33:36 -07001662 svm_msg_q_free_msg (mq, &msg);
1663
Florin Coras05ce4b82018-12-15 18:30:43 -08001664 if (PREDICT_FALSE (s->session_state == STATE_DISCONNECT))
1665 return VPPCOM_ECONNRESET;
Florin Coras2cba8532018-09-11 16:33:36 -07001666 }
1667 }
1668
1669 n_read = svm_fifo_segments (rx_fifo, (svm_fifo_segment_t *) ds);
1670 svm_fifo_unset_event (rx_fifo);
1671
1672 if (is_ct && n_read + svm_fifo_max_dequeue (rx_fifo) == rx_fifo->nitems)
1673 {
1674 /* If the peer is not polling send notification */
1675 if (!svm_fifo_has_event (s->rx_fifo))
1676 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo,
1677 SESSION_IO_EVT_CT_RX, SVM_Q_WAIT);
1678 }
1679
1680 return n_read;
1681}
1682
1683void
1684vppcom_session_free_segments (uint32_t session_handle,
1685 vppcom_data_segments_t ds)
1686{
1687 vcl_worker_t *wrk = vcl_worker_get_current ();
1688 vcl_session_t *s;
1689
1690 s = vcl_session_get_w_handle (wrk, session_handle);
1691 if (PREDICT_FALSE (!s || s->is_vep))
1692 return;
1693
1694 svm_fifo_segments_free (s->rx_fifo, (svm_fifo_segment_t *) ds);
1695}
1696
Florin Coras2cba8532018-09-11 16:33:36 -07001697int
1698vppcom_data_segment_copy (void *buf, vppcom_data_segments_t ds, u32 max_bytes)
1699{
1700 u32 first_copy = clib_min (ds[0].len, max_bytes);
Dave Barach178cf492018-11-13 16:34:13 -05001701 clib_memcpy_fast (buf, ds[0].data, first_copy);
Florin Coras2cba8532018-09-11 16:33:36 -07001702 if (first_copy < max_bytes)
1703 {
Dave Barach178cf492018-11-13 16:34:13 -05001704 clib_memcpy_fast (buf + first_copy, ds[1].data,
1705 clib_min (ds[1].len, max_bytes - first_copy));
Florin Coras2cba8532018-09-11 16:33:36 -07001706 }
1707 return 0;
1708}
1709
Florin Coras54693d22018-07-17 10:46:29 -07001710static u8
1711vcl_is_tx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1712{
1713 if (!is_ct)
1714 return (e->event_type == FIFO_EVENT_APP_TX
1715 && e->fifo->client_session_index == sid);
Dave Wallace543852a2017-08-03 02:11:34 -04001716 else
Florin Coras54693d22018-07-17 10:46:29 -07001717 return (e->event_type == SESSION_IO_EVT_CT_RX);
Dave Wallace543852a2017-08-03 02:11:34 -04001718}
1719
Florin Coras42ceddb2018-12-12 10:56:01 -08001720static inline int
1721vppcom_session_write_inline (uint32_t session_handle, void *buf, size_t n,
1722 u8 is_flush)
Dave Wallace543852a2017-08-03 02:11:34 -04001723{
Florin Coras134a9962018-08-28 11:32:04 -07001724 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001725 int rv, n_write, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001726 vcl_session_t *s = 0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001727 svm_fifo_t *tx_fifo = 0;
Florin Coras460dce62018-07-27 05:45:06 -07001728 session_evt_type_t et;
Florin Coras54693d22018-07-17 10:46:29 -07001729 svm_msg_q_msg_t msg;
1730 session_event_t *e;
Florin Coras3c2fed52018-07-04 04:15:05 -07001731 svm_msg_q_t *mq;
Florin Coras0e88e852018-09-17 22:09:02 -07001732 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001733
Florin Coras070453d2018-08-24 17:04:27 -07001734 if (PREDICT_FALSE (!buf))
1735 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001736
Florin Coras134a9962018-08-28 11:32:04 -07001737 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001738 if (PREDICT_FALSE (!s))
1739 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001740
Florin Coras460dce62018-07-27 05:45:06 -07001741 if (PREDICT_FALSE (s->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001742 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001743 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001744 "cannot write to an epoll session!",
Florin Coras134a9962018-08-28 11:32:04 -07001745 getpid (), s->vpp_handle, session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001746
Florin Coras070453d2018-08-24 17:04:27 -07001747 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001748 }
1749
Florin Coras0e88e852018-09-17 22:09:02 -07001750 if (PREDICT_FALSE (!(s->session_state & STATE_OPEN)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001751 {
Florin Coras460dce62018-07-27 05:45:06 -07001752 session_state_t state = s->session_state;
Florin Coras54693d22018-07-17 10:46:29 -07001753 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Florin Coras0d427d82018-06-27 03:24:07 -07001754 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open! "
Florin Coras0e88e852018-09-17 22:09:02 -07001755 "state 0x%x (%s)", getpid (), s->vpp_handle, session_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001756 state, vppcom_session_state_str (state));
Florin Coras070453d2018-08-24 17:04:27 -07001757 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001758 }
1759
Florin Coras0e88e852018-09-17 22:09:02 -07001760 tx_fifo = s->tx_fifo;
1761 is_ct = vcl_session_is_ct (s);
1762 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1763 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
Florin Coras54693d22018-07-17 10:46:29 -07001764 if (svm_fifo_is_full (tx_fifo))
Dave Wallace543852a2017-08-03 02:11:34 -04001765 {
Florin Coras54693d22018-07-17 10:46:29 -07001766 if (is_nonblocking)
1767 {
Florin Coras070453d2018-08-24 17:04:27 -07001768 return VPPCOM_EWOULDBLOCK;
Florin Coras54693d22018-07-17 10:46:29 -07001769 }
Florin Coras60f1fc12018-08-16 14:57:31 -07001770 while (svm_fifo_is_full (tx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001771 {
Florin Coras1bcad5c2019-01-09 20:04:38 -08001772 svm_fifo_add_want_tx_ntf (tx_fifo, SVM_FIFO_WANT_TX_NOTIF);
Florin Coras99368312018-08-02 10:45:44 -07001773 svm_msg_q_lock (mq);
Florin Corasaa27eb92018-10-13 12:20:01 -07001774 if (svm_msg_q_is_empty (mq))
1775 svm_msg_q_wait (mq);
Florin Coras0e88e852018-09-17 22:09:02 -07001776
Florin Coras54693d22018-07-17 10:46:29 -07001777 svm_msg_q_sub_w_lock (mq, &msg);
1778 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001779 svm_msg_q_unlock (mq);
1780
Florin Coras0e88e852018-09-17 22:09:02 -07001781 if (!vcl_is_tx_evt_for_session (e, s->session_index, is_ct))
Florin Coras86f04502018-09-12 16:08:01 -07001782 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001783 svm_msg_q_free_msg (mq, &msg);
Florin Coras05ce4b82018-12-15 18:30:43 -08001784
1785 if (PREDICT_FALSE (!(s->session_state & STATE_OPEN)))
1786 return VPPCOM_ECONNRESET;
Florin Coras54693d22018-07-17 10:46:29 -07001787 }
Dave Wallace543852a2017-08-03 02:11:34 -04001788 }
Dave Wallace543852a2017-08-03 02:11:34 -04001789
Florin Coras460dce62018-07-27 05:45:06 -07001790 ASSERT (FIFO_EVENT_APP_TX + 1 == SESSION_IO_EVT_CT_TX);
1791 et = FIFO_EVENT_APP_TX + vcl_session_is_ct (s);
Florin Coras42ceddb2018-12-12 10:56:01 -08001792 if (is_flush && !vcl_session_is_ct (s))
1793 et = SESSION_IO_EVT_TX_FLUSH;
1794
Florin Coras460dce62018-07-27 05:45:06 -07001795 if (s->is_dgram)
1796 n_write = app_send_dgram_raw (tx_fifo, &s->transport,
1797 s->vpp_evt_q, buf, n, et, SVM_Q_WAIT);
1798 else
1799 n_write = app_send_stream_raw (tx_fifo, s->vpp_evt_q, buf, n, et,
1800 SVM_Q_WAIT);
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -07001801
Florin Coras460dce62018-07-27 05:45:06 -07001802 ASSERT (n_write > 0);
Dave Wallace543852a2017-08-03 02:11:34 -04001803
Florin Coras0e88e852018-09-17 22:09:02 -07001804 VDBG (2, "VCL<%d>: vpp handle 0x%llx, sid %u: wrote %d bytes", getpid (),
1805 s->vpp_handle, session_handle, n_write);
1806
Florin Coras54693d22018-07-17 10:46:29 -07001807 return n_write;
Dave Wallace543852a2017-08-03 02:11:34 -04001808}
1809
Florin Coras42ceddb2018-12-12 10:56:01 -08001810int
1811vppcom_session_write (uint32_t session_handle, void *buf, size_t n)
1812{
1813 return vppcom_session_write_inline (session_handle, buf, n,
1814 0 /* is_flush */ );
1815}
1816
Florin Corasb0f662f2018-12-27 14:51:46 -08001817int
1818vppcom_session_write_msg (uint32_t session_handle, void *buf, size_t n)
1819{
1820 return vppcom_session_write_inline (session_handle, buf, n,
1821 1 /* is_flush */ );
1822}
1823
1824
Florin Coras99368312018-08-02 10:45:44 -07001825static vcl_session_t *
Florin Coras134a9962018-08-28 11:32:04 -07001826vcl_ct_session_get_from_fifo (vcl_worker_t * wrk, svm_fifo_t * f, u8 type)
Florin Coras99368312018-08-02 10:45:44 -07001827{
1828 vcl_session_t *s;
Florin Coras134a9962018-08-28 11:32:04 -07001829 s = vcl_session_get (wrk, f->client_session_index);
Florin Coras99368312018-08-02 10:45:44 -07001830 if (s)
1831 {
1832 /* rx fifo */
1833 if (type == 0 && s->rx_fifo == f)
1834 return s;
1835 /* tx fifo */
1836 if (type == 1 && s->tx_fifo == f)
1837 return s;
1838 }
Florin Coras134a9962018-08-28 11:32:04 -07001839 s = vcl_session_get (wrk, f->master_session_index);
Florin Coras99368312018-08-02 10:45:44 -07001840 if (s)
1841 {
1842 if (type == 0 && s->rx_fifo == f)
1843 return s;
1844 if (type == 1 && s->tx_fifo == f)
1845 return s;
1846 }
1847 return 0;
1848}
1849
Florin Coras6d4bb422018-09-04 22:07:27 -07001850#define vcl_fifo_rx_evt_valid_or_break(_fifo) \
1851if (PREDICT_FALSE (svm_fifo_is_empty (_fifo))) \
1852 { \
1853 svm_fifo_unset_event (_fifo); \
1854 if (svm_fifo_is_empty (_fifo)) \
Florin Coras41c9e042018-09-11 00:10:41 -07001855 break; \
Florin Coras6d4bb422018-09-04 22:07:27 -07001856 } \
1857
Florin Coras86f04502018-09-12 16:08:01 -07001858static void
1859vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
1860 unsigned long n_bits, unsigned long *read_map,
1861 unsigned long *write_map,
1862 unsigned long *except_map, u32 * bits_set)
Florin Coras54693d22018-07-17 10:46:29 -07001863{
1864 session_disconnected_msg_t *disconnected_msg;
Florin Coras99368312018-08-02 10:45:44 -07001865 session_connected_msg_t *connected_msg;
Florin Coras54693d22018-07-17 10:46:29 -07001866 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07001867 u32 sid;
1868
1869 switch (e->event_type)
1870 {
1871 case FIFO_EVENT_APP_RX:
1872 vcl_fifo_rx_evt_valid_or_break (e->fifo);
1873 sid = e->fifo->client_session_index;
1874 session = vcl_session_get (wrk, sid);
1875 if (!session)
1876 break;
1877 if (sid < n_bits && read_map)
1878 {
David Johnsond9818dd2018-12-14 14:53:41 -05001879 clib_bitmap_set_no_check ((uword *) read_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07001880 *bits_set += 1;
1881 }
1882 break;
1883 case FIFO_EVENT_APP_TX:
1884 sid = e->fifo->client_session_index;
1885 session = vcl_session_get (wrk, sid);
1886 if (!session)
1887 break;
1888 if (sid < n_bits && write_map)
1889 {
David Johnsond9818dd2018-12-14 14:53:41 -05001890 clib_bitmap_set_no_check ((uword *) write_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07001891 *bits_set += 1;
1892 }
1893 break;
1894 case SESSION_IO_EVT_CT_TX:
1895 vcl_fifo_rx_evt_valid_or_break (e->fifo);
1896 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0);
1897 if (!session)
1898 break;
1899 sid = session->session_index;
1900 if (sid < n_bits && read_map)
1901 {
David Johnsond9818dd2018-12-14 14:53:41 -05001902 clib_bitmap_set_no_check ((uword *) read_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07001903 *bits_set += 1;
1904 }
1905 break;
1906 case SESSION_IO_EVT_CT_RX:
1907 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1);
1908 if (!session)
1909 break;
1910 sid = session->session_index;
1911 if (sid < n_bits && write_map)
1912 {
David Johnsond9818dd2018-12-14 14:53:41 -05001913 clib_bitmap_set_no_check ((uword *) write_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07001914 *bits_set += 1;
1915 }
1916 break;
1917 case SESSION_CTRL_EVT_ACCEPTED:
Florin Coras3c7d4f92018-12-14 11:28:43 -08001918 session = vcl_session_accepted (wrk,
1919 (session_accepted_msg_t *) e->data);
Florin Coras86f04502018-09-12 16:08:01 -07001920 if (!session)
Florin Coras3c7d4f92018-12-14 11:28:43 -08001921 break;
Florin Coras86f04502018-09-12 16:08:01 -07001922 sid = session->session_index;
1923 if (sid < n_bits && read_map)
1924 {
David Johnsond9818dd2018-12-14 14:53:41 -05001925 clib_bitmap_set_no_check ((uword *) read_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07001926 *bits_set += 1;
1927 }
1928 break;
1929 case SESSION_CTRL_EVT_CONNECTED:
1930 connected_msg = (session_connected_msg_t *) e->data;
1931 vcl_session_connected_handler (wrk, connected_msg);
1932 break;
1933 case SESSION_CTRL_EVT_DISCONNECTED:
1934 disconnected_msg = (session_disconnected_msg_t *) e->data;
Florin Coras3c7d4f92018-12-14 11:28:43 -08001935 session = vcl_session_disconnected_handler (wrk, disconnected_msg);
1936 if (!session)
1937 break;
1938 sid = session->session_index;
Florin Coras86f04502018-09-12 16:08:01 -07001939 if (sid < n_bits && except_map)
1940 {
David Johnsond9818dd2018-12-14 14:53:41 -05001941 clib_bitmap_set_no_check ((uword *) except_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07001942 *bits_set += 1;
1943 }
1944 break;
1945 case SESSION_CTRL_EVT_RESET:
1946 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
1947 if (sid < n_bits && except_map)
1948 {
David Johnsond9818dd2018-12-14 14:53:41 -05001949 clib_bitmap_set_no_check ((uword *) except_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07001950 *bits_set += 1;
1951 }
1952 break;
Florin Coras30e79c22019-01-02 19:31:22 -08001953 case SESSION_CTRL_EVT_WORKER_UPDATE_REPLY:
1954 vcl_session_worker_update_reply_handler (wrk, e->data);
1955 break;
1956 case SESSION_CTRL_EVT_REQ_WORKER_UPDATE:
1957 vcl_session_req_worker_update_handler (wrk, e->data);
1958 break;
Florin Coras86f04502018-09-12 16:08:01 -07001959 default:
1960 clib_warning ("unhandled: %u", e->event_type);
1961 break;
1962 }
1963}
1964
1965static int
1966vcl_select_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
1967 unsigned long n_bits, unsigned long *read_map,
1968 unsigned long *write_map, unsigned long *except_map,
1969 double time_to_wait, u32 * bits_set)
1970{
Florin Coras99368312018-08-02 10:45:44 -07001971 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07001972 session_event_t *e;
Florin Coras86f04502018-09-12 16:08:01 -07001973 u32 i;
Florin Coras54693d22018-07-17 10:46:29 -07001974
1975 svm_msg_q_lock (mq);
1976 if (svm_msg_q_is_empty (mq))
Dave Wallace4878cbe2017-11-21 03:45:09 -05001977 {
Florin Coras54693d22018-07-17 10:46:29 -07001978 if (*bits_set)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001979 {
Florin Coras54693d22018-07-17 10:46:29 -07001980 svm_msg_q_unlock (mq);
1981 return 0;
1982 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001983
Florin Coras54693d22018-07-17 10:46:29 -07001984 if (!time_to_wait)
1985 {
1986 svm_msg_q_unlock (mq);
1987 return 0;
1988 }
1989 else if (time_to_wait < 0)
1990 {
1991 svm_msg_q_wait (mq);
1992 }
1993 else
1994 {
1995 if (svm_msg_q_timedwait (mq, time_to_wait))
1996 {
1997 svm_msg_q_unlock (mq);
1998 return 0;
1999 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002000 }
2001 }
Florin Coras134a9962018-08-28 11:32:04 -07002002 vcl_mq_dequeue_batch (wrk, mq);
Florin Coras54693d22018-07-17 10:46:29 -07002003 svm_msg_q_unlock (mq);
2004
Florin Coras134a9962018-08-28 11:32:04 -07002005 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07002006 {
Florin Coras134a9962018-08-28 11:32:04 -07002007 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07002008 e = svm_msg_q_msg_data (mq, msg);
Florin Coras86f04502018-09-12 16:08:01 -07002009 vcl_select_handle_mq_event (wrk, e, n_bits, read_map, write_map,
2010 except_map, bits_set);
Florin Coras99368312018-08-02 10:45:44 -07002011 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002012 }
Florin Coras134a9962018-08-28 11:32:04 -07002013 vec_reset_length (wrk->mq_msg_vector);
Florin Coras30e79c22019-01-02 19:31:22 -08002014 vcl_handle_pending_wrk_updates (wrk);
Florin Coras54693d22018-07-17 10:46:29 -07002015 return *bits_set;
Dave Wallace543852a2017-08-03 02:11:34 -04002016}
2017
Florin Coras99368312018-08-02 10:45:44 -07002018static int
Florin Coras294afe22019-01-07 17:49:17 -08002019vppcom_select_condvar (vcl_worker_t * wrk, int n_bits,
2020 vcl_si_set * read_map, vcl_si_set * write_map,
2021 vcl_si_set * except_map, double time_to_wait,
Florin Coras134a9962018-08-28 11:32:04 -07002022 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002023{
2024 double total_wait = 0, wait_slice;
2025 vcl_cut_through_registration_t *cr;
2026
Florin Coras294afe22019-01-07 17:49:17 -08002027 time_to_wait = (time_to_wait == -1) ? 1e6 : time_to_wait;
Florin Coras134a9962018-08-28 11:32:04 -07002028 wait_slice = wrk->cut_through_registrations ? 10e-6 : time_to_wait;
Florin Coras99368312018-08-02 10:45:44 -07002029 do
2030 {
Florin Coras134a9962018-08-28 11:32:04 -07002031 vcl_ct_registration_lock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002032 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002033 pool_foreach (cr, wrk->cut_through_registrations, ({
2034 vcl_select_handle_mq (wrk, cr->mq, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002035 0, bits_set);
2036 }));
2037 /* *INDENT-ON* */
Florin Coras134a9962018-08-28 11:32:04 -07002038 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002039
Florin Coras134a9962018-08-28 11:32:04 -07002040 vcl_select_handle_mq (wrk, wrk->app_event_queue, n_bits, read_map,
Florin Coras294afe22019-01-07 17:49:17 -08002041 write_map, except_map, wait_slice, bits_set);
Florin Coras99368312018-08-02 10:45:44 -07002042 total_wait += wait_slice;
2043 if (*bits_set)
2044 return *bits_set;
2045 }
2046 while (total_wait < time_to_wait);
2047
2048 return 0;
2049}
2050
2051static int
Florin Coras294afe22019-01-07 17:49:17 -08002052vppcom_select_eventfd (vcl_worker_t * wrk, int n_bits,
2053 vcl_si_set * read_map, vcl_si_set * write_map,
2054 vcl_si_set * except_map, double time_to_wait,
Florin Coras134a9962018-08-28 11:32:04 -07002055 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002056{
2057 vcl_mq_evt_conn_t *mqc;
2058 int __clib_unused n_read;
2059 int n_mq_evts, i;
2060 u64 buf;
2061
Florin Coras134a9962018-08-28 11:32:04 -07002062 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
2063 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2064 vec_len (wrk->mq_events), time_to_wait);
Florin Coras99368312018-08-02 10:45:44 -07002065 for (i = 0; i < n_mq_evts; i++)
2066 {
Florin Coras134a9962018-08-28 11:32:04 -07002067 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002068 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002069 vcl_select_handle_mq (wrk, mqc->mq, n_bits, read_map, write_map,
Florin Coras99368312018-08-02 10:45:44 -07002070 except_map, 0, bits_set);
2071 }
2072
2073 return (n_mq_evts > 0 ? (int) *bits_set : 0);
2074}
2075
Dave Wallace543852a2017-08-03 02:11:34 -04002076int
Florin Coras294afe22019-01-07 17:49:17 -08002077vppcom_select (int n_bits, vcl_si_set * read_map, vcl_si_set * write_map,
2078 vcl_si_set * except_map, double time_to_wait)
Dave Wallace543852a2017-08-03 02:11:34 -04002079{
Florin Coras54693d22018-07-17 10:46:29 -07002080 u32 sid, minbits = clib_max (n_bits, BITS (uword)), bits_set = 0;
Florin Coras134a9962018-08-28 11:32:04 -07002081 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002082 vcl_session_t *session = 0;
Florin Coras86f04502018-09-12 16:08:01 -07002083 int rv, i;
Dave Wallace543852a2017-08-03 02:11:34 -04002084
Dave Wallace7876d392017-10-19 03:53:57 -04002085 if (n_bits && read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002086 {
Florin Coras134a9962018-08-28 11:32:04 -07002087 clib_bitmap_validate (wrk->rd_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002088 clib_memcpy_fast (wrk->rd_bitmap, read_map,
Florin Coras294afe22019-01-07 17:49:17 -08002089 vec_len (wrk->rd_bitmap) * sizeof (vcl_si_set));
2090 memset (read_map, 0, vec_len (wrk->rd_bitmap) * sizeof (vcl_si_set));
Dave Wallace543852a2017-08-03 02:11:34 -04002091 }
Dave Wallace7876d392017-10-19 03:53:57 -04002092 if (n_bits && write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002093 {
Florin Coras134a9962018-08-28 11:32:04 -07002094 clib_bitmap_validate (wrk->wr_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002095 clib_memcpy_fast (wrk->wr_bitmap, write_map,
Florin Coras294afe22019-01-07 17:49:17 -08002096 vec_len (wrk->wr_bitmap) * sizeof (vcl_si_set));
2097 memset (write_map, 0, vec_len (wrk->wr_bitmap) * sizeof (vcl_si_set));
Dave Wallace543852a2017-08-03 02:11:34 -04002098 }
Dave Wallace7876d392017-10-19 03:53:57 -04002099 if (n_bits && except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002100 {
Florin Coras134a9962018-08-28 11:32:04 -07002101 clib_bitmap_validate (wrk->ex_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002102 clib_memcpy_fast (wrk->ex_bitmap, except_map,
Florin Coras294afe22019-01-07 17:49:17 -08002103 vec_len (wrk->ex_bitmap) * sizeof (vcl_si_set));
2104 memset (except_map, 0, vec_len (wrk->ex_bitmap) * sizeof (vcl_si_set));
Dave Wallace543852a2017-08-03 02:11:34 -04002105 }
2106
Florin Coras54693d22018-07-17 10:46:29 -07002107 if (!n_bits)
2108 return 0;
2109
2110 if (!write_map)
2111 goto check_rd;
2112
2113 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002114 clib_bitmap_foreach (sid, wrk->wr_bitmap, ({
2115 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002116 {
Florin Coras47c40e22018-11-26 17:01:36 -08002117 if (except_map && sid < minbits)
2118 clib_bitmap_set_no_check (except_map, sid, 1);
2119 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002120 }
2121
2122 rv = svm_fifo_is_full (session->tx_fifo);
Florin Coras54693d22018-07-17 10:46:29 -07002123 if (!rv)
2124 {
David Johnsond9818dd2018-12-14 14:53:41 -05002125 clib_bitmap_set_no_check ((uword*)write_map, sid, 1);
Florin Coras54693d22018-07-17 10:46:29 -07002126 bits_set++;
2127 }
Florin Coras294afe22019-01-07 17:49:17 -08002128 else
Florin Coras1bcad5c2019-01-09 20:04:38 -08002129 svm_fifo_add_want_tx_ntf (session->tx_fifo, SVM_FIFO_WANT_TX_NOTIF);
Florin Coras54693d22018-07-17 10:46:29 -07002130 }));
2131
2132check_rd:
2133 if (!read_map)
2134 goto check_mq;
Florin Coras99368312018-08-02 10:45:44 -07002135
Florin Coras134a9962018-08-28 11:32:04 -07002136 clib_bitmap_foreach (sid, wrk->rd_bitmap, ({
2137 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002138 {
Florin Coras47c40e22018-11-26 17:01:36 -08002139 if (except_map && sid < minbits)
2140 clib_bitmap_set_no_check (except_map, sid, 1);
2141 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002142 }
2143
Florin Coras0ef8ef22019-01-18 08:37:13 -08002144 rv = vcl_session_read_ready (session);
Florin Coras54693d22018-07-17 10:46:29 -07002145 if (rv)
2146 {
David Johnsond9818dd2018-12-14 14:53:41 -05002147 clib_bitmap_set_no_check ((uword*)read_map, sid, 1);
Florin Coras54693d22018-07-17 10:46:29 -07002148 bits_set++;
2149 }
2150 }));
2151 /* *INDENT-ON* */
2152
2153check_mq:
Dave Wallace543852a2017-08-03 02:11:34 -04002154
Florin Coras86f04502018-09-12 16:08:01 -07002155 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2156 {
2157 vcl_select_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i], n_bits,
2158 read_map, write_map, except_map, &bits_set);
2159 }
2160 vec_reset_length (wrk->unhandled_evts_vector);
2161
Florin Coras99368312018-08-02 10:45:44 -07002162 if (vcm->cfg.use_mq_eventfd)
Florin Coras134a9962018-08-28 11:32:04 -07002163 vppcom_select_eventfd (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002164 time_to_wait, &bits_set);
2165 else
Florin Coras134a9962018-08-28 11:32:04 -07002166 vppcom_select_condvar (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002167 time_to_wait, &bits_set);
Florin Coras54693d22018-07-17 10:46:29 -07002168
Dave Wallace543852a2017-08-03 02:11:34 -04002169 return (bits_set);
2170}
2171
Dave Wallacef7f809c2017-10-03 01:48:42 -04002172static inline void
Florin Coras134a9962018-08-28 11:32:04 -07002173vep_verify_epoll_chain (vcl_worker_t * wrk, u32 vep_idx)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002174{
Florin Coras7e12d942018-06-27 14:32:43 -07002175 vcl_session_t *session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002176 vppcom_epoll_t *vep;
Dave Wallace498b3a52017-11-09 13:00:34 -05002177 u32 sid = vep_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002178
Dave Wallace498b3a52017-11-09 13:00:34 -05002179 if (VPPCOM_DEBUG <= 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002180 return;
2181
2182 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Florin Coras134a9962018-08-28 11:32:04 -07002183 session = vcl_session_get (wrk, vep_idx);
Florin Coras070453d2018-08-24 17:04:27 -07002184 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002185 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002186 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!",
2187 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002188 goto done;
2189 }
2190 if (PREDICT_FALSE (!session->is_vep))
2191 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002192 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
2193 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002194 goto done;
2195 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002196 vep = &session->vep;
Dave Wallace048b1d62018-01-03 22:24:41 -05002197 clib_warning ("VCL<%d>: vep_idx (%u): Dumping epoll chain\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05002198 "{\n"
2199 " is_vep = %u\n"
2200 " is_vep_session = %u\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05002201 " next_sid = 0x%x (%u)\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05002202 " wait_cont_idx = 0x%x (%u)\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05002203 "}\n", getpid (), vep_idx,
2204 session->is_vep, session->is_vep_session,
Florin Coras134a9962018-08-28 11:32:04 -07002205 vep->next_sh, vep->next_sh,
Dave Wallace498b3a52017-11-09 13:00:34 -05002206 session->wait_cont_idx, session->wait_cont_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002207
Florin Coras134a9962018-08-28 11:32:04 -07002208 for (sid = vep->next_sh; sid != ~0; sid = vep->next_sh)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002209 {
Florin Coras134a9962018-08-28 11:32:04 -07002210 session = vcl_session_get (wrk, sid);
Florin Coras070453d2018-08-24 17:04:27 -07002211 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002212 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002213 clib_warning ("VCL<%d>: ERROR: Invalid sid (%u)!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002214 goto done;
2215 }
2216 if (PREDICT_FALSE (session->is_vep))
Dave Wallace048b1d62018-01-03 22:24:41 -05002217 clib_warning ("VCL<%d>: ERROR: sid (%u) is a vep!",
2218 getpid (), vep_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002219 else if (PREDICT_FALSE (!session->is_vep_session))
2220 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002221 clib_warning ("VCL<%d>: ERROR: session (%u) "
2222 "is not a vep session!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002223 goto done;
2224 }
2225 vep = &session->vep;
Florin Coras134a9962018-08-28 11:32:04 -07002226 if (PREDICT_FALSE (vep->vep_sh != vep_idx))
Dave Wallace048b1d62018-01-03 22:24:41 -05002227 clib_warning ("VCL<%d>: ERROR: session (%u) vep_idx (%u) != "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002228 "vep_idx (%u)!", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002229 sid, session->vep.vep_sh, vep_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002230 if (session->is_vep_session)
2231 {
2232 clib_warning ("vep_idx[%u]: sid 0x%x (%u)\n"
2233 "{\n"
2234 " next_sid = 0x%x (%u)\n"
2235 " prev_sid = 0x%x (%u)\n"
2236 " vep_idx = 0x%x (%u)\n"
2237 " ev.events = 0x%x\n"
2238 " ev.data.u64 = 0x%llx\n"
2239 " et_mask = 0x%x\n"
2240 "}\n",
2241 vep_idx, sid, sid,
Florin Coras134a9962018-08-28 11:32:04 -07002242 vep->next_sh, vep->next_sh,
2243 vep->prev_sh, vep->prev_sh,
2244 vep->vep_sh, vep->vep_sh,
Dave Wallace4878cbe2017-11-21 03:45:09 -05002245 vep->ev.events, vep->ev.data.u64, vep->et_mask);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002246 }
2247 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002248
2249done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002250 clib_warning ("VCL<%d>: vep_idx (%u): Dump complete!\n",
2251 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002252}
2253
2254int
2255vppcom_epoll_create (void)
2256{
Florin Coras134a9962018-08-28 11:32:04 -07002257 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002258 vcl_session_t *vep_session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002259
Florin Coras134a9962018-08-28 11:32:04 -07002260 vep_session = vcl_session_alloc (wrk);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002261
2262 vep_session->is_vep = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002263 vep_session->vep.vep_sh = ~0;
2264 vep_session->vep.next_sh = ~0;
2265 vep_session->vep.prev_sh = ~0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002266 vep_session->wait_cont_idx = ~0;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002267 vep_session->vpp_handle = ~0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002268
Florin Corasa7a1a222018-12-30 17:11:31 -08002269 vcl_evt (VCL_EVT_EPOLL_CREATE, vep_session, vep_session->session_index);
2270 VDBG (0, "Created vep_idx %u", vep_session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08002271
Florin Corasab2f6db2018-08-31 14:31:41 -07002272 return vcl_session_handle (vep_session);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002273}
2274
2275int
Florin Coras134a9962018-08-28 11:32:04 -07002276vppcom_epoll_ctl (uint32_t vep_handle, int op, uint32_t session_handle,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002277 struct epoll_event *event)
2278{
Florin Coras134a9962018-08-28 11:32:04 -07002279 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002280 vcl_session_t *vep_session;
2281 vcl_session_t *session;
Florin Coras070453d2018-08-24 17:04:27 -07002282 int rv = VPPCOM_OK;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002283
Florin Coras134a9962018-08-28 11:32:04 -07002284 if (vep_handle == session_handle)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002285 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002286 VDBG (0, "vep_sh == session handle (%u)!", vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002287 return VPPCOM_EINVAL;
2288 }
2289
Florin Coras134a9962018-08-28 11:32:04 -07002290 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002291 if (PREDICT_FALSE (!vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002292 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002293 VDBG (0, "Invalid vep_sh (%u)!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002294 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002295 }
2296 if (PREDICT_FALSE (!vep_session->is_vep))
2297 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002298 VDBG (0, "vep_sh (%u) is not a vep!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002299 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002300 }
2301
Florin Coras134a9962018-08-28 11:32:04 -07002302 ASSERT (vep_session->vep.vep_sh == ~0);
2303 ASSERT (vep_session->vep.prev_sh == ~0);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002304
Florin Coras134a9962018-08-28 11:32:04 -07002305 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002306 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002307 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002308 VDBG (0, "Invalid session_handle (%u)!", session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002309 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002310 }
2311 if (PREDICT_FALSE (session->is_vep))
2312 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002313 VDBG (0, "session_handle (%u) is a vep!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002314 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002315 }
2316
2317 switch (op)
2318 {
2319 case EPOLL_CTL_ADD:
2320 if (PREDICT_FALSE (!event))
2321 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002322 VDBG (0, "EPOLL_CTL_ADD: NULL pointer to epoll_event structure!");
Florin Coras070453d2018-08-24 17:04:27 -07002323 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002324 }
Florin Coras134a9962018-08-28 11:32:04 -07002325 if (vep_session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002326 {
Florin Coras7e12d942018-06-27 14:32:43 -07002327 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002328 next_session = vcl_session_get_w_handle (wrk,
2329 vep_session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002330 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002331 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002332 VDBG (0, "EPOLL_CTL_ADD: Invalid vep.next_sid (%u) on "
2333 "vep_idx (%u)!", vep_session->vep.next_sh, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002334 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002335 }
Florin Coras134a9962018-08-28 11:32:04 -07002336 ASSERT (next_session->vep.prev_sh == vep_handle);
2337 next_session->vep.prev_sh = session_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002338 }
Florin Coras134a9962018-08-28 11:32:04 -07002339 session->vep.next_sh = vep_session->vep.next_sh;
2340 session->vep.prev_sh = vep_handle;
2341 session->vep.vep_sh = vep_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002342 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2343 session->vep.ev = *event;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002344 session->is_vep = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002345 session->is_vep_session = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002346 vep_session->vep.next_sh = session_handle;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08002347
Florin Coras1bcad5c2019-01-09 20:04:38 -08002348 if (session->tx_fifo)
2349 svm_fifo_add_want_tx_ntf (session->tx_fifo,
2350 SVM_FIFO_WANT_TX_NOTIF_IF_FULL);
2351
Florin Corasa7a1a222018-12-30 17:11:31 -08002352 VDBG (1, "EPOLL_CTL_ADD: vep_sh %u, sh %u, events 0x%x, data 0x%llx!",
2353 vep_handle, session_handle, event->events, event->data.u64);
Florin Coras0d427d82018-06-27 03:24:07 -07002354 vcl_evt (VCL_EVT_EPOLL_CTLADD, session, event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002355 break;
2356
2357 case EPOLL_CTL_MOD:
2358 if (PREDICT_FALSE (!event))
2359 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002360 VDBG (0, "EPOLL_CTL_MOD: NULL pointer to epoll_event structure!");
Dave Wallacef7f809c2017-10-03 01:48:42 -04002361 rv = VPPCOM_EINVAL;
2362 goto done;
2363 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002364 else if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002365 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002366 VDBG (0, "sid %u EPOLL_CTL_MOD: not a vep session!",
2367 session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002368 rv = VPPCOM_EINVAL;
2369 goto done;
2370 }
Florin Coras134a9962018-08-28 11:32:04 -07002371 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002372 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002373 VDBG (0, "EPOLL_CTL_MOD: sh %u vep_sh (%u) != vep_sh (%u)!",
2374 session_handle, session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002375 rv = VPPCOM_EINVAL;
2376 goto done;
2377 }
2378 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2379 session->vep.ev = *event;
Florin Corasa7a1a222018-12-30 17:11:31 -08002380 VDBG (1, "EPOLL_CTL_MOD: vep_sh %u, sh %u, events 0x%x, data 0x%llx!",
2381 vep_handle, session_handle, event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002382 break;
2383
2384 case EPOLL_CTL_DEL:
Dave Wallace4878cbe2017-11-21 03:45:09 -05002385 if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002386 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002387 VDBG (0, "EPOLL_CTL_DEL: %u not a vep session!", session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002388 rv = VPPCOM_EINVAL;
2389 goto done;
2390 }
Florin Coras134a9962018-08-28 11:32:04 -07002391 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002392 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002393 VDBG (0, "EPOLL_CTL_DEL: sh %u vep_sh (%u) != vep_sh (%u)!",
2394 session_handle, session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002395 rv = VPPCOM_EINVAL;
2396 goto done;
2397 }
2398
2399 vep_session->wait_cont_idx =
Florin Coras134a9962018-08-28 11:32:04 -07002400 (vep_session->wait_cont_idx == session_handle) ?
2401 session->vep.next_sh : vep_session->wait_cont_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002402
Florin Coras134a9962018-08-28 11:32:04 -07002403 if (session->vep.prev_sh == vep_handle)
2404 vep_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002405 else
2406 {
Florin Coras7e12d942018-06-27 14:32:43 -07002407 vcl_session_t *prev_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002408 prev_session = vcl_session_get_w_handle (wrk, session->vep.prev_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002409 if (PREDICT_FALSE (!prev_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002410 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002411 VDBG (0, "EPOLL_CTL_DEL: Invalid prev_sid (%u) on sid (%u)!",
2412 session->vep.prev_sh, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002413 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002414 }
Florin Coras134a9962018-08-28 11:32:04 -07002415 ASSERT (prev_session->vep.next_sh == session_handle);
2416 prev_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002417 }
Florin Coras134a9962018-08-28 11:32:04 -07002418 if (session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002419 {
Florin Coras7e12d942018-06-27 14:32:43 -07002420 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002421 next_session = vcl_session_get_w_handle (wrk, session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002422 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002423 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002424 VDBG (0, "EPOLL_CTL_DEL: Invalid next_sid (%u) on sid (%u)!",
2425 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 Coras1bcad5c2019-01-09 20:04:38 -08002437
2438 if (session->tx_fifo)
2439 svm_fifo_del_want_tx_ntf (session->tx_fifo, SVM_FIFO_NO_TX_NOTIF);
2440
Florin Corasa7a1a222018-12-30 17:11:31 -08002441 VDBG (1, "EPOLL_CTL_DEL: vep_idx %u, sid %u!", vep_handle,
2442 session_handle);
Florin Coras134a9962018-08-28 11:32:04 -07002443 vcl_evt (VCL_EVT_EPOLL_CTLDEL, session, vep_sh);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002444 break;
2445
2446 default:
Florin Corasa7a1a222018-12-30 17:11:31 -08002447 VDBG (0, "Invalid operation (%d)!", op);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002448 rv = VPPCOM_EINVAL;
2449 }
2450
Florin Coras134a9962018-08-28 11:32:04 -07002451 vep_verify_epoll_chain (wrk, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002452
2453done:
Dave Wallacef7f809c2017-10-03 01:48:42 -04002454 return rv;
2455}
2456
Florin Coras86f04502018-09-12 16:08:01 -07002457static inline void
2458vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
2459 struct epoll_event *events, u32 * num_ev)
Florin Coras54693d22018-07-17 10:46:29 -07002460{
2461 session_disconnected_msg_t *disconnected_msg;
2462 session_connected_msg_t *connected_msg;
Florin Coras99368312018-08-02 10:45:44 -07002463 u32 sid = ~0, session_events;
Florin Coras3c7d4f92018-12-14 11:28:43 -08002464 u64 session_evt_data = ~0;
Florin Coras54693d22018-07-17 10:46:29 -07002465 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07002466 u8 add_event = 0;
2467
2468 switch (e->event_type)
2469 {
2470 case FIFO_EVENT_APP_RX:
2471 ASSERT (e->fifo->client_thread_index == vcl_get_worker_index ());
2472 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2473 sid = e->fifo->client_session_index;
Florin Corasfa915f82018-12-26 16:29:06 -08002474 if (!(session = vcl_session_get (wrk, sid)))
2475 break;
Florin Coras86f04502018-09-12 16:08:01 -07002476 session_events = session->vep.ev.events;
Florin Corasaa27eb92018-10-13 12:20:01 -07002477 if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
Florin Coras86f04502018-09-12 16:08:01 -07002478 break;
2479 add_event = 1;
2480 events[*num_ev].events |= EPOLLIN;
2481 session_evt_data = session->vep.ev.data.u64;
Florin Corasaa27eb92018-10-13 12:20:01 -07002482 session->has_rx_evt = 1;
Florin Coras86f04502018-09-12 16:08:01 -07002483 break;
2484 case FIFO_EVENT_APP_TX:
2485 sid = e->fifo->client_session_index;
Florin Corasfa915f82018-12-26 16:29:06 -08002486 if (!(session = vcl_session_get (wrk, sid)))
2487 break;
Florin Coras86f04502018-09-12 16:08:01 -07002488 session_events = session->vep.ev.events;
2489 if (!(EPOLLOUT & session_events))
2490 break;
2491 add_event = 1;
2492 events[*num_ev].events |= EPOLLOUT;
2493 session_evt_data = session->vep.ev.data.u64;
Florin Coras1bcad5c2019-01-09 20:04:38 -08002494 svm_fifo_reset_tx_ntf (session->tx_fifo);
Florin Coras86f04502018-09-12 16:08:01 -07002495 break;
2496 case SESSION_IO_EVT_CT_TX:
2497 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2498 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0);
Florin Corasfa915f82018-12-26 16:29:06 -08002499 if (PREDICT_FALSE (!session))
2500 break;
Florin Coras86f04502018-09-12 16:08:01 -07002501 sid = session->session_index;
2502 session_events = session->vep.ev.events;
Florin Corasaa27eb92018-10-13 12:20:01 -07002503 if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
Florin Coras86f04502018-09-12 16:08:01 -07002504 break;
2505 add_event = 1;
2506 events[*num_ev].events |= EPOLLIN;
2507 session_evt_data = session->vep.ev.data.u64;
Florin Corasaa27eb92018-10-13 12:20:01 -07002508 session->has_rx_evt = 1;
Florin Coras86f04502018-09-12 16:08:01 -07002509 break;
2510 case SESSION_IO_EVT_CT_RX:
2511 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1);
Florin Corasfa915f82018-12-26 16:29:06 -08002512 if (PREDICT_FALSE (!session))
2513 break;
Florin Coras86f04502018-09-12 16:08:01 -07002514 sid = session->session_index;
2515 session_events = session->vep.ev.events;
2516 if (!(EPOLLOUT & session_events))
2517 break;
2518 add_event = 1;
2519 events[*num_ev].events |= EPOLLOUT;
2520 session_evt_data = session->vep.ev.data.u64;
Florin Coras1bcad5c2019-01-09 20:04:38 -08002521 svm_fifo_reset_tx_ntf (session->tx_fifo);
Florin Coras86f04502018-09-12 16:08:01 -07002522 break;
2523 case SESSION_CTRL_EVT_ACCEPTED:
Florin Coras3c7d4f92018-12-14 11:28:43 -08002524 session = vcl_session_accepted (wrk,
2525 (session_accepted_msg_t *) e->data);
Florin Coras86f04502018-09-12 16:08:01 -07002526 if (!session)
Florin Coras3c7d4f92018-12-14 11:28:43 -08002527 break;
Florin Coras86f04502018-09-12 16:08:01 -07002528
Florin Coras86f04502018-09-12 16:08:01 -07002529 session_events = session->vep.ev.events;
2530 if (!(EPOLLIN & session_events))
2531 break;
2532
2533 add_event = 1;
2534 events[*num_ev].events |= EPOLLIN;
2535 session_evt_data = session->vep.ev.data.u64;
2536 break;
2537 case SESSION_CTRL_EVT_CONNECTED:
2538 connected_msg = (session_connected_msg_t *) e->data;
2539 vcl_session_connected_handler (wrk, connected_msg);
2540 /* Generate EPOLLOUT because there's no connected event */
2541 sid = vcl_session_index_from_vpp_handle (wrk, connected_msg->handle);
Florin Corasfa915f82018-12-26 16:29:06 -08002542 if (!(session = vcl_session_get (wrk, sid)))
2543 break;
Florin Coras86f04502018-09-12 16:08:01 -07002544 session_events = session->vep.ev.events;
Florin Coras72f77822019-01-22 19:05:52 -08002545 if (!(EPOLLOUT & session_events))
2546 break;
2547 add_event = 1;
2548 events[*num_ev].events |= EPOLLOUT;
2549 session_evt_data = session->vep.ev.data.u64;
Florin Coras86f04502018-09-12 16:08:01 -07002550 break;
2551 case SESSION_CTRL_EVT_DISCONNECTED:
2552 disconnected_msg = (session_disconnected_msg_t *) e->data;
Florin Coras3c7d4f92018-12-14 11:28:43 -08002553 session = vcl_session_disconnected_handler (wrk, disconnected_msg);
2554 if (!session)
Florin Coras86f04502018-09-12 16:08:01 -07002555 break;
Florin Coras72f77822019-01-22 19:05:52 -08002556 session_events = session->vep.ev.events;
2557 if (!((EPOLLHUP | EPOLLRDHUP) & session_events))
2558 break;
Florin Coras86f04502018-09-12 16:08:01 -07002559 add_event = 1;
2560 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2561 session_evt_data = session->vep.ev.data.u64;
Florin Coras86f04502018-09-12 16:08:01 -07002562 break;
2563 case SESSION_CTRL_EVT_RESET:
2564 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
2565 if (!(session = vcl_session_get (wrk, sid)))
2566 break;
Florin Coras72f77822019-01-22 19:05:52 -08002567 session_events = session->vep.ev.events;
2568 if (!((EPOLLHUP | EPOLLRDHUP) & session_events))
2569 break;
Florin Coras86f04502018-09-12 16:08:01 -07002570 add_event = 1;
2571 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2572 session_evt_data = session->vep.ev.data.u64;
Florin Coras86f04502018-09-12 16:08:01 -07002573 break;
Florin Coras30e79c22019-01-02 19:31:22 -08002574 case SESSION_CTRL_EVT_REQ_WORKER_UPDATE:
2575 vcl_session_req_worker_update_handler (wrk, e->data);
2576 break;
2577 case SESSION_CTRL_EVT_WORKER_UPDATE_REPLY:
2578 vcl_session_worker_update_reply_handler (wrk, e->data);
2579 break;
Florin Coras86f04502018-09-12 16:08:01 -07002580 default:
2581 VDBG (0, "unhandled: %u", e->event_type);
2582 break;
2583 }
2584
2585 if (add_event)
2586 {
2587 events[*num_ev].data.u64 = session_evt_data;
2588 if (EPOLLONESHOT & session_events)
2589 {
2590 session = vcl_session_get (wrk, sid);
2591 session->vep.ev.events = 0;
2592 }
2593 *num_ev += 1;
2594 }
2595}
2596
2597static int
2598vcl_epoll_wait_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
2599 struct epoll_event *events, u32 maxevents,
2600 double wait_for_time, u32 * num_ev)
2601{
Florin Coras99368312018-08-02 10:45:44 -07002602 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07002603 session_event_t *e;
Florin Coras54693d22018-07-17 10:46:29 -07002604 int i;
2605
Florin Coras539663c2018-09-28 14:59:37 -07002606 if (vec_len (wrk->mq_msg_vector) && svm_msg_q_is_empty (mq))
2607 goto handle_dequeued;
2608
Florin Coras54693d22018-07-17 10:46:29 -07002609 svm_msg_q_lock (mq);
2610 if (svm_msg_q_is_empty (mq))
2611 {
2612 if (!wait_for_time)
2613 {
2614 svm_msg_q_unlock (mq);
2615 return 0;
2616 }
2617 else if (wait_for_time < 0)
2618 {
2619 svm_msg_q_wait (mq);
2620 }
2621 else
2622 {
Florin Coras60f1fc12018-08-16 14:57:31 -07002623 if (svm_msg_q_timedwait (mq, wait_for_time / 1e3))
Florin Coras54693d22018-07-17 10:46:29 -07002624 {
2625 svm_msg_q_unlock (mq);
2626 return 0;
2627 }
2628 }
2629 }
Florin Coras134a9962018-08-28 11:32:04 -07002630 vcl_mq_dequeue_batch (wrk, mq);
Florin Coras54693d22018-07-17 10:46:29 -07002631 svm_msg_q_unlock (mq);
2632
Florin Coras539663c2018-09-28 14:59:37 -07002633handle_dequeued:
Florin Coras134a9962018-08-28 11:32:04 -07002634 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07002635 {
Florin Coras134a9962018-08-28 11:32:04 -07002636 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07002637 e = svm_msg_q_msg_data (mq, msg);
Florin Corasaa27eb92018-10-13 12:20:01 -07002638 if (*num_ev < maxevents)
2639 vcl_epoll_wait_handle_mq_event (wrk, e, events, num_ev);
2640 else
2641 vec_add1 (wrk->unhandled_evts_vector, *e);
Florin Coras99368312018-08-02 10:45:44 -07002642 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002643 }
Florin Corasaa27eb92018-10-13 12:20:01 -07002644 vec_reset_length (wrk->mq_msg_vector);
Florin Coras30e79c22019-01-02 19:31:22 -08002645 vcl_handle_pending_wrk_updates (wrk);
Florin Coras54693d22018-07-17 10:46:29 -07002646 return *num_ev;
2647}
2648
Florin Coras99368312018-08-02 10:45:44 -07002649static int
Florin Coras134a9962018-08-28 11:32:04 -07002650vppcom_epoll_wait_condvar (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002651 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002652{
2653 vcl_cut_through_registration_t *cr;
2654 double total_wait = 0, wait_slice;
Florin Coras99368312018-08-02 10:45:44 -07002655 int rv;
2656
Florin Coras72f77822019-01-22 19:05:52 -08002657 wait_for_time = (wait_for_time == -1) ? (double) 1e6 : wait_for_time;
Florin Coras134a9962018-08-28 11:32:04 -07002658 wait_slice = wrk->cut_through_registrations ? 10e-6 : wait_for_time;
Florin Coras99368312018-08-02 10:45:44 -07002659
2660 do
2661 {
Florin Coras134a9962018-08-28 11:32:04 -07002662 vcl_ct_registration_lock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002663 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002664 pool_foreach (cr, wrk->cut_through_registrations, ({
Florin Coras86f04502018-09-12 16:08:01 -07002665 vcl_epoll_wait_handle_mq (wrk, cr->mq, events, maxevents, 0, &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002666 }));
2667 /* *INDENT-ON* */
Florin Coras134a9962018-08-28 11:32:04 -07002668 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002669
Florin Coras134a9962018-08-28 11:32:04 -07002670 rv = vcl_epoll_wait_handle_mq (wrk, wrk->app_event_queue, events,
Florin Coras86f04502018-09-12 16:08:01 -07002671 maxevents, n_evts ? 0 : wait_slice,
2672 &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002673 if (rv)
2674 total_wait += wait_slice;
Florin Coras86f04502018-09-12 16:08:01 -07002675 if (n_evts)
2676 return n_evts;
Florin Coras99368312018-08-02 10:45:44 -07002677 }
2678 while (total_wait < wait_for_time);
Florin Coras86f04502018-09-12 16:08:01 -07002679 return n_evts;
Florin Coras99368312018-08-02 10:45:44 -07002680}
2681
2682static int
Florin Coras134a9962018-08-28 11:32:04 -07002683vppcom_epoll_wait_eventfd (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002684 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002685{
2686 vcl_mq_evt_conn_t *mqc;
2687 int __clib_unused n_read;
2688 int n_mq_evts, i;
Florin Coras99368312018-08-02 10:45:44 -07002689 u64 buf;
2690
Florin Coras134a9962018-08-28 11:32:04 -07002691 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
Florin Corasa4878ed2018-10-12 13:09:36 -07002692again:
Florin Coras134a9962018-08-28 11:32:04 -07002693 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2694 vec_len (wrk->mq_events), wait_for_time);
Florin Coras99368312018-08-02 10:45:44 -07002695 for (i = 0; i < n_mq_evts; i++)
2696 {
Florin Coras134a9962018-08-28 11:32:04 -07002697 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002698 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002699 vcl_epoll_wait_handle_mq (wrk, mqc->mq, events, maxevents, 0, &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002700 }
Florin Corasa4878ed2018-10-12 13:09:36 -07002701 if (!n_evts && n_mq_evts > 0)
2702 goto again;
Florin Coras99368312018-08-02 10:45:44 -07002703
2704 return (int) n_evts;
2705}
2706
Dave Wallacef7f809c2017-10-03 01:48:42 -04002707int
Florin Coras134a9962018-08-28 11:32:04 -07002708vppcom_epoll_wait (uint32_t vep_handle, struct epoll_event *events,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002709 int maxevents, double wait_for_time)
2710{
Florin Coras134a9962018-08-28 11:32:04 -07002711 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002712 vcl_session_t *vep_session;
Florin Coras86f04502018-09-12 16:08:01 -07002713 u32 n_evts = 0;
2714 int i;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002715
2716 if (PREDICT_FALSE (maxevents <= 0))
2717 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002718 clib_warning ("VCL<%d>: ERROR: Invalid maxevents (%d)!",
Dave Wallace4878cbe2017-11-21 03:45:09 -05002719 getpid (), maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002720 return VPPCOM_EINVAL;
2721 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002722
Florin Coras134a9962018-08-28 11:32:04 -07002723 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras14598772018-09-04 19:47:52 -07002724 if (!vep_session)
2725 return VPPCOM_EBADFD;
2726
Florin Coras54693d22018-07-17 10:46:29 -07002727 if (PREDICT_FALSE (!vep_session->is_vep))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002728 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002729 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
Florin Coras134a9962018-08-28 11:32:04 -07002730 getpid (), vep_handle);
Florin Coras54693d22018-07-17 10:46:29 -07002731 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002732 }
Florin Coras54693d22018-07-17 10:46:29 -07002733
2734 memset (events, 0, sizeof (*events) * maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002735
Florin Coras86f04502018-09-12 16:08:01 -07002736 if (vec_len (wrk->unhandled_evts_vector))
2737 {
2738 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2739 {
2740 vcl_epoll_wait_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i],
2741 events, &n_evts);
2742 if (n_evts == maxevents)
2743 {
2744 i += 1;
2745 break;
2746 }
2747 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002748
Florin Coras86f04502018-09-12 16:08:01 -07002749 vec_delete (wrk->unhandled_evts_vector, i, 0);
2750 }
2751
2752 if (vcm->cfg.use_mq_eventfd)
2753 return vppcom_epoll_wait_eventfd (wrk, events, maxevents, n_evts,
2754 wait_for_time);
2755
2756 return vppcom_epoll_wait_condvar (wrk, events, maxevents, n_evts,
2757 wait_for_time);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002758}
2759
Dave Wallace35830af2017-10-09 01:43:42 -04002760int
Florin Coras134a9962018-08-28 11:32:04 -07002761vppcom_session_attr (uint32_t session_handle, uint32_t op,
Dave Wallace35830af2017-10-09 01:43:42 -04002762 void *buffer, uint32_t * buflen)
2763{
Florin Coras134a9962018-08-28 11:32:04 -07002764 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002765 vcl_session_t *session;
Dave Wallace35830af2017-10-09 01:43:42 -04002766 int rv = VPPCOM_OK;
Florin Coras7baeb712019-01-04 17:05:43 -08002767 u32 *flags = buffer, tmp_flags = 0;
Steven2199aab2017-10-15 20:18:47 -07002768 vppcom_endpt_t *ep = buffer;
Dave Wallace35830af2017-10-09 01:43:42 -04002769
Florin Coras134a9962018-08-28 11:32:04 -07002770 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002771 if (!session)
2772 return VPPCOM_EBADFD;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002773
Dave Wallace35830af2017-10-09 01:43:42 -04002774 switch (op)
2775 {
2776 case VPPCOM_ATTR_GET_NREAD:
Florin Coras0ef8ef22019-01-18 08:37:13 -08002777 rv = vcl_session_read_ready (session);
Florin Coras7baeb712019-01-04 17:05:43 -08002778 VDBG (2, "VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d", rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002779 break;
2780
Dave Wallace227867f2017-11-13 21:21:53 -05002781 case VPPCOM_ATTR_GET_NWRITE:
Florin Coras0ef8ef22019-01-18 08:37:13 -08002782 rv = vcl_session_write_ready (session);
Florin Coras0d427d82018-06-27 03:24:07 -07002783 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d",
Florin Coras134a9962018-08-28 11:32:04 -07002784 getpid (), session_handle, rv);
Dave Wallace35830af2017-10-09 01:43:42 -04002785 break;
2786
2787 case VPPCOM_ATTR_GET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002788 if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002789 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002790 *flags = O_RDWR | (VCL_SESS_ATTR_TEST (session->attr,
2791 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002792 *buflen = sizeof (*flags);
Florin Coras0d427d82018-06-27 03:24:07 -07002793 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_FLAGS: sid %u, flags = 0x%08x, "
2794 "is_nonblocking = %u", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002795 session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07002796 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002797 }
2798 else
2799 rv = VPPCOM_EINVAL;
2800 break;
2801
2802 case VPPCOM_ATTR_SET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05002803 if (PREDICT_TRUE (buffer && buflen && (*buflen == sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04002804 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002805 if (*flags & O_NONBLOCK)
2806 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
2807 else
2808 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_NONBLOCK);
2809
Florin Coras0d427d82018-06-27 03:24:07 -07002810 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_FLAGS: sid %u, flags = 0x%08x,"
2811 " is_nonblocking = %u",
Florin Coras134a9962018-08-28 11:32:04 -07002812 getpid (), session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07002813 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04002814 }
2815 else
2816 rv = VPPCOM_EINVAL;
2817 break;
2818
2819 case VPPCOM_ATTR_GET_PEER_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002820 if (PREDICT_TRUE (buffer && buflen &&
2821 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002822 {
Florin Coras7e12d942018-06-27 14:32:43 -07002823 ep->is_ip4 = session->transport.is_ip4;
2824 ep->port = session->transport.rmt_port;
2825 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05002826 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
2827 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07002828 else
Dave Barach178cf492018-11-13 16:34:13 -05002829 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
2830 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07002831 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07002832 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = %u, "
2833 "addr = %U, port %u", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002834 session_handle, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07002835 &session->transport.rmt_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002836 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2837 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002838 }
2839 else
2840 rv = VPPCOM_EINVAL;
2841 break;
2842
2843 case VPPCOM_ATTR_GET_LCL_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05002844 if (PREDICT_TRUE (buffer && buflen &&
2845 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04002846 {
Florin Coras7e12d942018-06-27 14:32:43 -07002847 ep->is_ip4 = session->transport.is_ip4;
2848 ep->port = session->transport.lcl_port;
2849 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05002850 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip4,
2851 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07002852 else
Dave Barach178cf492018-11-13 16:34:13 -05002853 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip6,
2854 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07002855 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07002856 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = %u,"
2857 " addr = %U port %d", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002858 session_handle, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07002859 &session->transport.lcl_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07002860 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2861 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04002862 }
2863 else
2864 rv = VPPCOM_EINVAL;
2865 break;
Stevenb5a11602017-10-11 09:59:30 -07002866
Dave Wallace048b1d62018-01-03 22:24:41 -05002867 case VPPCOM_ATTR_GET_LIBC_EPFD:
2868 rv = session->libc_epfd;
Florin Coras0d427d82018-06-27 03:24:07 -07002869 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d",
2870 getpid (), rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05002871 break;
2872
2873 case VPPCOM_ATTR_SET_LIBC_EPFD:
2874 if (PREDICT_TRUE (buffer && buflen &&
2875 (*buflen == sizeof (session->libc_epfd))))
2876 {
2877 session->libc_epfd = *(int *) buffer;
2878 *buflen = sizeof (session->libc_epfd);
2879
Florin Coras0d427d82018-06-27 03:24:07 -07002880 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_LIBC_EPFD: libc_epfd %d, "
2881 "buflen %d", getpid (), session->libc_epfd, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002882 }
2883 else
2884 rv = VPPCOM_EINVAL;
2885 break;
2886
2887 case VPPCOM_ATTR_GET_PROTOCOL:
2888 if (buffer && buflen && (*buflen >= sizeof (int)))
2889 {
Florin Coras7e12d942018-06-27 14:32:43 -07002890 *(int *) buffer = session->session_type;
Dave Wallace048b1d62018-01-03 22:24:41 -05002891 *buflen = sizeof (int);
2892
Florin Coras0d427d82018-06-27 03:24:07 -07002893 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_PROTOCOL: %d (%s), buflen %d",
2894 getpid (), *(int *) buffer, *(int *) buffer ? "UDP" : "TCP",
2895 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002896 }
2897 else
2898 rv = VPPCOM_EINVAL;
2899 break;
2900
2901 case VPPCOM_ATTR_GET_LISTEN:
2902 if (buffer && buflen && (*buflen >= sizeof (int)))
2903 {
2904 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2905 VCL_SESS_ATTR_LISTEN);
2906 *buflen = sizeof (int);
2907
Florin Coras0d427d82018-06-27 03:24:07 -07002908 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LISTEN: %d, buflen %d",
2909 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002910 }
2911 else
2912 rv = VPPCOM_EINVAL;
2913 break;
2914
2915 case VPPCOM_ATTR_GET_ERROR:
2916 if (buffer && buflen && (*buflen >= sizeof (int)))
2917 {
2918 *(int *) buffer = 0;
2919 *buflen = sizeof (int);
2920
Florin Coras0d427d82018-06-27 03:24:07 -07002921 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_ERROR: %d, buflen %d, #VPP-TBD#",
2922 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002923 }
2924 else
2925 rv = VPPCOM_EINVAL;
2926 break;
2927
2928 case VPPCOM_ATTR_GET_TX_FIFO_LEN:
2929 if (buffer && buflen && (*buflen >= sizeof (u32)))
2930 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002931
2932 /* VPP-TBD */
2933 *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002934 session->tx_fifo ? session->tx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05002935 vcm->cfg.tx_fifo_size);
2936 *buflen = sizeof (u32);
2937
Florin Coras0d427d82018-06-27 03:24:07 -07002938 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), "
2939 "buflen %d, #VPP-TBD#", getpid (),
2940 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002941 }
2942 else
2943 rv = VPPCOM_EINVAL;
2944 break;
2945
2946 case VPPCOM_ATTR_SET_TX_FIFO_LEN:
2947 if (buffer && buflen && (*buflen == sizeof (u32)))
2948 {
2949 /* VPP-TBD */
2950 session->sndbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07002951 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), "
2952 "buflen %d, #VPP-TBD#", getpid (),
2953 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002954 }
2955 else
2956 rv = VPPCOM_EINVAL;
2957 break;
2958
2959 case VPPCOM_ATTR_GET_RX_FIFO_LEN:
2960 if (buffer && buflen && (*buflen >= sizeof (u32)))
2961 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002962
2963 /* VPP-TBD */
2964 *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002965 session->rx_fifo ? session->rx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05002966 vcm->cfg.rx_fifo_size);
2967 *buflen = sizeof (u32);
2968
Florin Coras0d427d82018-06-27 03:24:07 -07002969 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_RX_FIFO_LEN: %u (0x%x), "
2970 "buflen %d, #VPP-TBD#", getpid (),
2971 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002972 }
2973 else
2974 rv = VPPCOM_EINVAL;
2975 break;
2976
2977 case VPPCOM_ATTR_SET_RX_FIFO_LEN:
2978 if (buffer && buflen && (*buflen == sizeof (u32)))
2979 {
2980 /* VPP-TBD */
2981 session->rcvbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07002982 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_RX_FIFO_LEN: %u (0x%x), "
2983 "buflen %d, #VPP-TBD#", getpid (),
2984 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05002985 }
2986 else
2987 rv = VPPCOM_EINVAL;
2988 break;
2989
2990 case VPPCOM_ATTR_GET_REUSEADDR:
2991 if (buffer && buflen && (*buflen >= sizeof (int)))
2992 {
2993 /* VPP-TBD */
2994 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2995 VCL_SESS_ATTR_REUSEADDR);
2996 *buflen = sizeof (int);
2997
Florin Coras0d427d82018-06-27 03:24:07 -07002998 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEADDR: %d, "
2999 "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003000 }
3001 else
3002 rv = VPPCOM_EINVAL;
3003 break;
3004
Stevenb5a11602017-10-11 09:59:30 -07003005 case VPPCOM_ATTR_SET_REUSEADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05003006 if (buffer && buflen && (*buflen == sizeof (int)) &&
3007 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
3008 {
3009 /* VPP-TBD */
3010 if (*(int *) buffer)
3011 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEADDR);
3012 else
3013 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEADDR);
3014
Florin Coras0d427d82018-06-27 03:24:07 -07003015 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEADDR: %d, buflen %d,"
3016 " #VPP-TBD#", getpid (),
3017 VCL_SESS_ATTR_TEST (session->attr,
3018 VCL_SESS_ATTR_REUSEADDR), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003019 }
3020 else
3021 rv = VPPCOM_EINVAL;
3022 break;
3023
3024 case VPPCOM_ATTR_GET_REUSEPORT:
3025 if (buffer && buflen && (*buflen >= sizeof (int)))
3026 {
3027 /* VPP-TBD */
3028 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3029 VCL_SESS_ATTR_REUSEPORT);
3030 *buflen = sizeof (int);
3031
Florin Coras0d427d82018-06-27 03:24:07 -07003032 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEPORT: %d, buflen %d,"
3033 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003034 }
3035 else
3036 rv = VPPCOM_EINVAL;
3037 break;
3038
3039 case VPPCOM_ATTR_SET_REUSEPORT:
3040 if (buffer && buflen && (*buflen == sizeof (int)) &&
3041 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
3042 {
3043 /* VPP-TBD */
3044 if (*(int *) buffer)
3045 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEPORT);
3046 else
3047 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEPORT);
3048
Florin Coras0d427d82018-06-27 03:24:07 -07003049 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEPORT: %d, buflen %d,"
3050 " #VPP-TBD#", getpid (),
3051 VCL_SESS_ATTR_TEST (session->attr,
3052 VCL_SESS_ATTR_REUSEPORT), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003053 }
3054 else
3055 rv = VPPCOM_EINVAL;
3056 break;
3057
3058 case VPPCOM_ATTR_GET_BROADCAST:
3059 if (buffer && buflen && (*buflen >= sizeof (int)))
3060 {
3061 /* VPP-TBD */
3062 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3063 VCL_SESS_ATTR_BROADCAST);
3064 *buflen = sizeof (int);
3065
Florin Coras0d427d82018-06-27 03:24:07 -07003066 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_BROADCAST: %d, buflen %d,"
3067 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003068 }
3069 else
3070 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003071 break;
3072
3073 case VPPCOM_ATTR_SET_BROADCAST:
Dave Wallace048b1d62018-01-03 22:24:41 -05003074 if (buffer && buflen && (*buflen == sizeof (int)))
3075 {
3076 /* VPP-TBD */
3077 if (*(int *) buffer)
3078 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_BROADCAST);
3079 else
3080 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_BROADCAST);
3081
Florin Coras0d427d82018-06-27 03:24:07 -07003082 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_BROADCAST: %d, buflen %d, "
3083 "#VPP-TBD#", getpid (),
3084 VCL_SESS_ATTR_TEST (session->attr,
3085 VCL_SESS_ATTR_BROADCAST), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003086 }
3087 else
3088 rv = VPPCOM_EINVAL;
3089 break;
3090
3091 case VPPCOM_ATTR_GET_V6ONLY:
3092 if (buffer && buflen && (*buflen >= sizeof (int)))
3093 {
3094 /* VPP-TBD */
3095 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3096 VCL_SESS_ATTR_V6ONLY);
3097 *buflen = sizeof (int);
3098
Florin Coras0d427d82018-06-27 03:24:07 -07003099 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_V6ONLY: %d, buflen %d, "
3100 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003101 }
3102 else
3103 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003104 break;
3105
3106 case VPPCOM_ATTR_SET_V6ONLY:
Dave Wallace048b1d62018-01-03 22:24:41 -05003107 if (buffer && buflen && (*buflen == sizeof (int)))
3108 {
3109 /* VPP-TBD */
3110 if (*(int *) buffer)
3111 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_V6ONLY);
3112 else
3113 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_V6ONLY);
3114
Florin Coras0d427d82018-06-27 03:24:07 -07003115 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_V6ONLY: %d, buflen %d, "
3116 "#VPP-TBD#", getpid (),
3117 VCL_SESS_ATTR_TEST (session->attr,
3118 VCL_SESS_ATTR_V6ONLY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003119 }
3120 else
3121 rv = VPPCOM_EINVAL;
3122 break;
3123
3124 case VPPCOM_ATTR_GET_KEEPALIVE:
3125 if (buffer && buflen && (*buflen >= sizeof (int)))
3126 {
3127 /* VPP-TBD */
3128 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3129 VCL_SESS_ATTR_KEEPALIVE);
3130 *buflen = sizeof (int);
3131
Florin Coras0d427d82018-06-27 03:24:07 -07003132 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_KEEPALIVE: %d, buflen %d, "
3133 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003134 }
3135 else
3136 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003137 break;
Stevenbccd3392017-10-12 20:42:21 -07003138
3139 case VPPCOM_ATTR_SET_KEEPALIVE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003140 if (buffer && buflen && (*buflen == sizeof (int)))
3141 {
3142 /* VPP-TBD */
3143 if (*(int *) buffer)
3144 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3145 else
3146 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3147
Florin Coras0d427d82018-06-27 03:24:07 -07003148 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_KEEPALIVE: %d, buflen %d, "
3149 "#VPP-TBD#", getpid (),
3150 VCL_SESS_ATTR_TEST (session->attr,
3151 VCL_SESS_ATTR_KEEPALIVE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003152 }
3153 else
3154 rv = VPPCOM_EINVAL;
3155 break;
3156
3157 case VPPCOM_ATTR_GET_TCP_NODELAY:
3158 if (buffer && buflen && (*buflen >= sizeof (int)))
3159 {
3160 /* VPP-TBD */
3161 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3162 VCL_SESS_ATTR_TCP_NODELAY);
3163 *buflen = sizeof (int);
3164
Florin Coras0d427d82018-06-27 03:24:07 -07003165 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_NODELAY: %d, buflen %d, "
3166 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003167 }
3168 else
3169 rv = VPPCOM_EINVAL;
3170 break;
3171
3172 case VPPCOM_ATTR_SET_TCP_NODELAY:
3173 if (buffer && buflen && (*buflen == sizeof (int)))
3174 {
3175 /* VPP-TBD */
3176 if (*(int *) buffer)
3177 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3178 else
3179 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3180
Florin Coras0d427d82018-06-27 03:24:07 -07003181 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_NODELAY: %d, buflen %d, "
3182 "#VPP-TBD#", getpid (),
3183 VCL_SESS_ATTR_TEST (session->attr,
3184 VCL_SESS_ATTR_TCP_NODELAY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003185 }
3186 else
3187 rv = VPPCOM_EINVAL;
3188 break;
3189
3190 case VPPCOM_ATTR_GET_TCP_KEEPIDLE:
3191 if (buffer && buflen && (*buflen >= sizeof (int)))
3192 {
3193 /* VPP-TBD */
3194 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3195 VCL_SESS_ATTR_TCP_KEEPIDLE);
3196 *buflen = sizeof (int);
3197
Florin Coras0d427d82018-06-27 03:24:07 -07003198 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPIDLE: %d, buflen %d, "
3199 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003200 }
3201 else
3202 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003203 break;
3204
3205 case VPPCOM_ATTR_SET_TCP_KEEPIDLE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003206 if (buffer && buflen && (*buflen == sizeof (int)))
3207 {
3208 /* VPP-TBD */
3209 if (*(int *) buffer)
3210 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3211 else
3212 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3213
Florin Coras0d427d82018-06-27 03:24:07 -07003214 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPIDLE: %d, buflen %d, "
3215 "#VPP-TBD#", getpid (),
3216 VCL_SESS_ATTR_TEST (session->attr,
3217 VCL_SESS_ATTR_TCP_KEEPIDLE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003218 }
3219 else
3220 rv = VPPCOM_EINVAL;
3221 break;
3222
3223 case VPPCOM_ATTR_GET_TCP_KEEPINTVL:
3224 if (buffer && buflen && (*buflen >= sizeof (int)))
3225 {
3226 /* VPP-TBD */
3227 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3228 VCL_SESS_ATTR_TCP_KEEPINTVL);
3229 *buflen = sizeof (int);
3230
Florin Coras0d427d82018-06-27 03:24:07 -07003231 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPINTVL: %d, buflen %d, "
3232 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003233 }
3234 else
3235 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003236 break;
3237
3238 case VPPCOM_ATTR_SET_TCP_KEEPINTVL:
Dave Wallace048b1d62018-01-03 22:24:41 -05003239 if (buffer && buflen && (*buflen == sizeof (int)))
3240 {
3241 /* VPP-TBD */
3242 if (*(int *) buffer)
3243 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3244 else
3245 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3246
Florin Coras0d427d82018-06-27 03:24:07 -07003247 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPINTVL: %d, buflen %d, "
3248 "#VPP-TBD#", getpid (),
3249 VCL_SESS_ATTR_TEST (session->attr,
3250 VCL_SESS_ATTR_TCP_KEEPINTVL), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003251 }
3252 else
3253 rv = VPPCOM_EINVAL;
3254 break;
3255
3256 case VPPCOM_ATTR_GET_TCP_USER_MSS:
3257 if (buffer && buflen && (*buflen >= sizeof (u32)))
3258 {
3259 /* VPP-TBD */
3260 *(u32 *) buffer = session->user_mss;
3261 *buflen = sizeof (int);
3262
Florin Coras0d427d82018-06-27 03:24:07 -07003263 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d,"
3264 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003265 }
3266 else
3267 rv = VPPCOM_EINVAL;
3268 break;
3269
3270 case VPPCOM_ATTR_SET_TCP_USER_MSS:
3271 if (buffer && buflen && (*buflen == sizeof (u32)))
3272 {
3273 /* VPP-TBD */
3274 session->user_mss = *(u32 *) buffer;
3275
Florin Coras0d427d82018-06-27 03:24:07 -07003276 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_USER_MSS: %u, buflen %d, "
3277 "#VPP-TBD#", getpid (), session->user_mss, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003278 }
3279 else
3280 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003281 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003282
Florin Coras7baeb712019-01-04 17:05:43 -08003283 case VPPCOM_ATTR_SET_SHUT:
3284 if (*flags == SHUT_RD || *flags == SHUT_RDWR)
3285 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_SHUT_RD);
3286 if (*flags == SHUT_WR || *flags == SHUT_RDWR)
3287 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_SHUT_WR);
3288 break;
3289
3290 case VPPCOM_ATTR_GET_SHUT:
3291 if (VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_SHUT_RD))
3292 tmp_flags = 1;
3293 if (VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_SHUT_WR))
3294 tmp_flags |= 2;
3295 if (tmp_flags == 1)
3296 *(int *) buffer = SHUT_RD;
3297 else if (tmp_flags == 2)
3298 *(int *) buffer = SHUT_WR;
3299 else if (tmp_flags == 3)
3300 *(int *) buffer = SHUT_RDWR;
3301 *buflen = sizeof (int);
3302 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003303 default:
3304 rv = VPPCOM_EINVAL;
3305 break;
Dave Wallace35830af2017-10-09 01:43:42 -04003306 }
3307
Dave Wallace35830af2017-10-09 01:43:42 -04003308 return rv;
3309}
3310
Stevenac1f96d2017-10-24 16:03:58 -07003311int
Florin Coras134a9962018-08-28 11:32:04 -07003312vppcom_session_recvfrom (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003313 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3314{
Florin Coras134a9962018-08-28 11:32:04 -07003315 vcl_worker_t *wrk = vcl_worker_get_current ();
Stevenac1f96d2017-10-24 16:03:58 -07003316 int rv = VPPCOM_OK;
Florin Coras7e12d942018-06-27 14:32:43 -07003317 vcl_session_t *session = 0;
Stevenac1f96d2017-10-24 16:03:58 -07003318
3319 if (ep)
3320 {
Florin Coras134a9962018-08-28 11:32:04 -07003321 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07003322 if (PREDICT_FALSE (!session))
Stevenac1f96d2017-10-24 16:03:58 -07003323 {
Florin Coras0d427d82018-06-27 03:24:07 -07003324 VDBG (0, "VCL<%d>: invalid session, sid (%u) has been closed!",
Florin Coras134a9962018-08-28 11:32:04 -07003325 getpid (), session_handle);
Florin Coras460dce62018-07-27 05:45:06 -07003326 return VPPCOM_EBADFD;
Stevenac1f96d2017-10-24 16:03:58 -07003327 }
Florin Coras7e12d942018-06-27 14:32:43 -07003328 ep->is_ip4 = session->transport.is_ip4;
3329 ep->port = session->transport.rmt_port;
Stevenac1f96d2017-10-24 16:03:58 -07003330 }
Steven58f464e2017-10-25 12:33:12 -07003331
3332 if (flags == 0)
Florin Coras134a9962018-08-28 11:32:04 -07003333 rv = vppcom_session_read (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003334 else if (flags & MSG_PEEK)
Florin Coras134a9962018-08-28 11:32:04 -07003335 rv = vppcom_session_peek (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003336 else
3337 {
Florin Corasa7a1a222018-12-30 17:11:31 -08003338 VDBG (0, "Unsupport flags for recvfrom %d", flags);
Florin Coras460dce62018-07-27 05:45:06 -07003339 return VPPCOM_EAFNOSUPPORT;
Stevenac1f96d2017-10-24 16:03:58 -07003340 }
3341
Florin Coras99368312018-08-02 10:45:44 -07003342 if (ep)
3343 {
3344 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05003345 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
3346 sizeof (ip4_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003347 else
Dave Barach178cf492018-11-13 16:34:13 -05003348 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
3349 sizeof (ip6_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003350 }
Florin Coras460dce62018-07-27 05:45:06 -07003351
Stevenac1f96d2017-10-24 16:03:58 -07003352 return rv;
3353}
3354
3355int
Florin Coras134a9962018-08-28 11:32:04 -07003356vppcom_session_sendto (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003357 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3358{
Dave Wallace617dffa2017-10-26 14:47:06 -04003359 if (!buffer)
3360 return VPPCOM_EINVAL;
3361
3362 if (ep)
3363 {
3364 // TBD
3365 return VPPCOM_EINVAL;
3366 }
3367
3368 if (flags)
3369 {
3370 // TBD check the flags and do the right thing
Florin Coras0d427d82018-06-27 03:24:07 -07003371 VDBG (2, "VCL<%d>: handling flags 0x%u (%d) not implemented yet.",
3372 getpid (), flags, flags);
Dave Wallace617dffa2017-10-26 14:47:06 -04003373 }
3374
Florin Coras42ceddb2018-12-12 10:56:01 -08003375 return (vppcom_session_write_inline (session_handle, buffer, buflen, 1));
Stevenac1f96d2017-10-24 16:03:58 -07003376}
3377
Dave Wallace048b1d62018-01-03 22:24:41 -05003378int
3379vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time)
3380{
Florin Coras134a9962018-08-28 11:32:04 -07003381 vcl_worker_t *wrk = vcl_worker_get_current ();
3382 f64 timeout = clib_time_now (&wrk->clib_time) + wait_for_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05003383 u32 i, keep_trying = 1;
Florin Coras6917b942018-11-13 22:44:54 -08003384 svm_msg_q_msg_t msg;
3385 session_event_t *e;
Dave Wallace048b1d62018-01-03 22:24:41 -05003386 int rv, num_ev = 0;
3387
Florin Coras0d427d82018-06-27 03:24:07 -07003388 VDBG (3, "VCL<%d>: vp %p, nsids %u, wait_for_time %f",
3389 getpid (), vp, n_sids, wait_for_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05003390
3391 if (!vp)
3392 return VPPCOM_EFAULT;
3393
3394 do
3395 {
Florin Coras7e12d942018-06-27 14:32:43 -07003396 vcl_session_t *session;
Dave Wallace048b1d62018-01-03 22:24:41 -05003397
Florin Coras6917b942018-11-13 22:44:54 -08003398 /* Dequeue all events and drop all unhandled io events */
3399 while (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0) == 0)
3400 {
3401 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
3402 vcl_handle_mq_event (wrk, e);
3403 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
3404 }
3405 vec_reset_length (wrk->unhandled_evts_vector);
3406
Dave Wallace048b1d62018-01-03 22:24:41 -05003407 for (i = 0; i < n_sids; i++)
3408 {
Florin Coras7baeb712019-01-04 17:05:43 -08003409 session = vcl_session_get (wrk, vp[i].sh);
Florin Coras070453d2018-08-24 17:04:27 -07003410 if (!session)
Florin Coras6917b942018-11-13 22:44:54 -08003411 {
3412 vp[i].revents = POLLHUP;
3413 num_ev++;
3414 continue;
3415 }
Dave Wallace048b1d62018-01-03 22:24:41 -05003416
Florin Coras6917b942018-11-13 22:44:54 -08003417 vp[i].revents = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003418
3419 if (POLLIN & vp[i].events)
3420 {
Florin Coras0ef8ef22019-01-18 08:37:13 -08003421 rv = vcl_session_read_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003422 if (rv > 0)
3423 {
Florin Coras6917b942018-11-13 22:44:54 -08003424 vp[i].revents |= POLLIN;
Dave Wallace048b1d62018-01-03 22:24:41 -05003425 num_ev++;
3426 }
3427 else if (rv < 0)
3428 {
3429 switch (rv)
3430 {
3431 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003432 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003433 break;
3434
3435 default:
Florin Coras6917b942018-11-13 22:44:54 -08003436 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003437 break;
3438 }
3439 num_ev++;
3440 }
3441 }
3442
3443 if (POLLOUT & vp[i].events)
3444 {
Florin Coras0ef8ef22019-01-18 08:37:13 -08003445 rv = vcl_session_write_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003446 if (rv > 0)
3447 {
Florin Coras6917b942018-11-13 22:44:54 -08003448 vp[i].revents |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05003449 num_ev++;
3450 }
3451 else if (rv < 0)
3452 {
3453 switch (rv)
3454 {
3455 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003456 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003457 break;
3458
3459 default:
Florin Coras6917b942018-11-13 22:44:54 -08003460 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003461 break;
3462 }
3463 num_ev++;
3464 }
3465 }
3466
Dave Wallace7e607a72018-06-18 18:41:32 -04003467 if (0) // Note "done:" label used by VCL_SESSION_LOCK_AND_GET()
Dave Wallace048b1d62018-01-03 22:24:41 -05003468 {
Florin Coras6917b942018-11-13 22:44:54 -08003469 vp[i].revents = POLLNVAL;
Dave Wallace048b1d62018-01-03 22:24:41 -05003470 num_ev++;
3471 }
3472 }
3473 if (wait_for_time != -1)
Florin Coras134a9962018-08-28 11:32:04 -07003474 keep_trying = (clib_time_now (&wrk->clib_time) <= timeout) ? 1 : 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003475 }
3476 while ((num_ev == 0) && keep_trying);
3477
3478 if (VPPCOM_DEBUG > 3)
3479 {
3480 clib_warning ("VCL<%d>: returning %d", getpid (), num_ev);
3481 for (i = 0; i < n_sids; i++)
3482 {
3483 clib_warning ("VCL<%d>: vp[%d].sid %d (0x%x), .events 0x%x, "
Florin Coras7baeb712019-01-04 17:05:43 -08003484 ".revents 0x%x", getpid (), i, vp[i].sh, vp[i].sh,
Florin Coras6917b942018-11-13 22:44:54 -08003485 vp[i].events, vp[i].revents);
Dave Wallace048b1d62018-01-03 22:24:41 -05003486 }
3487 }
3488 return num_ev;
3489}
3490
Florin Coras99368312018-08-02 10:45:44 -07003491int
3492vppcom_mq_epoll_fd (void)
3493{
Florin Coras134a9962018-08-28 11:32:04 -07003494 vcl_worker_t *wrk = vcl_worker_get_current ();
3495 return wrk->mqs_epfd;
3496}
3497
3498int
Florin Coras30e79c22019-01-02 19:31:22 -08003499vppcom_session_index (vcl_session_handle_t session_handle)
Florin Coras134a9962018-08-28 11:32:04 -07003500{
3501 return session_handle & 0xFFFFFF;
3502}
3503
3504int
Florin Coras30e79c22019-01-02 19:31:22 -08003505vppcom_session_worker (vcl_session_handle_t session_handle)
3506{
3507 return session_handle >> 24;
3508}
3509
3510int
Florin Coras134a9962018-08-28 11:32:04 -07003511vppcom_worker_register (void)
3512{
Florin Coras47c40e22018-11-26 17:01:36 -08003513 if (!vcl_worker_alloc_and_init ())
3514 return VPPCOM_EEXIST;
3515
3516 if (vcl_worker_set_bapi ())
3517 return VPPCOM_EEXIST;
3518
3519 if (vcl_worker_register_with_vpp ())
3520 return VPPCOM_EEXIST;
3521
3522 return VPPCOM_OK;
Florin Coras99368312018-08-02 10:45:44 -07003523}
3524
Florin Corasdfe4cf42018-11-28 22:13:45 -08003525int
3526vppcom_worker_index (void)
3527{
3528 return vcl_get_worker_index ();
3529}
3530
Florin Corase0982e52019-01-25 13:19:56 -08003531int
3532vppcom_worker_mqs_epfd (void)
3533{
3534 vcl_worker_t *wrk = vcl_worker_get_current ();
3535 if (!vcm->cfg.use_mq_eventfd)
3536 return -1;
3537 return wrk->mqs_epfd;
3538}
3539
Dave Wallacee22aa742017-10-20 12:30:38 -04003540/*
3541 * fd.io coding-style-patch-verification: ON
3542 *
3543 * Local Variables:
3544 * eval: (c-set-style "gnu")
3545 * End:
3546 */