blob: 2c2cb2c186bbbff3dcb65a8c799e0b9708d5893b [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)
33 return 1;
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
508 if (session->is_dgram)
509 {
510 svm_fifo_t *rx_fifo, *tx_fifo;
511 session->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
512 rx_fifo = uword_to_pointer (mp->rx_fifo, svm_fifo_t *);
513 rx_fifo->client_session_index = sid;
514 tx_fifo = uword_to_pointer (mp->tx_fifo, svm_fifo_t *);
515 tx_fifo->client_session_index = sid;
516 session->rx_fifo = rx_fifo;
517 session->tx_fifo = tx_fifo;
518 }
519
Florin Coras05ecfcc2018-12-12 18:19:39 -0800520 VDBG (0, "session %u [0x%llx]: listen succeeded!", sid, mp->handle);
Florin Coras60116992018-08-27 09:52:18 -0700521 return sid;
522}
523
Florin Coras3c7d4f92018-12-14 11:28:43 -0800524static vcl_session_t *
525vcl_session_accepted (vcl_worker_t * wrk, session_accepted_msg_t * msg)
526{
527 vcl_session_msg_t *vcl_msg;
528 vcl_session_t *session;
529
530 session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
531 if (PREDICT_FALSE (session != 0))
Florin Corasb0f662f2018-12-27 14:51:46 -0800532 VWRN ("session overlap handle %lu state %u!", msg->handle,
533 session->session_state);
Florin Coras3c7d4f92018-12-14 11:28:43 -0800534
535 session = vcl_session_table_lookup_listener (wrk, msg->listener_handle);
536 if (!session)
537 {
538 VERR ("couldn't find listen session: listener handle %llx",
539 msg->listener_handle);
540 return 0;
541 }
542
543 clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
544 vcl_msg->accepted_msg = *msg;
545 /* Session handle points to listener until fully accepted by app */
546 vcl_session_table_add_vpp_handle (wrk, msg->handle, session->session_index);
547
548 return session;
549}
550
551static vcl_session_t *
552vcl_session_disconnected_handler (vcl_worker_t * wrk,
553 session_disconnected_msg_t * msg)
554{
555 vcl_session_t *session;
556
557 session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
558 if (!session)
559 {
560 VDBG (0, "request to disconnect unknown handle 0x%llx", msg->handle);
561 return 0;
562 }
563
564 /* Caught a disconnect before actually accepting the session */
565 if (session->session_state == STATE_LISTEN)
566 {
Florin Coras3c7d4f92018-12-14 11:28:43 -0800567 if (!vcl_flag_accepted_session (session, msg->handle,
568 VCL_ACCEPTED_F_CLOSED))
569 VDBG (0, "session was not accepted!");
570 return 0;
571 }
572
573 session->session_state = STATE_VPP_CLOSING;
574 return session;
575}
576
Florin Coras30e79c22019-01-02 19:31:22 -0800577static void
578vcl_session_req_worker_update_handler (vcl_worker_t * wrk, void *data)
579{
580 session_req_worker_update_msg_t *msg;
581 vcl_session_t *s;
582
583 msg = (session_req_worker_update_msg_t *) data;
584 s = vcl_session_get_w_vpp_handle (wrk, msg->session_handle);
585 if (!s)
586 return;
587
588 vec_add1 (wrk->pending_session_wrk_updates, s->session_index);
589}
590
591static void
592vcl_session_worker_update_reply_handler (vcl_worker_t * wrk, void *data)
593{
594 session_worker_update_reply_msg_t *msg;
595 vcl_session_t *s;
596
597 msg = (session_worker_update_reply_msg_t *) data;
598 s = vcl_session_get_w_vpp_handle (wrk, msg->handle);
599 if (!s)
600 {
601 VDBG (0, "unknown handle 0x%llx", msg->handle);
602 return;
603 }
604 if (vcl_wait_for_segment (msg->segment_handle))
605 {
606 clib_warning ("segment for session %u couldn't be mounted!",
607 s->session_index);
608 return;
609 }
610 s->rx_fifo = uword_to_pointer (msg->rx_fifo, svm_fifo_t *);
611 s->tx_fifo = uword_to_pointer (msg->tx_fifo, svm_fifo_t *);
612
613 s->rx_fifo->client_session_index = s->session_index;
614 s->tx_fifo->client_session_index = s->session_index;
615 s->rx_fifo->client_thread_index = wrk->wrk_index;
616 s->tx_fifo->client_thread_index = wrk->wrk_index;
617 s->session_state = STATE_UPDATED;
618
619 if (s->shared_index != VCL_INVALID_SESSION_INDEX)
620 {
621 vcl_shared_session_t *ss;
622 ss = vcl_shared_session_get (s->shared_index);
623 if (vec_len (ss->workers) > 1)
624 VDBG (0, "workers need to be updated");
625 }
626 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
744static void
745vcl_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 Coras053a0e42018-11-13 15:52:38 -0800875static void
876vcl_cleanup_bapi (void)
877{
Florin Coras47c40e22018-11-26 17:01:36 -0800878 socket_client_main_t *scm = &socket_client_main;
Florin Coras053a0e42018-11-13 15:52:38 -0800879 api_main_t *am = &api_main;
880
881 am->my_client_index = ~0;
882 am->my_registration = 0;
883 am->vl_input_queue = 0;
884 am->msg_index_by_name_and_crc = 0;
Florin Coras47c40e22018-11-26 17:01:36 -0800885 scm->socket_fd = 0;
Florin Coras053a0e42018-11-13 15:52:38 -0800886
887 vl_client_api_unmap ();
888}
889
Florin Coras01f3f892018-12-02 12:45:53 -0800890static void
891vcl_cleanup_forked_child (vcl_worker_t * wrk, vcl_worker_t * child_wrk)
892{
893 vcl_worker_t *sub_child;
894 int tries = 0;
895
896 if (child_wrk->forked_child != ~0)
897 {
898 sub_child = vcl_worker_get_if_valid (child_wrk->forked_child);
899 if (sub_child)
900 {
901 /* Wait a bit, maybe the process is going away */
902 while (kill (sub_child->current_pid, 0) >= 0 && tries++ < 50)
903 usleep (1e3);
904 if (kill (sub_child->current_pid, 0) < 0)
905 vcl_cleanup_forked_child (child_wrk, sub_child);
906 }
907 }
908 vcl_worker_cleanup (child_wrk, 1 /* notify vpp */ );
909 VDBG (0, "Cleaned up wrk %u", child_wrk->wrk_index);
910 wrk->forked_child = ~0;
911}
912
913static struct sigaction old_sa;
914
915static void
916vcl_intercept_sigchld_handler (int signum, siginfo_t * si, void *uc)
917{
918 vcl_worker_t *wrk, *child_wrk;
919
920 if (vcl_get_worker_index () == ~0)
921 return;
922
Florin Corasc227e492018-12-21 19:28:34 -0800923 if (sigaction (SIGCHLD, &old_sa, 0))
924 {
925 VERR ("couldn't restore sigchld");
926 exit (-1);
927 }
Florin Coras01f3f892018-12-02 12:45:53 -0800928
929 wrk = vcl_worker_get_current ();
930 if (wrk->forked_child == ~0)
931 return;
932
933 child_wrk = vcl_worker_get_if_valid (wrk->forked_child);
Florin Coraseaec2a62018-12-04 16:34:05 -0800934 if (!child_wrk)
935 goto done;
936
937 if (si && si->si_pid != child_wrk->current_pid)
Florin Coras01f3f892018-12-02 12:45:53 -0800938 {
939 VDBG (0, "unexpected child pid %u", si->si_pid);
Florin Coraseaec2a62018-12-04 16:34:05 -0800940 goto done;
Florin Coras01f3f892018-12-02 12:45:53 -0800941 }
Florin Coraseaec2a62018-12-04 16:34:05 -0800942 vcl_cleanup_forked_child (wrk, child_wrk);
Florin Coras01f3f892018-12-02 12:45:53 -0800943
Florin Coraseaec2a62018-12-04 16:34:05 -0800944done:
Florin Coras01f3f892018-12-02 12:45:53 -0800945 if (old_sa.sa_flags & SA_SIGINFO)
946 {
947 void (*fn) (int, siginfo_t *, void *) = old_sa.sa_sigaction;
948 fn (signum, si, uc);
949 }
950 else
951 {
952 void (*fn) (int) = old_sa.sa_handler;
953 if (fn)
954 fn (signum);
955 }
956}
957
958static void
959vcl_incercept_sigchld ()
960{
961 struct sigaction sa;
962 clib_memset (&sa, 0, sizeof (sa));
963 sa.sa_sigaction = vcl_intercept_sigchld_handler;
964 sa.sa_flags = SA_SIGINFO;
965 if (sigaction (SIGCHLD, &sa, &old_sa))
966 {
967 VERR ("couldn't intercept sigchld");
968 exit (-1);
969 }
970}
971
972static void
973vcl_app_pre_fork (void)
974{
975 vcl_incercept_sigchld ();
Florin Coras30e79c22019-01-02 19:31:22 -0800976 vcl_flush_mq_events ();
Florin Coras01f3f892018-12-02 12:45:53 -0800977}
978
979static void
Florin Coras053a0e42018-11-13 15:52:38 -0800980vcl_app_fork_child_handler (void)
981{
Florin Coras30e79c22019-01-02 19:31:22 -0800982 vcl_worker_t *parent_wrk, *wrk;
Florin Coras01f3f892018-12-02 12:45:53 -0800983 int rv, parent_wrk_index;
Florin Coras053a0e42018-11-13 15:52:38 -0800984 u8 *child_name;
Florin Coras053a0e42018-11-13 15:52:38 -0800985
Florin Coras01f3f892018-12-02 12:45:53 -0800986 parent_wrk_index = vcl_get_worker_index ();
987 VDBG (0, "initializing forked child with parent wrk %u", parent_wrk_index);
Florin Coras053a0e42018-11-13 15:52:38 -0800988
Florin Coras47c40e22018-11-26 17:01:36 -0800989 /*
990 * Allocate worker
991 */
Florin Coras47c40e22018-11-26 17:01:36 -0800992 vcl_set_worker_index (~0);
993 if (!vcl_worker_alloc_and_init ())
994 VERR ("couldn't allocate new worker");
995
996 /*
997 * Attach to binary api
998 */
999 child_name = format (0, "%v-child-%u%c", vcm->app_name, getpid (), 0);
Florin Coras053a0e42018-11-13 15:52:38 -08001000 vcl_cleanup_bapi ();
1001 vppcom_api_hookup ();
1002 vcm->app_state = STATE_APP_START;
1003 rv = vppcom_connect_to_vpp ((char *) child_name);
1004 vec_free (child_name);
1005 if (rv)
1006 {
1007 VERR ("couldn't connect to VPP!");
1008 return;
1009 }
1010
Florin Coras47c40e22018-11-26 17:01:36 -08001011 /*
1012 * Register worker with vpp and share sessions
1013 */
1014 vcl_worker_register_with_vpp ();
Florin Coras01f3f892018-12-02 12:45:53 -08001015 parent_wrk = vcl_worker_get (parent_wrk_index);
Florin Coras30e79c22019-01-02 19:31:22 -08001016 wrk = vcl_worker_get_current ();
1017 wrk->vpp_event_queues = vec_dup (parent_wrk->vpp_event_queues);
Florin Coras47c40e22018-11-26 17:01:36 -08001018 vcl_worker_share_sessions (parent_wrk);
Florin Coras01f3f892018-12-02 12:45:53 -08001019 parent_wrk->forked_child = vcl_get_worker_index ();
Florin Coras47c40e22018-11-26 17:01:36 -08001020
Florin Coras053a0e42018-11-13 15:52:38 -08001021 VDBG (0, "forked child main worker initialized");
Florin Coras47c40e22018-11-26 17:01:36 -08001022 vcm->forking = 0;
1023}
1024
Florin Coras01f3f892018-12-02 12:45:53 -08001025static void
Florin Coras47c40e22018-11-26 17:01:36 -08001026vcl_app_fork_parent_handler (void)
1027{
1028 vcm->forking = 1;
Florin Coras47c40e22018-11-26 17:01:36 -08001029 while (vcm->forking)
1030 ;
Florin Coras053a0e42018-11-13 15:52:38 -08001031}
1032
Florin Coras940f78f2018-11-30 12:11:20 -08001033/**
1034 * Handle app exit
1035 *
1036 * Notify vpp of the disconnect and mark the worker as free. If we're the
1037 * last worker, do a full cleanup otherwise, since we're probably a forked
1038 * child, avoid syscalls as much as possible. We might've lost privileges.
1039 */
1040void
1041vppcom_app_exit (void)
1042{
1043 if (!pool_elts (vcm->workers))
1044 return;
Florin Coras01f3f892018-12-02 12:45:53 -08001045 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
1046 vcl_set_worker_index (~0);
Florin Coras940f78f2018-11-30 12:11:20 -08001047 vcl_elog_stop (vcm);
1048 if (vec_len (vcm->workers) == 1)
1049 vl_client_disconnect_from_vlib ();
1050 else
Florin Coraseaec2a62018-12-04 16:34:05 -08001051 vl_client_send_disconnect (1 /* vpp should cleanup */ );
Florin Coras940f78f2018-11-30 12:11:20 -08001052}
1053
Dave Wallace543852a2017-08-03 02:11:34 -04001054/*
1055 * VPPCOM Public API functions
1056 */
1057int
1058vppcom_app_create (char *app_name)
1059{
Dave Wallace543852a2017-08-03 02:11:34 -04001060 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
Dave Wallace543852a2017-08-03 02:11:34 -04001061 int rv;
1062
Florin Coras47c40e22018-11-26 17:01:36 -08001063 if (vcm->is_init)
Dave Wallace543852a2017-08-03 02:11:34 -04001064 {
Florin Coras955bfbb2018-12-04 13:43:45 -08001065 VDBG (1, "already initialized");
1066 return VPPCOM_EEXIST;
Dave Wallace543852a2017-08-03 02:11:34 -04001067 }
1068
Florin Coras47c40e22018-11-26 17:01:36 -08001069 vcm->is_init = 1;
1070 vppcom_cfg (&vcm->cfg);
1071 vcl_cfg = &vcm->cfg;
1072
1073 vcm->main_cpu = pthread_self ();
1074 vcm->main_pid = getpid ();
1075 vcm->app_name = format (0, "%s", app_name);
1076 vppcom_init_error_string_table ();
Florin Corasadc74d72018-12-02 13:36:00 -08001077 svm_fifo_segment_main_init (&vcm->segment_main, vcl_cfg->segment_baseva,
Florin Coras47c40e22018-11-26 17:01:36 -08001078 20 /* timeout in secs */ );
1079 pool_alloc (vcm->workers, vcl_cfg->max_workers);
1080 clib_spinlock_init (&vcm->workers_lock);
Florin Corasd85de682018-11-29 17:02:29 -08001081 clib_rwlock_init (&vcm->segment_table_lock);
Florin Coras01f3f892018-12-02 12:45:53 -08001082 pthread_atfork (vcl_app_pre_fork, vcl_app_fork_parent_handler,
Florin Coras47c40e22018-11-26 17:01:36 -08001083 vcl_app_fork_child_handler);
Florin Coras940f78f2018-11-30 12:11:20 -08001084 atexit (vppcom_app_exit);
Florin Coras47c40e22018-11-26 17:01:36 -08001085
1086 /* Allocate default worker */
1087 vcl_worker_alloc_and_init ();
1088
1089 /* API hookup and connect to VPP */
1090 vppcom_api_hookup ();
1091 vcl_elog_init (vcm);
1092 vcm->app_state = STATE_APP_START;
1093 rv = vppcom_connect_to_vpp (app_name);
1094 if (rv)
Dave Wallace543852a2017-08-03 02:11:34 -04001095 {
Florin Coras47c40e22018-11-26 17:01:36 -08001096 VERR ("couldn't connect to VPP!");
1097 return rv;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001098 }
Florin Coras47c40e22018-11-26 17:01:36 -08001099 VDBG (0, "sending session enable");
1100 rv = vppcom_app_session_enable ();
1101 if (rv)
1102 {
1103 VERR ("vppcom_app_session_enable() failed!");
1104 return rv;
1105 }
1106
1107 VDBG (0, "sending app attach");
1108 rv = vppcom_app_attach ();
1109 if (rv)
1110 {
1111 VERR ("vppcom_app_attach() failed!");
1112 return rv;
1113 }
1114
1115 VDBG (0, "app_name '%s', my_client_index %d (0x%x)", app_name,
1116 vcm->workers[0].my_client_index, vcm->workers[0].my_client_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001117
1118 return VPPCOM_OK;
1119}
1120
1121void
1122vppcom_app_destroy (void)
1123{
Dave Wallace543852a2017-08-03 02:11:34 -04001124 int rv;
Dave Wallacede910062018-03-20 09:22:13 -04001125 f64 orig_app_timeout;
Dave Wallace543852a2017-08-03 02:11:34 -04001126
Florin Coras940f78f2018-11-30 12:11:20 -08001127 if (!pool_elts (vcm->workers))
1128 return;
1129
Florin Coras0d427d82018-06-27 03:24:07 -07001130 vcl_evt (VCL_EVT_DETACH, vcm);
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -08001131
Florin Coras940f78f2018-11-30 12:11:20 -08001132 if (pool_elts (vcm->workers) == 1)
Florin Coras47c40e22018-11-26 17:01:36 -08001133 {
1134 vppcom_app_send_detach ();
1135 orig_app_timeout = vcm->cfg.app_timeout;
1136 vcm->cfg.app_timeout = 2.0;
1137 rv = vcl_wait_for_app_state_change (STATE_APP_ENABLED);
1138 vcm->cfg.app_timeout = orig_app_timeout;
1139 if (PREDICT_FALSE (rv))
1140 VDBG (0, "application detach timed out! returning %d (%s)", rv,
1141 vppcom_retval_str (rv));
Florin Coras940f78f2018-11-30 12:11:20 -08001142 vec_free (vcm->app_name);
Florin Coras01f3f892018-12-02 12:45:53 -08001143 vcl_worker_cleanup (vcl_worker_get_current (), 0 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -08001144 }
1145 else
1146 {
Florin Coras01f3f892018-12-02 12:45:53 -08001147 vcl_worker_cleanup (vcl_worker_get_current (), 1 /* notify vpp */ );
Florin Coras47c40e22018-11-26 17:01:36 -08001148 }
Keith Burns (alagalah)8aa9aaf2018-01-05 12:16:22 -08001149
Florin Coras01f3f892018-12-02 12:45:53 -08001150 vcl_set_worker_index (~0);
Florin Coras0d427d82018-06-27 03:24:07 -07001151 vcl_elog_stop (vcm);
Dave Wallace543852a2017-08-03 02:11:34 -04001152 vl_client_disconnect_from_vlib ();
Dave Wallace543852a2017-08-03 02:11:34 -04001153}
1154
1155int
Dave Wallacec04cbf12018-02-07 18:14:02 -05001156vppcom_session_create (u8 proto, u8 is_nonblocking)
Dave Wallace543852a2017-08-03 02:11:34 -04001157{
Florin Coras134a9962018-08-28 11:32:04 -07001158 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001159 vcl_session_t *session;
Dave Wallace543852a2017-08-03 02:11:34 -04001160
Florin Coras134a9962018-08-28 11:32:04 -07001161 session = vcl_session_alloc (wrk);
Dave Wallace543852a2017-08-03 02:11:34 -04001162
Florin Coras7e12d942018-06-27 14:32:43 -07001163 session->session_type = proto;
1164 session->session_state = STATE_START;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001165 session->vpp_handle = ~0;
Florin Coras460dce62018-07-27 05:45:06 -07001166 session->is_dgram = proto == VPPCOM_PROTO_UDP;
Dave Wallace543852a2017-08-03 02:11:34 -04001167
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001168 if (is_nonblocking)
1169 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
Dave Wallace543852a2017-08-03 02:11:34 -04001170
Florin Coras7e12d942018-06-27 14:32:43 -07001171 vcl_evt (VCL_EVT_CREATE, session, session_type, session->session_state,
1172 is_nonblocking, session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001173
Florin Coras053a0e42018-11-13 15:52:38 -08001174 VDBG (0, "created sid %u", session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001175
Florin Coras134a9962018-08-28 11:32:04 -07001176 return vcl_session_handle (session);
Dave Wallace543852a2017-08-03 02:11:34 -04001177}
1178
1179int
Florin Coras134a9962018-08-28 11:32:04 -07001180vppcom_session_close (uint32_t session_handle)
Dave Wallace543852a2017-08-03 02:11:34 -04001181{
Florin Coras134a9962018-08-28 11:32:04 -07001182 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras47c40e22018-11-26 17:01:36 -08001183 u8 is_vep, do_disconnect = 1;
Florin Coras7e12d942018-06-27 14:32:43 -07001184 vcl_session_t *session = 0;
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001185 session_state_t state;
Florin Coras134a9962018-08-28 11:32:04 -07001186 u32 next_sh, vep_sh;
1187 int rv = VPPCOM_OK;
1188 u64 vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -04001189
Florin Coras134a9962018-08-28 11:32:04 -07001190 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001191 if (!session)
1192 return VPPCOM_EBADFD;
1193
Florin Coras47c40e22018-11-26 17:01:36 -08001194 if (session->shared_index != ~0)
1195 do_disconnect = vcl_worker_unshare_session (wrk, session);
1196
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001197 is_vep = session->is_vep;
Florin Coras134a9962018-08-28 11:32:04 -07001198 next_sh = session->vep.next_sh;
1199 vep_sh = session->vep.vep_sh;
Florin Coras7e12d942018-06-27 14:32:43 -07001200 state = session->session_state;
Dave Wallaceee45d412017-11-24 21:44:06 -05001201 vpp_handle = session->vpp_handle;
Dave Wallace543852a2017-08-03 02:11:34 -04001202
Florin Coras05ecfcc2018-12-12 18:19:39 -08001203 VDBG (1, "closing session handle %u vpp handle %u", session_handle,
Florin Coras47c40e22018-11-26 17:01:36 -08001204 vpp_handle);
Dave Wallace543852a2017-08-03 02:11:34 -04001205
Dave Wallace66cf6eb2017-10-26 02:51:07 -04001206 if (is_vep)
Dave Wallace543852a2017-08-03 02:11:34 -04001207 {
Florin Coras134a9962018-08-28 11:32:04 -07001208 while (next_sh != ~0)
Dave Wallace19481612017-09-15 18:47:44 -04001209 {
Florin Coras134a9962018-08-28 11:32:04 -07001210 rv = vppcom_epoll_ctl (session_handle, EPOLL_CTL_DEL, next_sh, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001211 if (PREDICT_FALSE (rv < 0))
Florin Coras47c40e22018-11-26 17:01:36 -08001212 VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u"
1213 " failed! rv %d (%s)", vpp_handle, next_sh, vep_sh, rv,
1214 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001215
Florin Coras134a9962018-08-28 11:32:04 -07001216 next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001217 }
1218 }
1219 else
1220 {
Florin Coras47c40e22018-11-26 17:01:36 -08001221 if (session->is_vep_session)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001222 {
Florin Coras134a9962018-08-28 11:32:04 -07001223 rv = vppcom_epoll_ctl (vep_sh, EPOLL_CTL_DEL, session_handle, 0);
Florin Coras0d427d82018-06-27 03:24:07 -07001224 if (rv < 0)
Florin Coras47c40e22018-11-26 17:01:36 -08001225 VDBG (0, "vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL vep_idx %u "
1226 "failed! rv %d (%s)", vpp_handle, session_handle, vep_sh,
1227 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001228 }
1229
Florin Coras47c40e22018-11-26 17:01:36 -08001230 if (!do_disconnect)
Florin Coras30e79c22019-01-02 19:31:22 -08001231 {
1232 VDBG (0, "session handle %u [0x%llx] disconnect skipped",
1233 session_handle, vpp_handle);
1234 goto cleanup;
1235 }
Florin Coras47c40e22018-11-26 17:01:36 -08001236
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001237 if (state & STATE_LISTEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001238 {
Florin Coras134a9962018-08-28 11:32:04 -07001239 rv = vppcom_session_unbind (session_handle);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001240 if (PREDICT_FALSE (rv < 0))
Florin Coras47c40e22018-11-26 17:01:36 -08001241 VDBG (0, "vpp handle 0x%llx, sid %u: listener unbind failed! "
1242 "rv %d (%s)", vpp_handle, session_handle, rv,
1243 vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001244 }
Florin Coras070453d2018-08-24 17:04:27 -07001245 else if (state & STATE_OPEN)
Dave Wallacef7f809c2017-10-03 01:48:42 -04001246 {
Florin Coras134a9962018-08-28 11:32:04 -07001247 rv = vppcom_session_disconnect (session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001248 if (PREDICT_FALSE (rv < 0))
Dave Wallace048b1d62018-01-03 22:24:41 -05001249 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001250 "session disconnect failed! rv %d (%s)",
Florin Coras134a9962018-08-28 11:32:04 -07001251 getpid (), vpp_handle, session_handle,
Dave Wallaceee45d412017-11-24 21:44:06 -05001252 rv, vppcom_retval_str (rv));
Dave Wallacef7f809c2017-10-03 01:48:42 -04001253 }
Florin Corasb0f662f2018-12-27 14:51:46 -08001254 else if (state == STATE_DISCONNECT)
1255 {
1256 svm_msg_q_t *mq = vcl_session_vpp_evt_q (wrk, session);
1257 vcl_send_session_reset_reply (mq, wrk->my_client_index,
1258 session->vpp_handle, 0);
1259 }
Dave Wallace19481612017-09-15 18:47:44 -04001260 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05001261
Florin Coras47c40e22018-11-26 17:01:36 -08001262cleanup:
1263
Florin Coras99368312018-08-02 10:45:44 -07001264 if (vcl_session_is_ct (session))
1265 {
1266 vcl_cut_through_registration_t *ctr;
1267 uword mq_addr;
1268
1269 mq_addr = pointer_to_uword (session->our_evt_q);
Florin Coras134a9962018-08-28 11:32:04 -07001270 ctr = vcl_ct_registration_lock_and_lookup (wrk, mq_addr);
Florin Coras99368312018-08-02 10:45:44 -07001271 ASSERT (ctr);
1272 if (ctr->epoll_evt_conn_index != ~0)
Florin Coras134a9962018-08-28 11:32:04 -07001273 vcl_mq_epoll_del_evfd (wrk, ctr->epoll_evt_conn_index);
Florin Coras99368312018-08-02 10:45:44 -07001274 VDBG (0, "Removing ct registration %u",
Florin Coras134a9962018-08-28 11:32:04 -07001275 vcl_ct_registration_index (wrk, ctr));
1276 vcl_ct_registration_del (wrk, ctr);
1277 vcl_ct_registration_lookup_del (wrk, mq_addr);
1278 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07001279 }
Florin Coras54693d22018-07-17 10:46:29 -07001280
Florin Coras30e79c22019-01-02 19:31:22 -08001281 vcl_session_table_del_vpp_handle (wrk, vpp_handle);
Florin Coras134a9962018-08-28 11:32:04 -07001282 vcl_session_free (wrk, session);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001283
Florin Coras05ecfcc2018-12-12 18:19:39 -08001284 VDBG (0, "session handle %u [0x%llx] removed", session_handle, vpp_handle);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001285
Florin Coras0d427d82018-06-27 03:24:07 -07001286 vcl_evt (VCL_EVT_CLOSE, session, rv);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08001287
Dave Wallace543852a2017-08-03 02:11:34 -04001288 return rv;
1289}
1290
1291int
Florin Coras134a9962018-08-28 11:32:04 -07001292vppcom_session_bind (uint32_t session_handle, vppcom_endpt_t * ep)
Dave Wallace543852a2017-08-03 02:11:34 -04001293{
Florin Coras134a9962018-08-28 11:32:04 -07001294 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001295 vcl_session_t *session = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001296
1297 if (!ep || !ep->ip)
1298 return VPPCOM_EINVAL;
1299
Florin Coras134a9962018-08-28 11:32:04 -07001300 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001301 if (!session)
1302 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001303
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001304 if (session->is_vep)
1305 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001306 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
Florin Coras134a9962018-08-28 11:32:04 -07001307 "bind to an epoll session!", getpid (), session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001308 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001309 }
1310
Florin Coras7e12d942018-06-27 14:32:43 -07001311 session->transport.is_ip4 = ep->is_ip4;
Florin Coras54693d22018-07-17 10:46:29 -07001312 if (ep->is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001313 clib_memcpy_fast (&session->transport.lcl_ip.ip4, ep->ip,
1314 sizeof (ip4_address_t));
Florin Coras54693d22018-07-17 10:46:29 -07001315 else
Dave Barach178cf492018-11-13 16:34:13 -05001316 clib_memcpy_fast (&session->transport.lcl_ip.ip6, ep->ip,
1317 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001318 session->transport.lcl_port = ep->port;
Stevenac1f96d2017-10-24 16:03:58 -07001319
Florin Coras0d427d82018-06-27 03:24:07 -07001320 VDBG (0, "VCL<%d>: sid %u: binding to local %s address %U port %u, "
Florin Coras134a9962018-08-28 11:32:04 -07001321 "proto %s", getpid (), session_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001322 session->transport.is_ip4 ? "IPv4" : "IPv6",
1323 format_ip46_address, &session->transport.lcl_ip,
1324 session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
1325 clib_net_to_host_u16 (session->transport.lcl_port),
Ping Yu34a3a082018-11-30 19:16:17 -05001326 vppcom_proto_str (session->session_type));
Florin Coras0d427d82018-06-27 03:24:07 -07001327 vcl_evt (VCL_EVT_BIND, session);
Florin Coras460dce62018-07-27 05:45:06 -07001328
1329 if (session->session_type == VPPCOM_PROTO_UDP)
Florin Coras134a9962018-08-28 11:32:04 -07001330 vppcom_session_listen (session_handle, 10);
Florin Coras460dce62018-07-27 05:45:06 -07001331
Florin Coras070453d2018-08-24 17:04:27 -07001332 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001333}
1334
1335int
Florin Coras134a9962018-08-28 11:32:04 -07001336vppcom_session_listen (uint32_t listen_sh, uint32_t q_len)
Dave Wallace543852a2017-08-03 02:11:34 -04001337{
Florin Coras134a9962018-08-28 11:32:04 -07001338 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001339 vcl_session_t *listen_session = 0;
Dave Wallaceee45d412017-11-24 21:44:06 -05001340 u64 listen_vpp_handle;
Florin Coras070453d2018-08-24 17:04:27 -07001341 int rv;
1342
Florin Coras134a9962018-08-28 11:32:04 -07001343 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001344 if (!listen_session || listen_session->is_vep)
Florin Coras070453d2018-08-24 17:04:27 -07001345 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001346
Keith Burns (alagalah)aba98de2018-02-22 03:23:40 -08001347 if (q_len == 0 || q_len == ~0)
1348 q_len = vcm->cfg.listen_queue_size;
1349
Dave Wallaceee45d412017-11-24 21:44:06 -05001350 listen_vpp_handle = listen_session->vpp_handle;
Florin Coras7e12d942018-06-27 14:32:43 -07001351 if (listen_session->session_state & STATE_LISTEN)
Dave Wallacee695cb42017-11-02 22:04:42 -04001352 {
Florin Coras05ecfcc2018-12-12 18:19:39 -08001353 VDBG (0, "session %u [0x%llx]: already in listen state!",
1354 listen_sh, listen_vpp_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001355 return VPPCOM_OK;
Dave Wallacee695cb42017-11-02 22:04:42 -04001356 }
1357
Florin Coras05ecfcc2018-12-12 18:19:39 -08001358 VDBG (0, "session %u [0x%llx]: sending vpp listen request...",
1359 listen_sh, listen_vpp_handle);
Dave Wallace543852a2017-08-03 02:11:34 -04001360
Florin Coras070453d2018-08-24 17:04:27 -07001361 /*
1362 * Send listen request to vpp and wait for reply
1363 */
Florin Coras134a9962018-08-28 11:32:04 -07001364 vppcom_send_bind_sock (listen_session);
1365 rv = vppcom_wait_for_session_state_change (listen_session->session_index,
1366 STATE_LISTEN,
1367 vcm->cfg.session_timeout);
Dave Wallace543852a2017-08-03 02:11:34 -04001368
Florin Coras070453d2018-08-24 17:04:27 -07001369 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001370 {
Florin Coras134a9962018-08-28 11:32:04 -07001371 listen_session = vcl_session_get_w_handle (wrk, listen_sh);
Florin Coras05ecfcc2018-12-12 18:19:39 -08001372 VDBG (0, "session %u [0x%llx]: listen failed! returning %d (%s)",
1373 listen_sh, listen_session->vpp_handle, rv,
1374 vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001375 return rv;
Dave Wallaceee45d412017-11-24 21:44:06 -05001376 }
1377
Florin Coras070453d2018-08-24 17:04:27 -07001378 return VPPCOM_OK;
Keith Burns (alagalah)0d2b0d52018-03-06 15:55:22 -08001379}
1380
Ping Yu34a3a082018-11-30 19:16:17 -05001381int
1382vppcom_session_tls_add_cert (uint32_t session_handle, char *cert,
1383 uint32_t cert_len)
1384{
1385
1386 vcl_worker_t *wrk = vcl_worker_get_current ();
1387 vcl_session_t *session = 0;
1388
1389 session = vcl_session_get_w_handle (wrk, session_handle);
1390 if (!session)
1391 return VPPCOM_EBADFD;
1392
1393 if (cert_len == 0 || cert_len == ~0)
1394 return VPPCOM_EBADFD;
1395
1396 /*
1397 * Send listen request to vpp and wait for reply
1398 */
1399 vppcom_send_application_tls_cert_add (session, cert, cert_len);
1400
1401 return VPPCOM_OK;
1402
1403}
1404
1405int
1406vppcom_session_tls_add_key (uint32_t session_handle, char *key,
1407 uint32_t key_len)
1408{
1409
1410 vcl_worker_t *wrk = vcl_worker_get_current ();
1411 vcl_session_t *session = 0;
1412
1413 session = vcl_session_get_w_handle (wrk, session_handle);
1414 if (!session)
1415 return VPPCOM_EBADFD;
1416
1417 if (key_len == 0 || key_len == ~0)
1418 return VPPCOM_EBADFD;
1419
1420 /*
1421 * Send listen request to vpp and wait for reply
1422 */
1423 vppcom_send_application_tls_key_add (session, key, key_len);
1424
1425 return VPPCOM_OK;
1426
1427
1428}
1429
Florin Coras134a9962018-08-28 11:32:04 -07001430static int
1431validate_args_session_accept_ (vcl_worker_t * wrk,
1432 vcl_session_t * listen_session)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001433{
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001434 /* Input validation - expects spinlock on sessions_lockp */
1435 if (listen_session->is_vep)
1436 {
1437 clib_warning ("VCL<%d>: ERROR: sid %u: cannot accept on an "
Florin Coras134a9962018-08-28 11:32:04 -07001438 "epoll session!", getpid (),
1439 listen_session->session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001440 return VPPCOM_EBADFD;
1441 }
1442
Florin Coras7e12d942018-06-27 14:32:43 -07001443 if (listen_session->session_state != STATE_LISTEN)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001444 {
1445 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
1446 "not in listen state! state 0x%x (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001447 listen_session->vpp_handle, listen_session->session_index,
Florin Coras7e12d942018-06-27 14:32:43 -07001448 listen_session->session_state,
1449 vppcom_session_state_str (listen_session->session_state));
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001450 return VPPCOM_EBADFD;
1451 }
1452 return VPPCOM_OK;
1453}
1454
1455int
Florin Coras134a9962018-08-28 11:32:04 -07001456vppcom_session_accept (uint32_t listen_session_handle, vppcom_endpt_t * ep,
Dave Wallace048b1d62018-01-03 22:24:41 -05001457 uint32_t flags)
Dave Wallace543852a2017-08-03 02:11:34 -04001458{
Florin Coras3c7d4f92018-12-14 11:28:43 -08001459 u32 client_session_index = ~0, listen_session_index, accept_flags = 0;
Florin Coras134a9962018-08-28 11:32:04 -07001460 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001461 session_accepted_msg_t accepted_msg;
Florin Coras7e12d942018-06-27 14:32:43 -07001462 vcl_session_t *listen_session = 0;
1463 vcl_session_t *client_session = 0;
Florin Coras54693d22018-07-17 10:46:29 -07001464 svm_msg_q_t *vpp_evt_q;
1465 vcl_session_msg_t *evt;
Dave Wallaceee45d412017-11-24 21:44:06 -05001466 u64 listen_vpp_handle;
Florin Coras54693d22018-07-17 10:46:29 -07001467 svm_msg_q_msg_t msg;
1468 session_event_t *e;
1469 u8 is_nonblocking;
1470 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001471
Florin Coras134a9962018-08-28 11:32:04 -07001472 listen_session = vcl_session_get_w_handle (wrk, listen_session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001473 if (!listen_session)
1474 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001475
Florin Coras134a9962018-08-28 11:32:04 -07001476 listen_session_index = listen_session->session_index;
1477 if ((rv = validate_args_session_accept_ (wrk, listen_session)))
Florin Coras070453d2018-08-24 17:04:27 -07001478 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001479
Florin Coras54693d22018-07-17 10:46:29 -07001480 if (clib_fifo_elts (listen_session->accept_evts_fifo))
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001481 {
Florin Coras54693d22018-07-17 10:46:29 -07001482 clib_fifo_sub2 (listen_session->accept_evts_fifo, evt);
Florin Coras3c7d4f92018-12-14 11:28:43 -08001483 accept_flags = evt->flags;
Florin Coras54693d22018-07-17 10:46:29 -07001484 accepted_msg = evt->accepted_msg;
1485 goto handle;
1486 }
1487
1488 is_nonblocking = VCL_SESS_ATTR_TEST (listen_session->attr,
1489 VCL_SESS_ATTR_NONBLOCK);
Florin Coras134a9962018-08-28 11:32:04 -07001490 if (svm_msg_q_is_empty (wrk->app_event_queue) && is_nonblocking)
Florin Coras54693d22018-07-17 10:46:29 -07001491 return VPPCOM_EAGAIN;
1492
1493 while (1)
1494 {
Florin Coras134a9962018-08-28 11:32:04 -07001495 if (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_WAIT, 0))
Florin Coras54693d22018-07-17 10:46:29 -07001496 return VPPCOM_EAGAIN;
1497
Florin Coras134a9962018-08-28 11:32:04 -07001498 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001499 if (e->event_type != SESSION_CTRL_EVT_ACCEPTED)
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001500 {
Florin Coras54693d22018-07-17 10:46:29 -07001501 clib_warning ("discarded event: %u", e->event_type);
Florin Coras134a9962018-08-28 11:32:04 -07001502 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001503 continue;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001504 }
Dave Barach178cf492018-11-13 16:34:13 -05001505 clib_memcpy_fast (&accepted_msg, e->data, sizeof (accepted_msg));
Florin Coras134a9962018-08-28 11:32:04 -07001506 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
Florin Coras54693d22018-07-17 10:46:29 -07001507 break;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001508 }
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001509
Florin Coras54693d22018-07-17 10:46:29 -07001510handle:
Keith Burns (alagalah)00f44cc2018-03-07 09:26:38 -08001511
Florin Coras134a9962018-08-28 11:32:04 -07001512 client_session_index = vcl_session_accepted_handler (wrk, &accepted_msg);
1513 listen_session = vcl_session_get (wrk, listen_session_index);
1514 client_session = vcl_session_get (wrk, client_session_index);
Dave Wallace543852a2017-08-03 02:11:34 -04001515
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001516 if (flags & O_NONBLOCK)
1517 VCL_SESS_ATTR_SET (client_session->attr, VCL_SESS_ATTR_NONBLOCK);
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001518
Florin Coras54693d22018-07-17 10:46:29 -07001519 listen_vpp_handle = listen_session->vpp_handle;
Florin Coras05ecfcc2018-12-12 18:19:39 -08001520 VDBG (1, "vpp handle 0x%llx, sid %u: Got a client request! "
Florin Coras0d427d82018-06-27 03:24:07 -07001521 "vpp handle 0x%llx, sid %u, flags %d, is_nonblocking %u",
Florin Corasdc2e2512018-12-03 17:47:26 -08001522 listen_vpp_handle, listen_session_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001523 client_session->vpp_handle, client_session_index,
1524 flags, VCL_SESS_ATTR_TEST (client_session->attr,
1525 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace543852a2017-08-03 02:11:34 -04001526
Dave Wallace048b1d62018-01-03 22:24:41 -05001527 if (ep)
1528 {
Florin Coras7e12d942018-06-27 14:32:43 -07001529 ep->is_ip4 = client_session->transport.is_ip4;
1530 ep->port = client_session->transport.rmt_port;
1531 if (client_session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001532 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip4,
1533 sizeof (ip4_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001534 else
Dave Barach178cf492018-11-13 16:34:13 -05001535 clib_memcpy_fast (ep->ip, &client_session->transport.rmt_ip.ip6,
1536 sizeof (ip6_address_t));
Dave Wallace048b1d62018-01-03 22:24:41 -05001537 }
Dave Wallace60caa062017-11-10 17:07:13 -05001538
Florin Coras54693d22018-07-17 10:46:29 -07001539 if (accepted_msg.server_event_queue_address)
1540 vpp_evt_q = uword_to_pointer (accepted_msg.vpp_event_queue_address,
1541 svm_msg_q_t *);
1542 else
1543 vpp_evt_q = client_session->vpp_evt_q;
Florin Coras99368312018-08-02 10:45:44 -07001544
Florin Coras54693d22018-07-17 10:46:29 -07001545 vcl_send_session_accepted_reply (vpp_evt_q, client_session->client_context,
1546 client_session->vpp_handle, 0);
Dave Wallace60caa062017-11-10 17:07:13 -05001547
Florin Coras05ecfcc2018-12-12 18:19:39 -08001548 VDBG (0, "listener %u [0x%llx] accepted %u [0x%llx] peer: %U:%u "
1549 "local: %U:%u", listen_session_handle, listen_vpp_handle,
1550 client_session_index, client_session->vpp_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001551 format_ip46_address, &client_session->transport.rmt_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001552 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001553 clib_net_to_host_u16 (client_session->transport.rmt_port),
Florin Coras7e12d942018-06-27 14:32:43 -07001554 format_ip46_address, &client_session->transport.lcl_ip,
Florin Coras54693d22018-07-17 10:46:29 -07001555 client_session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001556 clib_net_to_host_u16 (client_session->transport.lcl_port));
Florin Coras0d427d82018-06-27 03:24:07 -07001557 vcl_evt (VCL_EVT_ACCEPT, client_session, listen_session,
1558 client_session_index);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001559
Florin Coras3c7d4f92018-12-14 11:28:43 -08001560 /*
1561 * Session might have been closed already
1562 */
1563 if (accept_flags)
1564 {
Florin Coras3c7d4f92018-12-14 11:28:43 -08001565 if (accept_flags & VCL_ACCEPTED_F_CLOSED)
Florin Corasb0f662f2018-12-27 14:51:46 -08001566 client_session->session_state = STATE_VPP_CLOSING;
Florin Coras3c7d4f92018-12-14 11:28:43 -08001567 else if (accept_flags & VCL_ACCEPTED_F_RESET)
Florin Corasb0f662f2018-12-27 14:51:46 -08001568 client_session->session_state = STATE_DISCONNECT;
Florin Coras3c7d4f92018-12-14 11:28:43 -08001569 }
Florin Corasab2f6db2018-08-31 14:31:41 -07001570 return vcl_session_handle (client_session);
Dave Wallace543852a2017-08-03 02:11:34 -04001571}
1572
1573int
Florin Coras134a9962018-08-28 11:32:04 -07001574vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep)
Dave Wallace543852a2017-08-03 02:11:34 -04001575{
Florin Coras134a9962018-08-28 11:32:04 -07001576 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07001577 vcl_session_t *session = 0;
Florin Coras134a9962018-08-28 11:32:04 -07001578 u32 session_index;
Florin Coras070453d2018-08-24 17:04:27 -07001579 int rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001580
Florin Coras134a9962018-08-28 11:32:04 -07001581 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001582 if (!session)
1583 return VPPCOM_EBADFD;
Florin Coras134a9962018-08-28 11:32:04 -07001584 session_index = session->session_index;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001585
1586 if (PREDICT_FALSE (session->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001587 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001588 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
Florin Coras134a9962018-08-28 11:32:04 -07001589 "connect on an epoll session!", getpid (),
1590 session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001591 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001592 }
1593
Florin Coras7e12d942018-06-27 14:32:43 -07001594 if (PREDICT_FALSE (session->session_state & CLIENT_STATE_OPEN))
Dave Wallace543852a2017-08-03 02:11:34 -04001595 {
Florin Coras7baeb712019-01-04 17:05:43 -08001596 VDBG (0, "session handle %u [0x%llx]: session already "
Florin Coras0d427d82018-06-27 03:24:07 -07001597 "connected to %s %U port %d proto %s, state 0x%x (%s)",
Florin Coras7baeb712019-01-04 17:05:43 -08001598 session_handle, session->vpp_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001599 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001600 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001601 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001602 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001603 clib_net_to_host_u16 (session->transport.rmt_port),
Ping Yu34a3a082018-11-30 19:16:17 -05001604 vppcom_proto_str (session->session_type), session->session_state,
Florin Coras7e12d942018-06-27 14:32:43 -07001605 vppcom_session_state_str (session->session_state));
Florin Coras070453d2018-08-24 17:04:27 -07001606 return VPPCOM_OK;
Dave Wallace543852a2017-08-03 02:11:34 -04001607 }
1608
Florin Coras7e12d942018-06-27 14:32:43 -07001609 session->transport.is_ip4 = server_ep->is_ip4;
1610 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05001611 clib_memcpy_fast (&session->transport.rmt_ip.ip4, server_ep->ip,
1612 sizeof (ip4_address_t));
Dave Wallaced239f8d2018-06-19 13:37:30 -04001613 else
Dave Barach178cf492018-11-13 16:34:13 -05001614 clib_memcpy_fast (&session->transport.rmt_ip.ip6, server_ep->ip,
1615 sizeof (ip6_address_t));
Florin Coras7e12d942018-06-27 14:32:43 -07001616 session->transport.rmt_port = server_ep->port;
Dave Wallace543852a2017-08-03 02:11:34 -04001617
Florin Coras7baeb712019-01-04 17:05:43 -08001618 VDBG (0, "session handle %u [0x%llx]: connecting to server %s %U "
1619 "port %d proto %s", session_handle, session->vpp_handle,
Florin Coras7e12d942018-06-27 14:32:43 -07001620 session->transport.is_ip4 ? "IPv4" : "IPv6",
Florin Coras0d427d82018-06-27 03:24:07 -07001621 format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07001622 &session->transport.rmt_ip, session->transport.is_ip4 ?
Florin Coras0d427d82018-06-27 03:24:07 -07001623 IP46_TYPE_IP4 : IP46_TYPE_IP6,
Florin Coras7e12d942018-06-27 14:32:43 -07001624 clib_net_to_host_u16 (session->transport.rmt_port),
Ping Yu34a3a082018-11-30 19:16:17 -05001625 vppcom_proto_str (session->session_type));
Dave Wallace543852a2017-08-03 02:11:34 -04001626
Florin Coras070453d2018-08-24 17:04:27 -07001627 /*
1628 * Send connect request and wait for reply from vpp
1629 */
Florin Coras134a9962018-08-28 11:32:04 -07001630 vppcom_send_connect_sock (session);
Florin Coras070453d2018-08-24 17:04:27 -07001631 rv = vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
1632 vcm->cfg.session_timeout);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001633
Florin Coras134a9962018-08-28 11:32:04 -07001634 session = vcl_session_get (wrk, session_index);
Dave Wallace7876d392017-10-19 03:53:57 -04001635
Florin Coras070453d2018-08-24 17:04:27 -07001636 if (PREDICT_FALSE (rv))
Dave Wallaceee45d412017-11-24 21:44:06 -05001637 {
Dave Wallaceee45d412017-11-24 21:44:06 -05001638 if (VPPCOM_DEBUG > 0)
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001639 {
1640 if (session)
Florin Coras0d427d82018-06-27 03:24:07 -07001641 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connect "
Florin Coras134a9962018-08-28 11:32:04 -07001642 "failed! returning %d (%s)", getpid (),
1643 session->vpp_handle, session_handle, rv,
1644 vppcom_retval_str (rv));
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001645 else
1646 clib_warning ("VCL<%d>: no session for sid %u: connect failed! "
1647 "returning %d (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001648 session_handle, rv, vppcom_retval_str (rv));
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001649 }
Dave Wallaceee45d412017-11-24 21:44:06 -05001650 }
Florin Coras0d427d82018-06-27 03:24:07 -07001651 else
1652 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connected!",
Florin Coras134a9962018-08-28 11:32:04 -07001653 getpid (), session->vpp_handle, session_handle);
Dave Wallaceee45d412017-11-24 21:44:06 -05001654
Dave Wallace4878cbe2017-11-21 03:45:09 -05001655 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001656}
1657
Florin Coras54693d22018-07-17 10:46:29 -07001658static u8
1659vcl_is_rx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1660{
1661 if (!is_ct)
1662 return (e->event_type == FIFO_EVENT_APP_RX
1663 && e->fifo->client_session_index == sid);
1664 else
1665 return (e->event_type == SESSION_IO_EVT_CT_TX);
1666}
1667
Florin Coras460dce62018-07-27 05:45:06 -07001668static inline u8
1669vcl_session_is_readable (vcl_session_t * s)
1670{
1671 return ((s->session_state & STATE_OPEN)
1672 || (s->session_state == STATE_LISTEN
1673 && s->session_type == VPPCOM_PROTO_UDP));
1674}
1675
Steven58f464e2017-10-25 12:33:12 -07001676static inline int
Florin Coras134a9962018-08-28 11:32:04 -07001677vppcom_session_read_internal (uint32_t session_handle, void *buf, int n,
Steven58f464e2017-10-25 12:33:12 -07001678 u8 peek)
Dave Wallace543852a2017-08-03 02:11:34 -04001679{
Florin Coras134a9962018-08-28 11:32:04 -07001680 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001681 int n_read = 0, rv, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001682 vcl_session_t *s = 0;
Dave Wallace543852a2017-08-03 02:11:34 -04001683 svm_fifo_t *rx_fifo;
Florin Coras54693d22018-07-17 10:46:29 -07001684 svm_msg_q_msg_t msg;
1685 session_event_t *e;
1686 svm_msg_q_t *mq;
Florin Coras41c9e042018-09-11 00:10:41 -07001687 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001688
Florin Coras070453d2018-08-24 17:04:27 -07001689 if (PREDICT_FALSE (!buf))
1690 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001691
Florin Coras134a9962018-08-28 11:32:04 -07001692 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras2cba8532018-09-11 16:33:36 -07001693 if (PREDICT_FALSE (!s || s->is_vep))
Florin Coras070453d2018-08-24 17:04:27 -07001694 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001695
Florin Coras460dce62018-07-27 05:45:06 -07001696 if (PREDICT_FALSE (!vcl_session_is_readable (s)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001697 {
Florin Coras460dce62018-07-27 05:45:06 -07001698 session_state_t state = s->session_state;
Keith Burns (alagalah)56a0d062018-02-15 07:52:50 -08001699 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001700
Florin Corasb0f662f2018-12-27 14:51:46 -08001701 VDBG (0, "session handle %u[0x%llx] is not open! state 0x%x (%s),"
1702 " returning %d (%s)", session_handle, s->vpp_handle, state,
Florin Coras0d427d82018-06-27 03:24:07 -07001703 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
Florin Coras070453d2018-08-24 17:04:27 -07001704 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001705 }
1706
Florin Coras2cba8532018-09-11 16:33:36 -07001707 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
Florin Coras41c9e042018-09-11 00:10:41 -07001708 is_ct = vcl_session_is_ct (s);
1709 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
Florin Coras2cba8532018-09-11 16:33:36 -07001710 rx_fifo = s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001711 s->has_rx_evt = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04001712
Florin Coras54693d22018-07-17 10:46:29 -07001713 if (svm_fifo_is_empty (rx_fifo))
Dave Wallacef7f809c2017-10-03 01:48:42 -04001714 {
Florin Coras54693d22018-07-17 10:46:29 -07001715 if (is_nonblocking)
Dave Wallace4878cbe2017-11-21 03:45:09 -05001716 {
Florin Coras41c9e042018-09-11 00:10:41 -07001717 svm_fifo_unset_event (rx_fifo);
Florin Corasaa27eb92018-10-13 12:20:01 -07001718 return VPPCOM_EWOULDBLOCK;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001719 }
Florin Coras41c9e042018-09-11 00:10:41 -07001720 while (svm_fifo_is_empty (rx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001721 {
Florin Coras41c9e042018-09-11 00:10:41 -07001722 svm_fifo_unset_event (rx_fifo);
Florin Coras99368312018-08-02 10:45:44 -07001723 svm_msg_q_lock (mq);
Florin Coras54693d22018-07-17 10:46:29 -07001724 if (svm_msg_q_is_empty (mq))
1725 svm_msg_q_wait (mq);
Florin Coras99368312018-08-02 10:45:44 -07001726
Florin Coras54693d22018-07-17 10:46:29 -07001727 svm_msg_q_sub_w_lock (mq, &msg);
1728 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001729 svm_msg_q_unlock (mq);
Florin Coras41c9e042018-09-11 00:10:41 -07001730 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
Florin Coras05ce4b82018-12-15 18:30:43 -08001731 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001732 svm_msg_q_free_msg (mq, &msg);
Florin Coras41c9e042018-09-11 00:10:41 -07001733
Florin Coras05ce4b82018-12-15 18:30:43 -08001734 if (PREDICT_FALSE (s->session_state == STATE_DISCONNECT))
1735 return VPPCOM_ECONNRESET;
Florin Coras54693d22018-07-17 10:46:29 -07001736 }
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001737 }
Florin Coras54693d22018-07-17 10:46:29 -07001738
Florin Coras460dce62018-07-27 05:45:06 -07001739 if (s->is_dgram)
Florin Coras99368312018-08-02 10:45:44 -07001740 n_read = app_recv_dgram_raw (rx_fifo, buf, n, &s->transport, 0, peek);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001741 else
Florin Coras99368312018-08-02 10:45:44 -07001742 n_read = app_recv_stream_raw (rx_fifo, buf, n, 0, peek);
Florin Coras54693d22018-07-17 10:46:29 -07001743
Florin Coras41c9e042018-09-11 00:10:41 -07001744 if (svm_fifo_is_empty (rx_fifo))
1745 svm_fifo_unset_event (rx_fifo);
1746
Florin Coras58c101a2018-10-06 13:49:16 -07001747 if (is_ct && svm_fifo_want_tx_evt (rx_fifo))
Florin Coras99368312018-08-02 10:45:44 -07001748 {
Florin Coras58c101a2018-10-06 13:49:16 -07001749 svm_fifo_set_want_tx_evt (s->rx_fifo, 0);
1750 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo, SESSION_IO_EVT_CT_RX,
1751 SVM_Q_WAIT);
Florin Coras99368312018-08-02 10:45:44 -07001752 }
Florin Coras54693d22018-07-17 10:46:29 -07001753
Florin Corasa7a1a222018-12-30 17:11:31 -08001754 VDBG (2, "vpp handle 0x%llx, sid %u: read %d bytes from (%p)",
1755 s->vpp_handle, session_handle, n_read, rx_fifo);
Florin Coras2cba8532018-09-11 16:33:36 -07001756
Florin Coras54693d22018-07-17 10:46:29 -07001757 return n_read;
Dave Wallace543852a2017-08-03 02:11:34 -04001758}
1759
Steven58f464e2017-10-25 12:33:12 -07001760int
Florin Coras134a9962018-08-28 11:32:04 -07001761vppcom_session_read (uint32_t session_handle, void *buf, size_t n)
Steven58f464e2017-10-25 12:33:12 -07001762{
Florin Coras134a9962018-08-28 11:32:04 -07001763 return (vppcom_session_read_internal (session_handle, buf, n, 0));
Steven58f464e2017-10-25 12:33:12 -07001764}
1765
1766static int
Florin Coras134a9962018-08-28 11:32:04 -07001767vppcom_session_peek (uint32_t session_handle, void *buf, int n)
Steven58f464e2017-10-25 12:33:12 -07001768{
Florin Coras134a9962018-08-28 11:32:04 -07001769 return (vppcom_session_read_internal (session_handle, buf, n, 1));
Steven58f464e2017-10-25 12:33:12 -07001770}
1771
Florin Coras2cba8532018-09-11 16:33:36 -07001772int
1773vppcom_session_read_segments (uint32_t session_handle,
1774 vppcom_data_segments_t ds)
1775{
1776 vcl_worker_t *wrk = vcl_worker_get_current ();
1777 int n_read = 0, rv, is_nonblocking;
1778 vcl_session_t *s = 0;
1779 svm_fifo_t *rx_fifo;
1780 svm_msg_q_msg_t msg;
1781 session_event_t *e;
1782 svm_msg_q_t *mq;
1783 u8 is_ct;
1784
1785 s = vcl_session_get_w_handle (wrk, session_handle);
1786 if (PREDICT_FALSE (!s || s->is_vep))
1787 return VPPCOM_EBADFD;
1788
1789 if (PREDICT_FALSE (!vcl_session_is_readable (s)))
1790 {
1791 session_state_t state = s->session_state;
1792 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1793 return rv;
1794 }
1795
1796 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1797 is_ct = vcl_session_is_ct (s);
1798 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
1799 rx_fifo = s->rx_fifo;
Florin Corasaa27eb92018-10-13 12:20:01 -07001800 s->has_rx_evt = 0;
Florin Coras2cba8532018-09-11 16:33:36 -07001801
1802 if (svm_fifo_is_empty (rx_fifo))
1803 {
1804 if (is_nonblocking)
1805 {
1806 svm_fifo_unset_event (rx_fifo);
Florin Corasaa27eb92018-10-13 12:20:01 -07001807 return VPPCOM_EWOULDBLOCK;
Florin Coras2cba8532018-09-11 16:33:36 -07001808 }
1809 while (svm_fifo_is_empty (rx_fifo))
1810 {
1811 svm_fifo_unset_event (rx_fifo);
1812 svm_msg_q_lock (mq);
1813 if (svm_msg_q_is_empty (mq))
1814 svm_msg_q_wait (mq);
1815
1816 svm_msg_q_sub_w_lock (mq, &msg);
1817 e = svm_msg_q_msg_data (mq, &msg);
1818 svm_msg_q_unlock (mq);
1819 if (!vcl_is_rx_evt_for_session (e, s->session_index, is_ct))
Florin Coras05ce4b82018-12-15 18:30:43 -08001820 vcl_handle_mq_event (wrk, e);
Florin Coras2cba8532018-09-11 16:33:36 -07001821 svm_msg_q_free_msg (mq, &msg);
1822
Florin Coras05ce4b82018-12-15 18:30:43 -08001823 if (PREDICT_FALSE (s->session_state == STATE_DISCONNECT))
1824 return VPPCOM_ECONNRESET;
Florin Coras2cba8532018-09-11 16:33:36 -07001825 }
1826 }
1827
1828 n_read = svm_fifo_segments (rx_fifo, (svm_fifo_segment_t *) ds);
1829 svm_fifo_unset_event (rx_fifo);
1830
1831 if (is_ct && n_read + svm_fifo_max_dequeue (rx_fifo) == rx_fifo->nitems)
1832 {
1833 /* If the peer is not polling send notification */
1834 if (!svm_fifo_has_event (s->rx_fifo))
1835 app_send_io_evt_to_vpp (s->vpp_evt_q, s->rx_fifo,
1836 SESSION_IO_EVT_CT_RX, SVM_Q_WAIT);
1837 }
1838
1839 return n_read;
1840}
1841
1842void
1843vppcom_session_free_segments (uint32_t session_handle,
1844 vppcom_data_segments_t ds)
1845{
1846 vcl_worker_t *wrk = vcl_worker_get_current ();
1847 vcl_session_t *s;
1848
1849 s = vcl_session_get_w_handle (wrk, session_handle);
1850 if (PREDICT_FALSE (!s || s->is_vep))
1851 return;
1852
1853 svm_fifo_segments_free (s->rx_fifo, (svm_fifo_segment_t *) ds);
1854}
1855
Dave Wallace543852a2017-08-03 02:11:34 -04001856static inline int
Florin Coras54693d22018-07-17 10:46:29 -07001857vppcom_session_read_ready (vcl_session_t * session)
Dave Wallace543852a2017-08-03 02:11:34 -04001858{
Dave Wallace543852a2017-08-03 02:11:34 -04001859 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05001860 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001861 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001862 clib_warning ("VCL<%d>: ERROR: sid %u: cannot read from an "
Florin Coras134a9962018-08-28 11:32:04 -07001863 "epoll session!", getpid (), session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -07001864 return VPPCOM_EBADFD;
1865 }
1866
1867 if (PREDICT_FALSE (!(session->session_state & (STATE_OPEN | STATE_LISTEN))))
1868 {
1869 session_state_t state = session->session_state;
1870 int rv;
1871
1872 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1873
1874 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open!"
1875 " state 0x%x (%s), returning %d (%s)", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07001876 session->vpp_handle, session->session_index, state,
Florin Coras54693d22018-07-17 10:46:29 -07001877 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
1878 return rv;
Dave Wallace543852a2017-08-03 02:11:34 -04001879 }
Dave Wallace33e002b2017-09-06 01:20:02 -04001880
Florin Coras7e12d942018-06-27 14:32:43 -07001881 if (session->session_state & STATE_LISTEN)
Florin Coras54693d22018-07-17 10:46:29 -07001882 return clib_fifo_elts (session->accept_evts_fifo);
1883
1884 return svm_fifo_max_dequeue (session->rx_fifo);
1885}
1886
Florin Coras2cba8532018-09-11 16:33:36 -07001887int
1888vppcom_data_segment_copy (void *buf, vppcom_data_segments_t ds, u32 max_bytes)
1889{
1890 u32 first_copy = clib_min (ds[0].len, max_bytes);
Dave Barach178cf492018-11-13 16:34:13 -05001891 clib_memcpy_fast (buf, ds[0].data, first_copy);
Florin Coras2cba8532018-09-11 16:33:36 -07001892 if (first_copy < max_bytes)
1893 {
Dave Barach178cf492018-11-13 16:34:13 -05001894 clib_memcpy_fast (buf + first_copy, ds[1].data,
1895 clib_min (ds[1].len, max_bytes - first_copy));
Florin Coras2cba8532018-09-11 16:33:36 -07001896 }
1897 return 0;
1898}
1899
Florin Coras54693d22018-07-17 10:46:29 -07001900static u8
1901vcl_is_tx_evt_for_session (session_event_t * e, u32 sid, u8 is_ct)
1902{
1903 if (!is_ct)
1904 return (e->event_type == FIFO_EVENT_APP_TX
1905 && e->fifo->client_session_index == sid);
Dave Wallace543852a2017-08-03 02:11:34 -04001906 else
Florin Coras54693d22018-07-17 10:46:29 -07001907 return (e->event_type == SESSION_IO_EVT_CT_RX);
Dave Wallace543852a2017-08-03 02:11:34 -04001908}
1909
Florin Coras42ceddb2018-12-12 10:56:01 -08001910static inline int
1911vppcom_session_write_inline (uint32_t session_handle, void *buf, size_t n,
1912 u8 is_flush)
Dave Wallace543852a2017-08-03 02:11:34 -04001913{
Florin Coras134a9962018-08-28 11:32:04 -07001914 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras54693d22018-07-17 10:46:29 -07001915 int rv, n_write, is_nonblocking;
Florin Coras460dce62018-07-27 05:45:06 -07001916 vcl_session_t *s = 0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08001917 svm_fifo_t *tx_fifo = 0;
Florin Coras460dce62018-07-27 05:45:06 -07001918 session_evt_type_t et;
Florin Coras54693d22018-07-17 10:46:29 -07001919 svm_msg_q_msg_t msg;
1920 session_event_t *e;
Florin Coras3c2fed52018-07-04 04:15:05 -07001921 svm_msg_q_t *mq;
Florin Coras0e88e852018-09-17 22:09:02 -07001922 u8 is_ct;
Dave Wallace543852a2017-08-03 02:11:34 -04001923
Florin Coras070453d2018-08-24 17:04:27 -07001924 if (PREDICT_FALSE (!buf))
1925 return VPPCOM_EINVAL;
Dave Wallace543852a2017-08-03 02:11:34 -04001926
Florin Coras134a9962018-08-28 11:32:04 -07001927 s = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07001928 if (PREDICT_FALSE (!s))
1929 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05001930
Florin Coras460dce62018-07-27 05:45:06 -07001931 if (PREDICT_FALSE (s->is_vep))
Dave Wallace543852a2017-08-03 02:11:34 -04001932 {
Dave Wallace048b1d62018-01-03 22:24:41 -05001933 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05001934 "cannot write to an epoll session!",
Florin Coras134a9962018-08-28 11:32:04 -07001935 getpid (), s->vpp_handle, session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05001936
Florin Coras070453d2018-08-24 17:04:27 -07001937 return VPPCOM_EBADFD;
Dave Wallace543852a2017-08-03 02:11:34 -04001938 }
1939
Florin Coras0e88e852018-09-17 22:09:02 -07001940 if (PREDICT_FALSE (!(s->session_state & STATE_OPEN)))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001941 {
Florin Coras460dce62018-07-27 05:45:06 -07001942 session_state_t state = s->session_state;
Florin Coras54693d22018-07-17 10:46:29 -07001943 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Florin Coras0d427d82018-06-27 03:24:07 -07001944 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open! "
Florin Coras0e88e852018-09-17 22:09:02 -07001945 "state 0x%x (%s)", getpid (), s->vpp_handle, session_handle,
Florin Coras0d427d82018-06-27 03:24:07 -07001946 state, vppcom_session_state_str (state));
Florin Coras070453d2018-08-24 17:04:27 -07001947 return rv;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04001948 }
1949
Florin Coras0e88e852018-09-17 22:09:02 -07001950 tx_fifo = s->tx_fifo;
1951 is_ct = vcl_session_is_ct (s);
1952 is_nonblocking = VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK);
1953 mq = is_ct ? s->our_evt_q : wrk->app_event_queue;
Florin Coras54693d22018-07-17 10:46:29 -07001954 if (svm_fifo_is_full (tx_fifo))
Dave Wallace543852a2017-08-03 02:11:34 -04001955 {
Florin Coras54693d22018-07-17 10:46:29 -07001956 if (is_nonblocking)
1957 {
Florin Coras070453d2018-08-24 17:04:27 -07001958 return VPPCOM_EWOULDBLOCK;
Florin Coras54693d22018-07-17 10:46:29 -07001959 }
Florin Coras60f1fc12018-08-16 14:57:31 -07001960 while (svm_fifo_is_full (tx_fifo))
Florin Coras54693d22018-07-17 10:46:29 -07001961 {
Florin Coras0e88e852018-09-17 22:09:02 -07001962 svm_fifo_set_want_tx_evt (tx_fifo, 1);
Florin Coras99368312018-08-02 10:45:44 -07001963 svm_msg_q_lock (mq);
Florin Corasaa27eb92018-10-13 12:20:01 -07001964 if (svm_msg_q_is_empty (mq))
1965 svm_msg_q_wait (mq);
Florin Coras0e88e852018-09-17 22:09:02 -07001966
Florin Coras54693d22018-07-17 10:46:29 -07001967 svm_msg_q_sub_w_lock (mq, &msg);
1968 e = svm_msg_q_msg_data (mq, &msg);
Florin Coras99368312018-08-02 10:45:44 -07001969 svm_msg_q_unlock (mq);
1970
Florin Coras0e88e852018-09-17 22:09:02 -07001971 if (!vcl_is_tx_evt_for_session (e, s->session_index, is_ct))
Florin Coras86f04502018-09-12 16:08:01 -07001972 vcl_handle_mq_event (wrk, e);
Florin Coras54693d22018-07-17 10:46:29 -07001973 svm_msg_q_free_msg (mq, &msg);
Florin Coras05ce4b82018-12-15 18:30:43 -08001974
1975 if (PREDICT_FALSE (!(s->session_state & STATE_OPEN)))
1976 return VPPCOM_ECONNRESET;
Florin Coras54693d22018-07-17 10:46:29 -07001977 }
Dave Wallace543852a2017-08-03 02:11:34 -04001978 }
Dave Wallace543852a2017-08-03 02:11:34 -04001979
Florin Coras460dce62018-07-27 05:45:06 -07001980 ASSERT (FIFO_EVENT_APP_TX + 1 == SESSION_IO_EVT_CT_TX);
1981 et = FIFO_EVENT_APP_TX + vcl_session_is_ct (s);
Florin Coras42ceddb2018-12-12 10:56:01 -08001982 if (is_flush && !vcl_session_is_ct (s))
1983 et = SESSION_IO_EVT_TX_FLUSH;
1984
Florin Coras460dce62018-07-27 05:45:06 -07001985 if (s->is_dgram)
1986 n_write = app_send_dgram_raw (tx_fifo, &s->transport,
1987 s->vpp_evt_q, buf, n, et, SVM_Q_WAIT);
1988 else
1989 n_write = app_send_stream_raw (tx_fifo, s->vpp_evt_q, buf, n, et,
1990 SVM_Q_WAIT);
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -07001991
Florin Coras460dce62018-07-27 05:45:06 -07001992 ASSERT (n_write > 0);
Dave Wallace543852a2017-08-03 02:11:34 -04001993
Florin Coras0e88e852018-09-17 22:09:02 -07001994 VDBG (2, "VCL<%d>: vpp handle 0x%llx, sid %u: wrote %d bytes", getpid (),
1995 s->vpp_handle, session_handle, n_write);
1996
Florin Coras54693d22018-07-17 10:46:29 -07001997 return n_write;
Dave Wallace543852a2017-08-03 02:11:34 -04001998}
1999
Florin Coras42ceddb2018-12-12 10:56:01 -08002000int
2001vppcom_session_write (uint32_t session_handle, void *buf, size_t n)
2002{
2003 return vppcom_session_write_inline (session_handle, buf, n,
2004 0 /* is_flush */ );
2005}
2006
Florin Corasb0f662f2018-12-27 14:51:46 -08002007int
2008vppcom_session_write_msg (uint32_t session_handle, void *buf, size_t n)
2009{
2010 return vppcom_session_write_inline (session_handle, buf, n,
2011 1 /* is_flush */ );
2012}
2013
2014
Florin Coras99368312018-08-02 10:45:44 -07002015static vcl_session_t *
Florin Coras134a9962018-08-28 11:32:04 -07002016vcl_ct_session_get_from_fifo (vcl_worker_t * wrk, svm_fifo_t * f, u8 type)
Florin Coras99368312018-08-02 10:45:44 -07002017{
2018 vcl_session_t *s;
Florin Coras134a9962018-08-28 11:32:04 -07002019 s = vcl_session_get (wrk, f->client_session_index);
Florin Coras99368312018-08-02 10:45:44 -07002020 if (s)
2021 {
2022 /* rx fifo */
2023 if (type == 0 && s->rx_fifo == f)
2024 return s;
2025 /* tx fifo */
2026 if (type == 1 && s->tx_fifo == f)
2027 return s;
2028 }
Florin Coras134a9962018-08-28 11:32:04 -07002029 s = vcl_session_get (wrk, f->master_session_index);
Florin Coras99368312018-08-02 10:45:44 -07002030 if (s)
2031 {
2032 if (type == 0 && s->rx_fifo == f)
2033 return s;
2034 if (type == 1 && s->tx_fifo == f)
2035 return s;
2036 }
2037 return 0;
2038}
2039
Dave Wallace543852a2017-08-03 02:11:34 -04002040static inline int
Florin Coras134a9962018-08-28 11:32:04 -07002041vppcom_session_write_ready (vcl_session_t * session)
Dave Wallace543852a2017-08-03 02:11:34 -04002042{
Dave Wallace543852a2017-08-03 02:11:34 -04002043 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Dave Wallace4878cbe2017-11-21 03:45:09 -05002044 if (PREDICT_FALSE (session->is_vep))
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002045 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002046 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05002047 "cannot write to an epoll session!",
Florin Coras134a9962018-08-28 11:32:04 -07002048 getpid (), session->vpp_handle, session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -07002049 return VPPCOM_EBADFD;
Dave Wallace9c4b5b22017-10-18 21:15:48 -04002050 }
2051
Florin Coras7e12d942018-06-27 14:32:43 -07002052 if (PREDICT_FALSE (session->session_state & STATE_LISTEN))
Dave Wallace33e002b2017-09-06 01:20:02 -04002053 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002054 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Dave Wallaceee45d412017-11-24 21:44:06 -05002055 "cannot write to a listen session!",
Florin Coras134a9962018-08-28 11:32:04 -07002056 getpid (), session->vpp_handle, session->session_index);
Florin Coras54693d22018-07-17 10:46:29 -07002057 return VPPCOM_EBADFD;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002058 }
2059
Florin Coras54693d22018-07-17 10:46:29 -07002060 if (PREDICT_FALSE (!(session->session_state & STATE_OPEN)))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002061 {
Florin Coras7e12d942018-06-27 14:32:43 -07002062 session_state_t state = session->session_state;
Florin Coras54693d22018-07-17 10:46:29 -07002063 int rv;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002064
Keith Burns (alagalah)56a0d062018-02-15 07:52:50 -08002065 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
Dave Wallace048b1d62018-01-03 22:24:41 -05002066 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002067 "session is not open! state 0x%x (%s), "
Dave Wallaceee45d412017-11-24 21:44:06 -05002068 "returning %d (%s)", getpid (), session->vpp_handle,
Florin Coras134a9962018-08-28 11:32:04 -07002069 session->session_index,
Dave Wallace4878cbe2017-11-21 03:45:09 -05002070 state, vppcom_session_state_str (state),
2071 rv, vppcom_retval_str (rv));
Florin Coras54693d22018-07-17 10:46:29 -07002072 return rv;
Dave Wallace33e002b2017-09-06 01:20:02 -04002073 }
2074
Florin Coras0d427d82018-06-27 03:24:07 -07002075 VDBG (3, "VCL<%d>: vpp handle 0x%llx, sid %u: peek %s (%p), ready = %d",
Florin Coras134a9962018-08-28 11:32:04 -07002076 getpid (), session->vpp_handle, session->session_index,
2077 session->tx_fifo, svm_fifo_max_enqueue (session->tx_fifo));
Dave Wallacef7f809c2017-10-03 01:48:42 -04002078
Florin Coras54693d22018-07-17 10:46:29 -07002079 return svm_fifo_max_enqueue (session->tx_fifo);
2080}
2081
Florin Coras6d4bb422018-09-04 22:07:27 -07002082#define vcl_fifo_rx_evt_valid_or_break(_fifo) \
2083if (PREDICT_FALSE (svm_fifo_is_empty (_fifo))) \
2084 { \
2085 svm_fifo_unset_event (_fifo); \
2086 if (svm_fifo_is_empty (_fifo)) \
Florin Coras41c9e042018-09-11 00:10:41 -07002087 break; \
Florin Coras6d4bb422018-09-04 22:07:27 -07002088 } \
2089
Florin Coras86f04502018-09-12 16:08:01 -07002090static void
2091vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
2092 unsigned long n_bits, unsigned long *read_map,
2093 unsigned long *write_map,
2094 unsigned long *except_map, u32 * bits_set)
Florin Coras54693d22018-07-17 10:46:29 -07002095{
2096 session_disconnected_msg_t *disconnected_msg;
Florin Coras99368312018-08-02 10:45:44 -07002097 session_connected_msg_t *connected_msg;
Florin Coras54693d22018-07-17 10:46:29 -07002098 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07002099 u32 sid;
2100
2101 switch (e->event_type)
2102 {
2103 case FIFO_EVENT_APP_RX:
2104 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2105 sid = e->fifo->client_session_index;
2106 session = vcl_session_get (wrk, sid);
2107 if (!session)
2108 break;
2109 if (sid < n_bits && read_map)
2110 {
David Johnsond9818dd2018-12-14 14:53:41 -05002111 clib_bitmap_set_no_check ((uword *) read_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002112 *bits_set += 1;
2113 }
2114 break;
2115 case FIFO_EVENT_APP_TX:
2116 sid = e->fifo->client_session_index;
2117 session = vcl_session_get (wrk, sid);
2118 if (!session)
2119 break;
2120 if (sid < n_bits && write_map)
2121 {
David Johnsond9818dd2018-12-14 14:53:41 -05002122 clib_bitmap_set_no_check ((uword *) write_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002123 *bits_set += 1;
2124 }
2125 break;
2126 case SESSION_IO_EVT_CT_TX:
2127 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2128 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0);
2129 if (!session)
2130 break;
2131 sid = session->session_index;
2132 if (sid < n_bits && read_map)
2133 {
David Johnsond9818dd2018-12-14 14:53:41 -05002134 clib_bitmap_set_no_check ((uword *) read_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002135 *bits_set += 1;
2136 }
2137 break;
2138 case SESSION_IO_EVT_CT_RX:
2139 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1);
2140 if (!session)
2141 break;
2142 sid = session->session_index;
2143 if (sid < n_bits && write_map)
2144 {
David Johnsond9818dd2018-12-14 14:53:41 -05002145 clib_bitmap_set_no_check ((uword *) write_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002146 *bits_set += 1;
2147 }
2148 break;
2149 case SESSION_CTRL_EVT_ACCEPTED:
Florin Coras3c7d4f92018-12-14 11:28:43 -08002150 session = vcl_session_accepted (wrk,
2151 (session_accepted_msg_t *) e->data);
Florin Coras86f04502018-09-12 16:08:01 -07002152 if (!session)
Florin Coras3c7d4f92018-12-14 11:28:43 -08002153 break;
Florin Coras86f04502018-09-12 16:08:01 -07002154 sid = session->session_index;
2155 if (sid < n_bits && read_map)
2156 {
David Johnsond9818dd2018-12-14 14:53:41 -05002157 clib_bitmap_set_no_check ((uword *) read_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002158 *bits_set += 1;
2159 }
2160 break;
2161 case SESSION_CTRL_EVT_CONNECTED:
2162 connected_msg = (session_connected_msg_t *) e->data;
2163 vcl_session_connected_handler (wrk, connected_msg);
2164 break;
2165 case SESSION_CTRL_EVT_DISCONNECTED:
2166 disconnected_msg = (session_disconnected_msg_t *) e->data;
Florin Coras3c7d4f92018-12-14 11:28:43 -08002167 session = vcl_session_disconnected_handler (wrk, disconnected_msg);
2168 if (!session)
2169 break;
2170 sid = session->session_index;
Florin Coras86f04502018-09-12 16:08:01 -07002171 if (sid < n_bits && except_map)
2172 {
David Johnsond9818dd2018-12-14 14:53:41 -05002173 clib_bitmap_set_no_check ((uword *) except_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002174 *bits_set += 1;
2175 }
2176 break;
2177 case SESSION_CTRL_EVT_RESET:
2178 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
2179 if (sid < n_bits && except_map)
2180 {
David Johnsond9818dd2018-12-14 14:53:41 -05002181 clib_bitmap_set_no_check ((uword *) except_map, sid, 1);
Florin Coras86f04502018-09-12 16:08:01 -07002182 *bits_set += 1;
2183 }
2184 break;
Florin Coras30e79c22019-01-02 19:31:22 -08002185 case SESSION_CTRL_EVT_WORKER_UPDATE_REPLY:
2186 vcl_session_worker_update_reply_handler (wrk, e->data);
2187 break;
2188 case SESSION_CTRL_EVT_REQ_WORKER_UPDATE:
2189 vcl_session_req_worker_update_handler (wrk, e->data);
2190 break;
Florin Coras86f04502018-09-12 16:08:01 -07002191 default:
2192 clib_warning ("unhandled: %u", e->event_type);
2193 break;
2194 }
2195}
2196
2197static int
2198vcl_select_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
2199 unsigned long n_bits, unsigned long *read_map,
2200 unsigned long *write_map, unsigned long *except_map,
2201 double time_to_wait, u32 * bits_set)
2202{
Florin Coras99368312018-08-02 10:45:44 -07002203 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07002204 session_event_t *e;
Florin Coras86f04502018-09-12 16:08:01 -07002205 u32 i;
Florin Coras54693d22018-07-17 10:46:29 -07002206
2207 svm_msg_q_lock (mq);
2208 if (svm_msg_q_is_empty (mq))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002209 {
Florin Coras54693d22018-07-17 10:46:29 -07002210 if (*bits_set)
Dave Wallace4878cbe2017-11-21 03:45:09 -05002211 {
Florin Coras54693d22018-07-17 10:46:29 -07002212 svm_msg_q_unlock (mq);
2213 return 0;
2214 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002215
Florin Coras54693d22018-07-17 10:46:29 -07002216 if (!time_to_wait)
2217 {
2218 svm_msg_q_unlock (mq);
2219 return 0;
2220 }
2221 else if (time_to_wait < 0)
2222 {
2223 svm_msg_q_wait (mq);
2224 }
2225 else
2226 {
2227 if (svm_msg_q_timedwait (mq, time_to_wait))
2228 {
2229 svm_msg_q_unlock (mq);
2230 return 0;
2231 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002232 }
2233 }
Florin Coras134a9962018-08-28 11:32:04 -07002234 vcl_mq_dequeue_batch (wrk, mq);
Florin Coras54693d22018-07-17 10:46:29 -07002235 svm_msg_q_unlock (mq);
2236
Florin Coras134a9962018-08-28 11:32:04 -07002237 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07002238 {
Florin Coras134a9962018-08-28 11:32:04 -07002239 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07002240 e = svm_msg_q_msg_data (mq, msg);
Florin Coras86f04502018-09-12 16:08:01 -07002241 vcl_select_handle_mq_event (wrk, e, n_bits, read_map, write_map,
2242 except_map, bits_set);
Florin Coras99368312018-08-02 10:45:44 -07002243 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002244 }
Florin Coras134a9962018-08-28 11:32:04 -07002245 vec_reset_length (wrk->mq_msg_vector);
Florin Coras30e79c22019-01-02 19:31:22 -08002246 vcl_handle_pending_wrk_updates (wrk);
Florin Coras54693d22018-07-17 10:46:29 -07002247 return *bits_set;
Dave Wallace543852a2017-08-03 02:11:34 -04002248}
2249
Florin Coras99368312018-08-02 10:45:44 -07002250static int
Florin Coras134a9962018-08-28 11:32:04 -07002251vppcom_select_condvar (vcl_worker_t * wrk, unsigned long n_bits,
2252 unsigned long *read_map, unsigned long *write_map,
2253 unsigned long *except_map, double time_to_wait,
2254 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002255{
2256 double total_wait = 0, wait_slice;
2257 vcl_cut_through_registration_t *cr;
2258
2259 time_to_wait = (time_to_wait == -1) ? 10e9 : time_to_wait;
Florin Coras134a9962018-08-28 11:32:04 -07002260 wait_slice = wrk->cut_through_registrations ? 10e-6 : time_to_wait;
Florin Coras99368312018-08-02 10:45:44 -07002261 do
2262 {
Florin Coras134a9962018-08-28 11:32:04 -07002263 vcl_ct_registration_lock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002264 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002265 pool_foreach (cr, wrk->cut_through_registrations, ({
2266 vcl_select_handle_mq (wrk, cr->mq, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002267 0, bits_set);
2268 }));
2269 /* *INDENT-ON* */
Florin Coras134a9962018-08-28 11:32:04 -07002270 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002271
Florin Coras134a9962018-08-28 11:32:04 -07002272 vcl_select_handle_mq (wrk, wrk->app_event_queue, n_bits, read_map,
2273 write_map, except_map, time_to_wait, bits_set);
Florin Coras99368312018-08-02 10:45:44 -07002274 total_wait += wait_slice;
2275 if (*bits_set)
2276 return *bits_set;
2277 }
2278 while (total_wait < time_to_wait);
2279
2280 return 0;
2281}
2282
2283static int
Florin Coras134a9962018-08-28 11:32:04 -07002284vppcom_select_eventfd (vcl_worker_t * wrk, unsigned long n_bits,
2285 unsigned long *read_map, unsigned long *write_map,
2286 unsigned long *except_map, double time_to_wait,
2287 u32 * bits_set)
Florin Coras99368312018-08-02 10:45:44 -07002288{
2289 vcl_mq_evt_conn_t *mqc;
2290 int __clib_unused n_read;
2291 int n_mq_evts, i;
2292 u64 buf;
2293
Florin Coras134a9962018-08-28 11:32:04 -07002294 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
2295 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2296 vec_len (wrk->mq_events), time_to_wait);
Florin Coras99368312018-08-02 10:45:44 -07002297 for (i = 0; i < n_mq_evts; i++)
2298 {
Florin Coras134a9962018-08-28 11:32:04 -07002299 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002300 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002301 vcl_select_handle_mq (wrk, mqc->mq, n_bits, read_map, write_map,
Florin Coras99368312018-08-02 10:45:44 -07002302 except_map, 0, bits_set);
2303 }
2304
2305 return (n_mq_evts > 0 ? (int) *bits_set : 0);
2306}
2307
Dave Wallace543852a2017-08-03 02:11:34 -04002308int
2309vppcom_select (unsigned long n_bits, unsigned long *read_map,
2310 unsigned long *write_map, unsigned long *except_map,
2311 double time_to_wait)
2312{
Florin Coras54693d22018-07-17 10:46:29 -07002313 u32 sid, minbits = clib_max (n_bits, BITS (uword)), bits_set = 0;
Florin Coras134a9962018-08-28 11:32:04 -07002314 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002315 vcl_session_t *session = 0;
Florin Coras86f04502018-09-12 16:08:01 -07002316 int rv, i;
Dave Wallace543852a2017-08-03 02:11:34 -04002317
David Johnsond9818dd2018-12-14 14:53:41 -05002318 STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (unsigned long),
2319 "vppcom bitmap size mismatch");
2320 STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (fd_mask),
2321 "vppcom bitmap size mismatch");
2322 STATIC_ASSERT (sizeof (clib_bitmap_t) == sizeof (uword),
2323 "vppcom bitmap size mismatch");
Dave Wallace543852a2017-08-03 02:11:34 -04002324
Dave Wallace7876d392017-10-19 03:53:57 -04002325 if (n_bits && read_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002326 {
Florin Coras134a9962018-08-28 11:32:04 -07002327 clib_bitmap_validate (wrk->rd_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002328 clib_memcpy_fast (wrk->rd_bitmap, read_map,
David Johnsond9818dd2018-12-14 14:53:41 -05002329 vec_len (wrk->rd_bitmap) * sizeof (unsigned long));
2330 memset (read_map, 0, vec_len (wrk->rd_bitmap) * sizeof (unsigned long));
Dave Wallace543852a2017-08-03 02:11:34 -04002331 }
Dave Wallace7876d392017-10-19 03:53:57 -04002332 if (n_bits && write_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002333 {
Florin Coras134a9962018-08-28 11:32:04 -07002334 clib_bitmap_validate (wrk->wr_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002335 clib_memcpy_fast (wrk->wr_bitmap, write_map,
David Johnsond9818dd2018-12-14 14:53:41 -05002336 vec_len (wrk->wr_bitmap) * sizeof (unsigned long));
Dave Wallace048b1d62018-01-03 22:24:41 -05002337 memset (write_map, 0,
David Johnsond9818dd2018-12-14 14:53:41 -05002338 vec_len (wrk->wr_bitmap) * sizeof (unsigned long));
Dave Wallace543852a2017-08-03 02:11:34 -04002339 }
Dave Wallace7876d392017-10-19 03:53:57 -04002340 if (n_bits && except_map)
Dave Wallace543852a2017-08-03 02:11:34 -04002341 {
Florin Coras134a9962018-08-28 11:32:04 -07002342 clib_bitmap_validate (wrk->ex_bitmap, minbits);
Dave Barach178cf492018-11-13 16:34:13 -05002343 clib_memcpy_fast (wrk->ex_bitmap, except_map,
David Johnsond9818dd2018-12-14 14:53:41 -05002344 vec_len (wrk->ex_bitmap) * sizeof (unsigned long));
Dave Wallace048b1d62018-01-03 22:24:41 -05002345 memset (except_map, 0,
David Johnsond9818dd2018-12-14 14:53:41 -05002346 vec_len (wrk->ex_bitmap) * sizeof (unsigned long));
Dave Wallace543852a2017-08-03 02:11:34 -04002347 }
2348
Florin Coras54693d22018-07-17 10:46:29 -07002349 if (!n_bits)
2350 return 0;
2351
2352 if (!write_map)
2353 goto check_rd;
2354
2355 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002356 clib_bitmap_foreach (sid, wrk->wr_bitmap, ({
2357 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002358 {
Florin Coras47c40e22018-11-26 17:01:36 -08002359 if (except_map && sid < minbits)
2360 clib_bitmap_set_no_check (except_map, sid, 1);
2361 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002362 }
2363
2364 rv = svm_fifo_is_full (session->tx_fifo);
Florin Coras54693d22018-07-17 10:46:29 -07002365 if (!rv)
2366 {
David Johnsond9818dd2018-12-14 14:53:41 -05002367 clib_bitmap_set_no_check ((uword*)write_map, sid, 1);
Florin Coras54693d22018-07-17 10:46:29 -07002368 bits_set++;
2369 }
2370 }));
2371
2372check_rd:
2373 if (!read_map)
2374 goto check_mq;
Florin Coras99368312018-08-02 10:45:44 -07002375
Florin Coras134a9962018-08-28 11:32:04 -07002376 clib_bitmap_foreach (sid, wrk->rd_bitmap, ({
2377 if (!(session = vcl_session_get (wrk, sid)))
Florin Coras54693d22018-07-17 10:46:29 -07002378 {
Florin Coras47c40e22018-11-26 17:01:36 -08002379 if (except_map && sid < minbits)
2380 clib_bitmap_set_no_check (except_map, sid, 1);
2381 continue;
Florin Coras54693d22018-07-17 10:46:29 -07002382 }
2383
2384 rv = vppcom_session_read_ready (session);
Florin Coras54693d22018-07-17 10:46:29 -07002385 if (rv)
2386 {
David Johnsond9818dd2018-12-14 14:53:41 -05002387 clib_bitmap_set_no_check ((uword*)read_map, sid, 1);
Florin Coras54693d22018-07-17 10:46:29 -07002388 bits_set++;
2389 }
2390 }));
2391 /* *INDENT-ON* */
2392
2393check_mq:
Dave Wallace543852a2017-08-03 02:11:34 -04002394
Florin Coras86f04502018-09-12 16:08:01 -07002395 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2396 {
2397 vcl_select_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i], n_bits,
2398 read_map, write_map, except_map, &bits_set);
2399 }
2400 vec_reset_length (wrk->unhandled_evts_vector);
2401
Florin Coras99368312018-08-02 10:45:44 -07002402 if (vcm->cfg.use_mq_eventfd)
Florin Coras134a9962018-08-28 11:32:04 -07002403 vppcom_select_eventfd (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002404 time_to_wait, &bits_set);
2405 else
Florin Coras134a9962018-08-28 11:32:04 -07002406 vppcom_select_condvar (wrk, n_bits, read_map, write_map, except_map,
Florin Coras99368312018-08-02 10:45:44 -07002407 time_to_wait, &bits_set);
Florin Coras54693d22018-07-17 10:46:29 -07002408
Dave Wallace543852a2017-08-03 02:11:34 -04002409 return (bits_set);
2410}
2411
Dave Wallacef7f809c2017-10-03 01:48:42 -04002412static inline void
Florin Coras134a9962018-08-28 11:32:04 -07002413vep_verify_epoll_chain (vcl_worker_t * wrk, u32 vep_idx)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002414{
Florin Coras7e12d942018-06-27 14:32:43 -07002415 vcl_session_t *session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002416 vppcom_epoll_t *vep;
Dave Wallace498b3a52017-11-09 13:00:34 -05002417 u32 sid = vep_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002418
Dave Wallace498b3a52017-11-09 13:00:34 -05002419 if (VPPCOM_DEBUG <= 1)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002420 return;
2421
2422 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
Florin Coras134a9962018-08-28 11:32:04 -07002423 session = vcl_session_get (wrk, vep_idx);
Florin Coras070453d2018-08-24 17:04:27 -07002424 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002425 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002426 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!",
2427 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002428 goto done;
2429 }
2430 if (PREDICT_FALSE (!session->is_vep))
2431 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002432 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
2433 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002434 goto done;
2435 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002436 vep = &session->vep;
Dave Wallace048b1d62018-01-03 22:24:41 -05002437 clib_warning ("VCL<%d>: vep_idx (%u): Dumping epoll chain\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05002438 "{\n"
2439 " is_vep = %u\n"
2440 " is_vep_session = %u\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05002441 " next_sid = 0x%x (%u)\n"
Dave Wallace498b3a52017-11-09 13:00:34 -05002442 " wait_cont_idx = 0x%x (%u)\n"
Dave Wallace4878cbe2017-11-21 03:45:09 -05002443 "}\n", getpid (), vep_idx,
2444 session->is_vep, session->is_vep_session,
Florin Coras134a9962018-08-28 11:32:04 -07002445 vep->next_sh, vep->next_sh,
Dave Wallace498b3a52017-11-09 13:00:34 -05002446 session->wait_cont_idx, session->wait_cont_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002447
Florin Coras134a9962018-08-28 11:32:04 -07002448 for (sid = vep->next_sh; sid != ~0; sid = vep->next_sh)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002449 {
Florin Coras134a9962018-08-28 11:32:04 -07002450 session = vcl_session_get (wrk, sid);
Florin Coras070453d2018-08-24 17:04:27 -07002451 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002452 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002453 clib_warning ("VCL<%d>: ERROR: Invalid sid (%u)!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002454 goto done;
2455 }
2456 if (PREDICT_FALSE (session->is_vep))
Dave Wallace048b1d62018-01-03 22:24:41 -05002457 clib_warning ("VCL<%d>: ERROR: sid (%u) is a vep!",
2458 getpid (), vep_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002459 else if (PREDICT_FALSE (!session->is_vep_session))
2460 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002461 clib_warning ("VCL<%d>: ERROR: session (%u) "
2462 "is not a vep session!", getpid (), sid);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002463 goto done;
2464 }
2465 vep = &session->vep;
Florin Coras134a9962018-08-28 11:32:04 -07002466 if (PREDICT_FALSE (vep->vep_sh != vep_idx))
Dave Wallace048b1d62018-01-03 22:24:41 -05002467 clib_warning ("VCL<%d>: ERROR: session (%u) vep_idx (%u) != "
Dave Wallace4878cbe2017-11-21 03:45:09 -05002468 "vep_idx (%u)!", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07002469 sid, session->vep.vep_sh, vep_idx);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002470 if (session->is_vep_session)
2471 {
2472 clib_warning ("vep_idx[%u]: sid 0x%x (%u)\n"
2473 "{\n"
2474 " next_sid = 0x%x (%u)\n"
2475 " prev_sid = 0x%x (%u)\n"
2476 " vep_idx = 0x%x (%u)\n"
2477 " ev.events = 0x%x\n"
2478 " ev.data.u64 = 0x%llx\n"
2479 " et_mask = 0x%x\n"
2480 "}\n",
2481 vep_idx, sid, sid,
Florin Coras134a9962018-08-28 11:32:04 -07002482 vep->next_sh, vep->next_sh,
2483 vep->prev_sh, vep->prev_sh,
2484 vep->vep_sh, vep->vep_sh,
Dave Wallace4878cbe2017-11-21 03:45:09 -05002485 vep->ev.events, vep->ev.data.u64, vep->et_mask);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002486 }
2487 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002488
2489done:
Dave Wallace048b1d62018-01-03 22:24:41 -05002490 clib_warning ("VCL<%d>: vep_idx (%u): Dump complete!\n",
2491 getpid (), vep_idx);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002492}
2493
2494int
2495vppcom_epoll_create (void)
2496{
Florin Coras134a9962018-08-28 11:32:04 -07002497 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002498 vcl_session_t *vep_session;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002499
Florin Coras134a9962018-08-28 11:32:04 -07002500 vep_session = vcl_session_alloc (wrk);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002501
2502 vep_session->is_vep = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002503 vep_session->vep.vep_sh = ~0;
2504 vep_session->vep.next_sh = ~0;
2505 vep_session->vep.prev_sh = ~0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002506 vep_session->wait_cont_idx = ~0;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002507 vep_session->vpp_handle = ~0;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08002508
Florin Corasa7a1a222018-12-30 17:11:31 -08002509 vcl_evt (VCL_EVT_EPOLL_CREATE, vep_session, vep_session->session_index);
2510 VDBG (0, "Created vep_idx %u", vep_session->session_index);
Keith Burns (alagalah)09b27842018-01-05 14:39:59 -08002511
Florin Corasab2f6db2018-08-31 14:31:41 -07002512 return vcl_session_handle (vep_session);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002513}
2514
2515int
Florin Coras134a9962018-08-28 11:32:04 -07002516vppcom_epoll_ctl (uint32_t vep_handle, int op, uint32_t session_handle,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002517 struct epoll_event *event)
2518{
Florin Coras134a9962018-08-28 11:32:04 -07002519 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002520 vcl_session_t *vep_session;
2521 vcl_session_t *session;
Florin Coras070453d2018-08-24 17:04:27 -07002522 int rv = VPPCOM_OK;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002523
Florin Coras134a9962018-08-28 11:32:04 -07002524 if (vep_handle == session_handle)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002525 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002526 VDBG (0, "vep_sh == session handle (%u)!", vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002527 return VPPCOM_EINVAL;
2528 }
2529
Florin Coras134a9962018-08-28 11:32:04 -07002530 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002531 if (PREDICT_FALSE (!vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002532 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002533 VDBG (0, "Invalid vep_sh (%u)!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002534 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002535 }
2536 if (PREDICT_FALSE (!vep_session->is_vep))
2537 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002538 VDBG (0, "vep_sh (%u) is not a vep!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002539 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002540 }
2541
Florin Coras134a9962018-08-28 11:32:04 -07002542 ASSERT (vep_session->vep.vep_sh == ~0);
2543 ASSERT (vep_session->vep.prev_sh == ~0);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002544
Florin Coras134a9962018-08-28 11:32:04 -07002545 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002546 if (PREDICT_FALSE (!session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002547 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002548 VDBG (0, "Invalid session_handle (%u)!", session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002549 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002550 }
2551 if (PREDICT_FALSE (session->is_vep))
2552 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002553 VDBG (0, "session_handle (%u) is a vep!", vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002554 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002555 }
2556
2557 switch (op)
2558 {
2559 case EPOLL_CTL_ADD:
2560 if (PREDICT_FALSE (!event))
2561 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002562 VDBG (0, "EPOLL_CTL_ADD: NULL pointer to epoll_event structure!");
Florin Coras070453d2018-08-24 17:04:27 -07002563 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002564 }
Florin Coras134a9962018-08-28 11:32:04 -07002565 if (vep_session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002566 {
Florin Coras7e12d942018-06-27 14:32:43 -07002567 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002568 next_session = vcl_session_get_w_handle (wrk,
2569 vep_session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002570 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002571 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002572 VDBG (0, "EPOLL_CTL_ADD: Invalid vep.next_sid (%u) on "
2573 "vep_idx (%u)!", vep_session->vep.next_sh, vep_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002574 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002575 }
Florin Coras134a9962018-08-28 11:32:04 -07002576 ASSERT (next_session->vep.prev_sh == vep_handle);
2577 next_session->vep.prev_sh = session_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002578 }
Florin Coras134a9962018-08-28 11:32:04 -07002579 session->vep.next_sh = vep_session->vep.next_sh;
2580 session->vep.prev_sh = vep_handle;
2581 session->vep.vep_sh = vep_handle;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002582 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2583 session->vep.ev = *event;
Dave Wallace4878cbe2017-11-21 03:45:09 -05002584 session->is_vep = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002585 session->is_vep_session = 1;
Florin Coras134a9962018-08-28 11:32:04 -07002586 vep_session->vep.next_sh = session_handle;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08002587
Florin Corasa7a1a222018-12-30 17:11:31 -08002588 VDBG (1, "EPOLL_CTL_ADD: vep_sh %u, sh %u, events 0x%x, data 0x%llx!",
2589 vep_handle, session_handle, event->events, event->data.u64);
Florin Coras0d427d82018-06-27 03:24:07 -07002590 vcl_evt (VCL_EVT_EPOLL_CTLADD, session, event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002591 break;
2592
2593 case EPOLL_CTL_MOD:
2594 if (PREDICT_FALSE (!event))
2595 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002596 VDBG (0, "EPOLL_CTL_MOD: NULL pointer to epoll_event structure!");
Dave Wallacef7f809c2017-10-03 01:48:42 -04002597 rv = VPPCOM_EINVAL;
2598 goto done;
2599 }
Dave Wallace4878cbe2017-11-21 03:45:09 -05002600 else if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002601 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002602 VDBG (0, "sid %u EPOLL_CTL_MOD: not a vep session!",
2603 session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002604 rv = VPPCOM_EINVAL;
2605 goto done;
2606 }
Florin Coras134a9962018-08-28 11:32:04 -07002607 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002608 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002609 VDBG (0, "EPOLL_CTL_MOD: sh %u vep_sh (%u) != vep_sh (%u)!",
2610 session_handle, session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002611 rv = VPPCOM_EINVAL;
2612 goto done;
2613 }
2614 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
2615 session->vep.ev = *event;
Florin Corasa7a1a222018-12-30 17:11:31 -08002616 VDBG (1, "EPOLL_CTL_MOD: vep_sh %u, sh %u, events 0x%x, data 0x%llx!",
2617 vep_handle, session_handle, event->events, event->data.u64);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002618 break;
2619
2620 case EPOLL_CTL_DEL:
Dave Wallace4878cbe2017-11-21 03:45:09 -05002621 if (PREDICT_FALSE (!session->is_vep_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002622 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002623 VDBG (0, "EPOLL_CTL_DEL: %u not a vep session!", session_handle);
Dave Wallace4878cbe2017-11-21 03:45:09 -05002624 rv = VPPCOM_EINVAL;
2625 goto done;
2626 }
Florin Coras134a9962018-08-28 11:32:04 -07002627 else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
Dave Wallace4878cbe2017-11-21 03:45:09 -05002628 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002629 VDBG (0, "EPOLL_CTL_DEL: sh %u vep_sh (%u) != vep_sh (%u)!",
2630 session_handle, session->vep.vep_sh, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002631 rv = VPPCOM_EINVAL;
2632 goto done;
2633 }
2634
2635 vep_session->wait_cont_idx =
Florin Coras134a9962018-08-28 11:32:04 -07002636 (vep_session->wait_cont_idx == session_handle) ?
2637 session->vep.next_sh : vep_session->wait_cont_idx;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002638
Florin Coras134a9962018-08-28 11:32:04 -07002639 if (session->vep.prev_sh == vep_handle)
2640 vep_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002641 else
2642 {
Florin Coras7e12d942018-06-27 14:32:43 -07002643 vcl_session_t *prev_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002644 prev_session = vcl_session_get_w_handle (wrk, session->vep.prev_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002645 if (PREDICT_FALSE (!prev_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002646 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002647 VDBG (0, "EPOLL_CTL_DEL: Invalid prev_sid (%u) on sid (%u)!",
2648 session->vep.prev_sh, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002649 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002650 }
Florin Coras134a9962018-08-28 11:32:04 -07002651 ASSERT (prev_session->vep.next_sh == session_handle);
2652 prev_session->vep.next_sh = session->vep.next_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002653 }
Florin Coras134a9962018-08-28 11:32:04 -07002654 if (session->vep.next_sh != ~0)
Dave Wallacef7f809c2017-10-03 01:48:42 -04002655 {
Florin Coras7e12d942018-06-27 14:32:43 -07002656 vcl_session_t *next_session;
Florin Corasab2f6db2018-08-31 14:31:41 -07002657 next_session = vcl_session_get_w_handle (wrk, session->vep.next_sh);
Florin Coras070453d2018-08-24 17:04:27 -07002658 if (PREDICT_FALSE (!next_session))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002659 {
Florin Corasa7a1a222018-12-30 17:11:31 -08002660 VDBG (0, "EPOLL_CTL_DEL: Invalid next_sid (%u) on sid (%u)!",
2661 session->vep.next_sh, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002662 return VPPCOM_EBADFD;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002663 }
Florin Coras134a9962018-08-28 11:32:04 -07002664 ASSERT (next_session->vep.prev_sh == session_handle);
2665 next_session->vep.prev_sh = session->vep.prev_sh;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002666 }
2667
2668 memset (&session->vep, 0, sizeof (session->vep));
Florin Coras134a9962018-08-28 11:32:04 -07002669 session->vep.next_sh = ~0;
2670 session->vep.prev_sh = ~0;
2671 session->vep.vep_sh = ~0;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002672 session->is_vep_session = 0;
Florin Corasa7a1a222018-12-30 17:11:31 -08002673 VDBG (1, "EPOLL_CTL_DEL: vep_idx %u, sid %u!", vep_handle,
2674 session_handle);
Florin Coras134a9962018-08-28 11:32:04 -07002675 vcl_evt (VCL_EVT_EPOLL_CTLDEL, session, vep_sh);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002676 break;
2677
2678 default:
Florin Corasa7a1a222018-12-30 17:11:31 -08002679 VDBG (0, "Invalid operation (%d)!", op);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002680 rv = VPPCOM_EINVAL;
2681 }
2682
Florin Coras134a9962018-08-28 11:32:04 -07002683 vep_verify_epoll_chain (wrk, vep_handle);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002684
2685done:
Dave Wallacef7f809c2017-10-03 01:48:42 -04002686 return rv;
2687}
2688
Florin Coras86f04502018-09-12 16:08:01 -07002689static inline void
2690vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
2691 struct epoll_event *events, u32 * num_ev)
Florin Coras54693d22018-07-17 10:46:29 -07002692{
2693 session_disconnected_msg_t *disconnected_msg;
2694 session_connected_msg_t *connected_msg;
Florin Coras99368312018-08-02 10:45:44 -07002695 u32 sid = ~0, session_events;
Florin Coras3c7d4f92018-12-14 11:28:43 -08002696 u64 session_evt_data = ~0;
Florin Coras54693d22018-07-17 10:46:29 -07002697 vcl_session_t *session;
Florin Coras86f04502018-09-12 16:08:01 -07002698 u8 add_event = 0;
2699
2700 switch (e->event_type)
2701 {
2702 case FIFO_EVENT_APP_RX:
2703 ASSERT (e->fifo->client_thread_index == vcl_get_worker_index ());
2704 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2705 sid = e->fifo->client_session_index;
Florin Corasfa915f82018-12-26 16:29:06 -08002706 if (!(session = vcl_session_get (wrk, sid)))
2707 break;
Florin Coras86f04502018-09-12 16:08:01 -07002708 session_events = session->vep.ev.events;
Florin Corasaa27eb92018-10-13 12:20:01 -07002709 if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
Florin Coras86f04502018-09-12 16:08:01 -07002710 break;
2711 add_event = 1;
2712 events[*num_ev].events |= EPOLLIN;
2713 session_evt_data = session->vep.ev.data.u64;
Florin Corasaa27eb92018-10-13 12:20:01 -07002714 session->has_rx_evt = 1;
Florin Coras86f04502018-09-12 16:08:01 -07002715 break;
2716 case FIFO_EVENT_APP_TX:
2717 sid = e->fifo->client_session_index;
Florin Corasfa915f82018-12-26 16:29:06 -08002718 if (!(session = vcl_session_get (wrk, sid)))
2719 break;
Florin Coras86f04502018-09-12 16:08:01 -07002720 session_events = session->vep.ev.events;
2721 if (!(EPOLLOUT & session_events))
2722 break;
2723 add_event = 1;
2724 events[*num_ev].events |= EPOLLOUT;
2725 session_evt_data = session->vep.ev.data.u64;
2726 break;
2727 case SESSION_IO_EVT_CT_TX:
2728 vcl_fifo_rx_evt_valid_or_break (e->fifo);
2729 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0);
Florin Corasfa915f82018-12-26 16:29:06 -08002730 if (PREDICT_FALSE (!session))
2731 break;
Florin Coras86f04502018-09-12 16:08:01 -07002732 sid = session->session_index;
2733 session_events = session->vep.ev.events;
Florin Corasaa27eb92018-10-13 12:20:01 -07002734 if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
Florin Coras86f04502018-09-12 16:08:01 -07002735 break;
2736 add_event = 1;
2737 events[*num_ev].events |= EPOLLIN;
2738 session_evt_data = session->vep.ev.data.u64;
Florin Corasaa27eb92018-10-13 12:20:01 -07002739 session->has_rx_evt = 1;
Florin Coras86f04502018-09-12 16:08:01 -07002740 break;
2741 case SESSION_IO_EVT_CT_RX:
2742 session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1);
Florin Corasfa915f82018-12-26 16:29:06 -08002743 if (PREDICT_FALSE (!session))
2744 break;
Florin Coras86f04502018-09-12 16:08:01 -07002745 sid = session->session_index;
2746 session_events = session->vep.ev.events;
2747 if (!(EPOLLOUT & session_events))
2748 break;
2749 add_event = 1;
2750 events[*num_ev].events |= EPOLLOUT;
2751 session_evt_data = session->vep.ev.data.u64;
2752 break;
2753 case SESSION_CTRL_EVT_ACCEPTED:
Florin Coras3c7d4f92018-12-14 11:28:43 -08002754 session = vcl_session_accepted (wrk,
2755 (session_accepted_msg_t *) e->data);
Florin Coras86f04502018-09-12 16:08:01 -07002756 if (!session)
Florin Coras3c7d4f92018-12-14 11:28:43 -08002757 break;
Florin Coras86f04502018-09-12 16:08:01 -07002758
Florin Coras86f04502018-09-12 16:08:01 -07002759 session_events = session->vep.ev.events;
2760 if (!(EPOLLIN & session_events))
2761 break;
2762
2763 add_event = 1;
2764 events[*num_ev].events |= EPOLLIN;
2765 session_evt_data = session->vep.ev.data.u64;
2766 break;
2767 case SESSION_CTRL_EVT_CONNECTED:
2768 connected_msg = (session_connected_msg_t *) e->data;
2769 vcl_session_connected_handler (wrk, connected_msg);
2770 /* Generate EPOLLOUT because there's no connected event */
2771 sid = vcl_session_index_from_vpp_handle (wrk, connected_msg->handle);
Florin Corasfa915f82018-12-26 16:29:06 -08002772 if (!(session = vcl_session_get (wrk, sid)))
2773 break;
Florin Coras86f04502018-09-12 16:08:01 -07002774 session_events = session->vep.ev.events;
2775 if (EPOLLOUT & session_events)
2776 {
2777 add_event = 1;
2778 events[*num_ev].events |= EPOLLOUT;
2779 session_evt_data = session->vep.ev.data.u64;
2780 }
2781 break;
2782 case SESSION_CTRL_EVT_DISCONNECTED:
2783 disconnected_msg = (session_disconnected_msg_t *) e->data;
Florin Coras3c7d4f92018-12-14 11:28:43 -08002784 session = vcl_session_disconnected_handler (wrk, disconnected_msg);
2785 if (!session)
Florin Coras86f04502018-09-12 16:08:01 -07002786 break;
2787 add_event = 1;
2788 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2789 session_evt_data = session->vep.ev.data.u64;
2790 session_events = session->vep.ev.events;
2791 break;
2792 case SESSION_CTRL_EVT_RESET:
2793 sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
2794 if (!(session = vcl_session_get (wrk, sid)))
2795 break;
2796 add_event = 1;
2797 events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
2798 session_evt_data = session->vep.ev.data.u64;
2799 session_events = session->vep.ev.events;
2800 break;
Florin Coras30e79c22019-01-02 19:31:22 -08002801 case SESSION_CTRL_EVT_REQ_WORKER_UPDATE:
2802 vcl_session_req_worker_update_handler (wrk, e->data);
2803 break;
2804 case SESSION_CTRL_EVT_WORKER_UPDATE_REPLY:
2805 vcl_session_worker_update_reply_handler (wrk, e->data);
2806 break;
Florin Coras86f04502018-09-12 16:08:01 -07002807 default:
2808 VDBG (0, "unhandled: %u", e->event_type);
2809 break;
2810 }
2811
2812 if (add_event)
2813 {
2814 events[*num_ev].data.u64 = session_evt_data;
2815 if (EPOLLONESHOT & session_events)
2816 {
2817 session = vcl_session_get (wrk, sid);
2818 session->vep.ev.events = 0;
2819 }
2820 *num_ev += 1;
2821 }
2822}
2823
2824static int
2825vcl_epoll_wait_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
2826 struct epoll_event *events, u32 maxevents,
2827 double wait_for_time, u32 * num_ev)
2828{
Florin Coras99368312018-08-02 10:45:44 -07002829 svm_msg_q_msg_t *msg;
Florin Coras54693d22018-07-17 10:46:29 -07002830 session_event_t *e;
Florin Coras54693d22018-07-17 10:46:29 -07002831 int i;
2832
Florin Coras539663c2018-09-28 14:59:37 -07002833 if (vec_len (wrk->mq_msg_vector) && svm_msg_q_is_empty (mq))
2834 goto handle_dequeued;
2835
Florin Coras54693d22018-07-17 10:46:29 -07002836 svm_msg_q_lock (mq);
2837 if (svm_msg_q_is_empty (mq))
2838 {
2839 if (!wait_for_time)
2840 {
2841 svm_msg_q_unlock (mq);
2842 return 0;
2843 }
2844 else if (wait_for_time < 0)
2845 {
2846 svm_msg_q_wait (mq);
2847 }
2848 else
2849 {
Florin Coras60f1fc12018-08-16 14:57:31 -07002850 if (svm_msg_q_timedwait (mq, wait_for_time / 1e3))
Florin Coras54693d22018-07-17 10:46:29 -07002851 {
2852 svm_msg_q_unlock (mq);
2853 return 0;
2854 }
2855 }
2856 }
Florin Coras134a9962018-08-28 11:32:04 -07002857 vcl_mq_dequeue_batch (wrk, mq);
Florin Coras54693d22018-07-17 10:46:29 -07002858 svm_msg_q_unlock (mq);
2859
Florin Coras539663c2018-09-28 14:59:37 -07002860handle_dequeued:
Florin Coras134a9962018-08-28 11:32:04 -07002861 for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
Florin Coras54693d22018-07-17 10:46:29 -07002862 {
Florin Coras134a9962018-08-28 11:32:04 -07002863 msg = vec_elt_at_index (wrk->mq_msg_vector, i);
Florin Coras99368312018-08-02 10:45:44 -07002864 e = svm_msg_q_msg_data (mq, msg);
Florin Corasaa27eb92018-10-13 12:20:01 -07002865 if (*num_ev < maxevents)
2866 vcl_epoll_wait_handle_mq_event (wrk, e, events, num_ev);
2867 else
2868 vec_add1 (wrk->unhandled_evts_vector, *e);
Florin Coras99368312018-08-02 10:45:44 -07002869 svm_msg_q_free_msg (mq, msg);
Florin Coras54693d22018-07-17 10:46:29 -07002870 }
Florin Corasaa27eb92018-10-13 12:20:01 -07002871 vec_reset_length (wrk->mq_msg_vector);
Florin Coras30e79c22019-01-02 19:31:22 -08002872 vcl_handle_pending_wrk_updates (wrk);
Florin Coras54693d22018-07-17 10:46:29 -07002873 return *num_ev;
2874}
2875
Florin Coras99368312018-08-02 10:45:44 -07002876static int
Florin Coras134a9962018-08-28 11:32:04 -07002877vppcom_epoll_wait_condvar (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002878 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002879{
2880 vcl_cut_through_registration_t *cr;
2881 double total_wait = 0, wait_slice;
Florin Coras99368312018-08-02 10:45:44 -07002882 int rv;
2883
2884 wait_for_time = (wait_for_time == -1) ? (double) 10e9 : wait_for_time;
Florin Coras134a9962018-08-28 11:32:04 -07002885 wait_slice = wrk->cut_through_registrations ? 10e-6 : wait_for_time;
Florin Coras99368312018-08-02 10:45:44 -07002886
2887 do
2888 {
Florin Coras134a9962018-08-28 11:32:04 -07002889 vcl_ct_registration_lock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002890 /* *INDENT-OFF* */
Florin Coras134a9962018-08-28 11:32:04 -07002891 pool_foreach (cr, wrk->cut_through_registrations, ({
Florin Coras86f04502018-09-12 16:08:01 -07002892 vcl_epoll_wait_handle_mq (wrk, cr->mq, events, maxevents, 0, &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002893 }));
2894 /* *INDENT-ON* */
Florin Coras134a9962018-08-28 11:32:04 -07002895 vcl_ct_registration_unlock (wrk);
Florin Coras99368312018-08-02 10:45:44 -07002896
Florin Coras134a9962018-08-28 11:32:04 -07002897 rv = vcl_epoll_wait_handle_mq (wrk, wrk->app_event_queue, events,
Florin Coras86f04502018-09-12 16:08:01 -07002898 maxevents, n_evts ? 0 : wait_slice,
2899 &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002900 if (rv)
2901 total_wait += wait_slice;
Florin Coras86f04502018-09-12 16:08:01 -07002902 if (n_evts)
2903 return n_evts;
Florin Coras99368312018-08-02 10:45:44 -07002904 }
2905 while (total_wait < wait_for_time);
Florin Coras86f04502018-09-12 16:08:01 -07002906 return n_evts;
Florin Coras99368312018-08-02 10:45:44 -07002907}
2908
2909static int
Florin Coras134a9962018-08-28 11:32:04 -07002910vppcom_epoll_wait_eventfd (vcl_worker_t * wrk, struct epoll_event *events,
Florin Coras86f04502018-09-12 16:08:01 -07002911 int maxevents, u32 n_evts, double wait_for_time)
Florin Coras99368312018-08-02 10:45:44 -07002912{
2913 vcl_mq_evt_conn_t *mqc;
2914 int __clib_unused n_read;
2915 int n_mq_evts, i;
Florin Coras99368312018-08-02 10:45:44 -07002916 u64 buf;
2917
Florin Coras134a9962018-08-28 11:32:04 -07002918 vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
Florin Corasa4878ed2018-10-12 13:09:36 -07002919again:
Florin Coras134a9962018-08-28 11:32:04 -07002920 n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
2921 vec_len (wrk->mq_events), wait_for_time);
Florin Coras99368312018-08-02 10:45:44 -07002922 for (i = 0; i < n_mq_evts; i++)
2923 {
Florin Coras134a9962018-08-28 11:32:04 -07002924 mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
Florin Coras99368312018-08-02 10:45:44 -07002925 n_read = read (mqc->mq_fd, &buf, sizeof (buf));
Florin Coras134a9962018-08-28 11:32:04 -07002926 vcl_epoll_wait_handle_mq (wrk, mqc->mq, events, maxevents, 0, &n_evts);
Florin Coras99368312018-08-02 10:45:44 -07002927 }
Florin Corasa4878ed2018-10-12 13:09:36 -07002928 if (!n_evts && n_mq_evts > 0)
2929 goto again;
Florin Coras99368312018-08-02 10:45:44 -07002930
2931 return (int) n_evts;
2932}
2933
Dave Wallacef7f809c2017-10-03 01:48:42 -04002934int
Florin Coras134a9962018-08-28 11:32:04 -07002935vppcom_epoll_wait (uint32_t vep_handle, struct epoll_event *events,
Dave Wallacef7f809c2017-10-03 01:48:42 -04002936 int maxevents, double wait_for_time)
2937{
Florin Coras134a9962018-08-28 11:32:04 -07002938 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002939 vcl_session_t *vep_session;
Florin Coras86f04502018-09-12 16:08:01 -07002940 u32 n_evts = 0;
2941 int i;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002942
2943 if (PREDICT_FALSE (maxevents <= 0))
2944 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002945 clib_warning ("VCL<%d>: ERROR: Invalid maxevents (%d)!",
Dave Wallace4878cbe2017-11-21 03:45:09 -05002946 getpid (), maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002947 return VPPCOM_EINVAL;
2948 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002949
Florin Coras134a9962018-08-28 11:32:04 -07002950 vep_session = vcl_session_get_w_handle (wrk, vep_handle);
Florin Coras14598772018-09-04 19:47:52 -07002951 if (!vep_session)
2952 return VPPCOM_EBADFD;
2953
Florin Coras54693d22018-07-17 10:46:29 -07002954 if (PREDICT_FALSE (!vep_session->is_vep))
Dave Wallacef7f809c2017-10-03 01:48:42 -04002955 {
Dave Wallace048b1d62018-01-03 22:24:41 -05002956 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
Florin Coras134a9962018-08-28 11:32:04 -07002957 getpid (), vep_handle);
Florin Coras54693d22018-07-17 10:46:29 -07002958 return VPPCOM_EINVAL;
Dave Wallacef7f809c2017-10-03 01:48:42 -04002959 }
Florin Coras54693d22018-07-17 10:46:29 -07002960
2961 memset (events, 0, sizeof (*events) * maxevents);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002962
Florin Coras86f04502018-09-12 16:08:01 -07002963 if (vec_len (wrk->unhandled_evts_vector))
2964 {
2965 for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
2966 {
2967 vcl_epoll_wait_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i],
2968 events, &n_evts);
2969 if (n_evts == maxevents)
2970 {
2971 i += 1;
2972 break;
2973 }
2974 }
Dave Wallacef7f809c2017-10-03 01:48:42 -04002975
Florin Coras86f04502018-09-12 16:08:01 -07002976 vec_delete (wrk->unhandled_evts_vector, i, 0);
2977 }
2978
2979 if (vcm->cfg.use_mq_eventfd)
2980 return vppcom_epoll_wait_eventfd (wrk, events, maxevents, n_evts,
2981 wait_for_time);
2982
2983 return vppcom_epoll_wait_condvar (wrk, events, maxevents, n_evts,
2984 wait_for_time);
Dave Wallacef7f809c2017-10-03 01:48:42 -04002985}
2986
Dave Wallace35830af2017-10-09 01:43:42 -04002987int
Florin Coras134a9962018-08-28 11:32:04 -07002988vppcom_session_attr (uint32_t session_handle, uint32_t op,
Dave Wallace35830af2017-10-09 01:43:42 -04002989 void *buffer, uint32_t * buflen)
2990{
Florin Coras134a9962018-08-28 11:32:04 -07002991 vcl_worker_t *wrk = vcl_worker_get_current ();
Florin Coras7e12d942018-06-27 14:32:43 -07002992 vcl_session_t *session;
Dave Wallace35830af2017-10-09 01:43:42 -04002993 int rv = VPPCOM_OK;
Florin Coras7baeb712019-01-04 17:05:43 -08002994 u32 *flags = buffer, tmp_flags = 0;
Steven2199aab2017-10-15 20:18:47 -07002995 vppcom_endpt_t *ep = buffer;
Dave Wallace35830af2017-10-09 01:43:42 -04002996
Florin Coras134a9962018-08-28 11:32:04 -07002997 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07002998 if (!session)
2999 return VPPCOM_EBADFD;
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08003000
Dave Wallace35830af2017-10-09 01:43:42 -04003001 switch (op)
3002 {
3003 case VPPCOM_ATTR_GET_NREAD:
Florin Coras54693d22018-07-17 10:46:29 -07003004 rv = vppcom_session_read_ready (session);
Florin Coras7baeb712019-01-04 17:05:43 -08003005 VDBG (2, "VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d", rv);
Dave Wallace35830af2017-10-09 01:43:42 -04003006 break;
3007
Dave Wallace227867f2017-11-13 21:21:53 -05003008 case VPPCOM_ATTR_GET_NWRITE:
Florin Coras134a9962018-08-28 11:32:04 -07003009 rv = vppcom_session_write_ready (session);
Florin Coras0d427d82018-06-27 03:24:07 -07003010 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d",
Florin Coras134a9962018-08-28 11:32:04 -07003011 getpid (), session_handle, rv);
Dave Wallace35830af2017-10-09 01:43:42 -04003012 break;
3013
3014 case VPPCOM_ATTR_GET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05003015 if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04003016 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08003017 *flags = O_RDWR | (VCL_SESS_ATTR_TEST (session->attr,
3018 VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04003019 *buflen = sizeof (*flags);
Florin Coras0d427d82018-06-27 03:24:07 -07003020 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_FLAGS: sid %u, flags = 0x%08x, "
3021 "is_nonblocking = %u", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07003022 session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07003023 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04003024 }
3025 else
3026 rv = VPPCOM_EINVAL;
3027 break;
3028
3029 case VPPCOM_ATTR_SET_FLAGS:
Dave Wallace048b1d62018-01-03 22:24:41 -05003030 if (PREDICT_TRUE (buffer && buflen && (*buflen == sizeof (*flags))))
Dave Wallace35830af2017-10-09 01:43:42 -04003031 {
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08003032 if (*flags & O_NONBLOCK)
3033 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
3034 else
3035 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_NONBLOCK);
3036
Florin Coras0d427d82018-06-27 03:24:07 -07003037 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_FLAGS: sid %u, flags = 0x%08x,"
3038 " is_nonblocking = %u",
Florin Coras134a9962018-08-28 11:32:04 -07003039 getpid (), session_handle, *flags,
Florin Coras0d427d82018-06-27 03:24:07 -07003040 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
Dave Wallace35830af2017-10-09 01:43:42 -04003041 }
3042 else
3043 rv = VPPCOM_EINVAL;
3044 break;
3045
3046 case VPPCOM_ATTR_GET_PEER_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05003047 if (PREDICT_TRUE (buffer && buflen &&
3048 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04003049 {
Florin Coras7e12d942018-06-27 14:32:43 -07003050 ep->is_ip4 = session->transport.is_ip4;
3051 ep->port = session->transport.rmt_port;
3052 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05003053 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
3054 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07003055 else
Dave Barach178cf492018-11-13 16:34:13 -05003056 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
3057 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07003058 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07003059 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = %u, "
3060 "addr = %U, port %u", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07003061 session_handle, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07003062 &session->transport.rmt_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07003063 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
3064 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04003065 }
3066 else
3067 rv = VPPCOM_EINVAL;
3068 break;
3069
3070 case VPPCOM_ATTR_GET_LCL_ADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05003071 if (PREDICT_TRUE (buffer && buflen &&
3072 (*buflen >= sizeof (*ep)) && ep->ip))
Dave Wallace35830af2017-10-09 01:43:42 -04003073 {
Florin Coras7e12d942018-06-27 14:32:43 -07003074 ep->is_ip4 = session->transport.is_ip4;
3075 ep->port = session->transport.lcl_port;
3076 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05003077 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip4,
3078 sizeof (ip4_address_t));
Steven2199aab2017-10-15 20:18:47 -07003079 else
Dave Barach178cf492018-11-13 16:34:13 -05003080 clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip6,
3081 sizeof (ip6_address_t));
Steven2199aab2017-10-15 20:18:47 -07003082 *buflen = sizeof (*ep);
Florin Coras0d427d82018-06-27 03:24:07 -07003083 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = %u,"
3084 " addr = %U port %d", getpid (),
Florin Coras134a9962018-08-28 11:32:04 -07003085 session_handle, ep->is_ip4, format_ip46_address,
Florin Coras7e12d942018-06-27 14:32:43 -07003086 &session->transport.lcl_ip,
Florin Coras0d427d82018-06-27 03:24:07 -07003087 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
3088 clib_net_to_host_u16 (ep->port));
Dave Wallace35830af2017-10-09 01:43:42 -04003089 }
3090 else
3091 rv = VPPCOM_EINVAL;
3092 break;
Stevenb5a11602017-10-11 09:59:30 -07003093
Dave Wallace048b1d62018-01-03 22:24:41 -05003094 case VPPCOM_ATTR_GET_LIBC_EPFD:
3095 rv = session->libc_epfd;
Florin Coras0d427d82018-06-27 03:24:07 -07003096 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d",
3097 getpid (), rv);
Dave Wallace048b1d62018-01-03 22:24:41 -05003098 break;
3099
3100 case VPPCOM_ATTR_SET_LIBC_EPFD:
3101 if (PREDICT_TRUE (buffer && buflen &&
3102 (*buflen == sizeof (session->libc_epfd))))
3103 {
3104 session->libc_epfd = *(int *) buffer;
3105 *buflen = sizeof (session->libc_epfd);
3106
Florin Coras0d427d82018-06-27 03:24:07 -07003107 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_LIBC_EPFD: libc_epfd %d, "
3108 "buflen %d", getpid (), session->libc_epfd, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003109 }
3110 else
3111 rv = VPPCOM_EINVAL;
3112 break;
3113
3114 case VPPCOM_ATTR_GET_PROTOCOL:
3115 if (buffer && buflen && (*buflen >= sizeof (int)))
3116 {
Florin Coras7e12d942018-06-27 14:32:43 -07003117 *(int *) buffer = session->session_type;
Dave Wallace048b1d62018-01-03 22:24:41 -05003118 *buflen = sizeof (int);
3119
Florin Coras0d427d82018-06-27 03:24:07 -07003120 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_PROTOCOL: %d (%s), buflen %d",
3121 getpid (), *(int *) buffer, *(int *) buffer ? "UDP" : "TCP",
3122 *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003123 }
3124 else
3125 rv = VPPCOM_EINVAL;
3126 break;
3127
3128 case VPPCOM_ATTR_GET_LISTEN:
3129 if (buffer && buflen && (*buflen >= sizeof (int)))
3130 {
3131 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3132 VCL_SESS_ATTR_LISTEN);
3133 *buflen = sizeof (int);
3134
Florin Coras0d427d82018-06-27 03:24:07 -07003135 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LISTEN: %d, buflen %d",
3136 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003137 }
3138 else
3139 rv = VPPCOM_EINVAL;
3140 break;
3141
3142 case VPPCOM_ATTR_GET_ERROR:
3143 if (buffer && buflen && (*buflen >= sizeof (int)))
3144 {
3145 *(int *) buffer = 0;
3146 *buflen = sizeof (int);
3147
Florin Coras0d427d82018-06-27 03:24:07 -07003148 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_ERROR: %d, buflen %d, #VPP-TBD#",
3149 getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003150 }
3151 else
3152 rv = VPPCOM_EINVAL;
3153 break;
3154
3155 case VPPCOM_ATTR_GET_TX_FIFO_LEN:
3156 if (buffer && buflen && (*buflen >= sizeof (u32)))
3157 {
Dave Wallace048b1d62018-01-03 22:24:41 -05003158
3159 /* VPP-TBD */
3160 *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08003161 session->tx_fifo ? session->tx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05003162 vcm->cfg.tx_fifo_size);
3163 *buflen = sizeof (u32);
3164
Florin Coras0d427d82018-06-27 03:24:07 -07003165 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), "
3166 "buflen %d, #VPP-TBD#", getpid (),
3167 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003168 }
3169 else
3170 rv = VPPCOM_EINVAL;
3171 break;
3172
3173 case VPPCOM_ATTR_SET_TX_FIFO_LEN:
3174 if (buffer && buflen && (*buflen == sizeof (u32)))
3175 {
3176 /* VPP-TBD */
3177 session->sndbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07003178 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), "
3179 "buflen %d, #VPP-TBD#", getpid (),
3180 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003181 }
3182 else
3183 rv = VPPCOM_EINVAL;
3184 break;
3185
3186 case VPPCOM_ATTR_GET_RX_FIFO_LEN:
3187 if (buffer && buflen && (*buflen >= sizeof (u32)))
3188 {
Dave Wallace048b1d62018-01-03 22:24:41 -05003189
3190 /* VPP-TBD */
3191 *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size :
Keith Burns (alagalah)9b793772018-02-16 08:20:56 -08003192 session->rx_fifo ? session->rx_fifo->nitems :
Dave Wallace048b1d62018-01-03 22:24:41 -05003193 vcm->cfg.rx_fifo_size);
3194 *buflen = sizeof (u32);
3195
Florin Coras0d427d82018-06-27 03:24:07 -07003196 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_RX_FIFO_LEN: %u (0x%x), "
3197 "buflen %d, #VPP-TBD#", getpid (),
3198 *(size_t *) buffer, *(size_t *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003199 }
3200 else
3201 rv = VPPCOM_EINVAL;
3202 break;
3203
3204 case VPPCOM_ATTR_SET_RX_FIFO_LEN:
3205 if (buffer && buflen && (*buflen == sizeof (u32)))
3206 {
3207 /* VPP-TBD */
3208 session->rcvbuf_size = *(u32 *) buffer;
Florin Coras0d427d82018-06-27 03:24:07 -07003209 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_RX_FIFO_LEN: %u (0x%x), "
3210 "buflen %d, #VPP-TBD#", getpid (),
3211 session->sndbuf_size, session->sndbuf_size, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003212 }
3213 else
3214 rv = VPPCOM_EINVAL;
3215 break;
3216
3217 case VPPCOM_ATTR_GET_REUSEADDR:
3218 if (buffer && buflen && (*buflen >= sizeof (int)))
3219 {
3220 /* VPP-TBD */
3221 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3222 VCL_SESS_ATTR_REUSEADDR);
3223 *buflen = sizeof (int);
3224
Florin Coras0d427d82018-06-27 03:24:07 -07003225 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEADDR: %d, "
3226 "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003227 }
3228 else
3229 rv = VPPCOM_EINVAL;
3230 break;
3231
Stevenb5a11602017-10-11 09:59:30 -07003232 case VPPCOM_ATTR_SET_REUSEADDR:
Dave Wallace048b1d62018-01-03 22:24:41 -05003233 if (buffer && buflen && (*buflen == sizeof (int)) &&
3234 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
3235 {
3236 /* VPP-TBD */
3237 if (*(int *) buffer)
3238 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEADDR);
3239 else
3240 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEADDR);
3241
Florin Coras0d427d82018-06-27 03:24:07 -07003242 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEADDR: %d, buflen %d,"
3243 " #VPP-TBD#", getpid (),
3244 VCL_SESS_ATTR_TEST (session->attr,
3245 VCL_SESS_ATTR_REUSEADDR), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003246 }
3247 else
3248 rv = VPPCOM_EINVAL;
3249 break;
3250
3251 case VPPCOM_ATTR_GET_REUSEPORT:
3252 if (buffer && buflen && (*buflen >= sizeof (int)))
3253 {
3254 /* VPP-TBD */
3255 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3256 VCL_SESS_ATTR_REUSEPORT);
3257 *buflen = sizeof (int);
3258
Florin Coras0d427d82018-06-27 03:24:07 -07003259 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEPORT: %d, buflen %d,"
3260 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003261 }
3262 else
3263 rv = VPPCOM_EINVAL;
3264 break;
3265
3266 case VPPCOM_ATTR_SET_REUSEPORT:
3267 if (buffer && buflen && (*buflen == sizeof (int)) &&
3268 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
3269 {
3270 /* VPP-TBD */
3271 if (*(int *) buffer)
3272 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEPORT);
3273 else
3274 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEPORT);
3275
Florin Coras0d427d82018-06-27 03:24:07 -07003276 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEPORT: %d, buflen %d,"
3277 " #VPP-TBD#", getpid (),
3278 VCL_SESS_ATTR_TEST (session->attr,
3279 VCL_SESS_ATTR_REUSEPORT), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003280 }
3281 else
3282 rv = VPPCOM_EINVAL;
3283 break;
3284
3285 case VPPCOM_ATTR_GET_BROADCAST:
3286 if (buffer && buflen && (*buflen >= sizeof (int)))
3287 {
3288 /* VPP-TBD */
3289 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3290 VCL_SESS_ATTR_BROADCAST);
3291 *buflen = sizeof (int);
3292
Florin Coras0d427d82018-06-27 03:24:07 -07003293 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_BROADCAST: %d, buflen %d,"
3294 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003295 }
3296 else
3297 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003298 break;
3299
3300 case VPPCOM_ATTR_SET_BROADCAST:
Dave Wallace048b1d62018-01-03 22:24:41 -05003301 if (buffer && buflen && (*buflen == sizeof (int)))
3302 {
3303 /* VPP-TBD */
3304 if (*(int *) buffer)
3305 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_BROADCAST);
3306 else
3307 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_BROADCAST);
3308
Florin Coras0d427d82018-06-27 03:24:07 -07003309 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_BROADCAST: %d, buflen %d, "
3310 "#VPP-TBD#", getpid (),
3311 VCL_SESS_ATTR_TEST (session->attr,
3312 VCL_SESS_ATTR_BROADCAST), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003313 }
3314 else
3315 rv = VPPCOM_EINVAL;
3316 break;
3317
3318 case VPPCOM_ATTR_GET_V6ONLY:
3319 if (buffer && buflen && (*buflen >= sizeof (int)))
3320 {
3321 /* VPP-TBD */
3322 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3323 VCL_SESS_ATTR_V6ONLY);
3324 *buflen = sizeof (int);
3325
Florin Coras0d427d82018-06-27 03:24:07 -07003326 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_V6ONLY: %d, buflen %d, "
3327 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003328 }
3329 else
3330 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003331 break;
3332
3333 case VPPCOM_ATTR_SET_V6ONLY:
Dave Wallace048b1d62018-01-03 22:24:41 -05003334 if (buffer && buflen && (*buflen == sizeof (int)))
3335 {
3336 /* VPP-TBD */
3337 if (*(int *) buffer)
3338 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_V6ONLY);
3339 else
3340 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_V6ONLY);
3341
Florin Coras0d427d82018-06-27 03:24:07 -07003342 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_V6ONLY: %d, buflen %d, "
3343 "#VPP-TBD#", getpid (),
3344 VCL_SESS_ATTR_TEST (session->attr,
3345 VCL_SESS_ATTR_V6ONLY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003346 }
3347 else
3348 rv = VPPCOM_EINVAL;
3349 break;
3350
3351 case VPPCOM_ATTR_GET_KEEPALIVE:
3352 if (buffer && buflen && (*buflen >= sizeof (int)))
3353 {
3354 /* VPP-TBD */
3355 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3356 VCL_SESS_ATTR_KEEPALIVE);
3357 *buflen = sizeof (int);
3358
Florin Coras0d427d82018-06-27 03:24:07 -07003359 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_KEEPALIVE: %d, buflen %d, "
3360 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003361 }
3362 else
3363 rv = VPPCOM_EINVAL;
Stevenb5a11602017-10-11 09:59:30 -07003364 break;
Stevenbccd3392017-10-12 20:42:21 -07003365
3366 case VPPCOM_ATTR_SET_KEEPALIVE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003367 if (buffer && buflen && (*buflen == sizeof (int)))
3368 {
3369 /* VPP-TBD */
3370 if (*(int *) buffer)
3371 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3372 else
3373 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_KEEPALIVE);
3374
Florin Coras0d427d82018-06-27 03:24:07 -07003375 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_KEEPALIVE: %d, buflen %d, "
3376 "#VPP-TBD#", getpid (),
3377 VCL_SESS_ATTR_TEST (session->attr,
3378 VCL_SESS_ATTR_KEEPALIVE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003379 }
3380 else
3381 rv = VPPCOM_EINVAL;
3382 break;
3383
3384 case VPPCOM_ATTR_GET_TCP_NODELAY:
3385 if (buffer && buflen && (*buflen >= sizeof (int)))
3386 {
3387 /* VPP-TBD */
3388 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3389 VCL_SESS_ATTR_TCP_NODELAY);
3390 *buflen = sizeof (int);
3391
Florin Coras0d427d82018-06-27 03:24:07 -07003392 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_NODELAY: %d, buflen %d, "
3393 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003394 }
3395 else
3396 rv = VPPCOM_EINVAL;
3397 break;
3398
3399 case VPPCOM_ATTR_SET_TCP_NODELAY:
3400 if (buffer && buflen && (*buflen == sizeof (int)))
3401 {
3402 /* VPP-TBD */
3403 if (*(int *) buffer)
3404 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3405 else
3406 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
3407
Florin Coras0d427d82018-06-27 03:24:07 -07003408 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_NODELAY: %d, buflen %d, "
3409 "#VPP-TBD#", getpid (),
3410 VCL_SESS_ATTR_TEST (session->attr,
3411 VCL_SESS_ATTR_TCP_NODELAY), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003412 }
3413 else
3414 rv = VPPCOM_EINVAL;
3415 break;
3416
3417 case VPPCOM_ATTR_GET_TCP_KEEPIDLE:
3418 if (buffer && buflen && (*buflen >= sizeof (int)))
3419 {
3420 /* VPP-TBD */
3421 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3422 VCL_SESS_ATTR_TCP_KEEPIDLE);
3423 *buflen = sizeof (int);
3424
Florin Coras0d427d82018-06-27 03:24:07 -07003425 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPIDLE: %d, buflen %d, "
3426 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003427 }
3428 else
3429 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003430 break;
3431
3432 case VPPCOM_ATTR_SET_TCP_KEEPIDLE:
Dave Wallace048b1d62018-01-03 22:24:41 -05003433 if (buffer && buflen && (*buflen == sizeof (int)))
3434 {
3435 /* VPP-TBD */
3436 if (*(int *) buffer)
3437 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3438 else
3439 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
3440
Florin Coras0d427d82018-06-27 03:24:07 -07003441 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPIDLE: %d, buflen %d, "
3442 "#VPP-TBD#", getpid (),
3443 VCL_SESS_ATTR_TEST (session->attr,
3444 VCL_SESS_ATTR_TCP_KEEPIDLE), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003445 }
3446 else
3447 rv = VPPCOM_EINVAL;
3448 break;
3449
3450 case VPPCOM_ATTR_GET_TCP_KEEPINTVL:
3451 if (buffer && buflen && (*buflen >= sizeof (int)))
3452 {
3453 /* VPP-TBD */
3454 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
3455 VCL_SESS_ATTR_TCP_KEEPINTVL);
3456 *buflen = sizeof (int);
3457
Florin Coras0d427d82018-06-27 03:24:07 -07003458 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPINTVL: %d, buflen %d, "
3459 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003460 }
3461 else
3462 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003463 break;
3464
3465 case VPPCOM_ATTR_SET_TCP_KEEPINTVL:
Dave Wallace048b1d62018-01-03 22:24:41 -05003466 if (buffer && buflen && (*buflen == sizeof (int)))
3467 {
3468 /* VPP-TBD */
3469 if (*(int *) buffer)
3470 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3471 else
3472 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
3473
Florin Coras0d427d82018-06-27 03:24:07 -07003474 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPINTVL: %d, buflen %d, "
3475 "#VPP-TBD#", getpid (),
3476 VCL_SESS_ATTR_TEST (session->attr,
3477 VCL_SESS_ATTR_TCP_KEEPINTVL), *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003478 }
3479 else
3480 rv = VPPCOM_EINVAL;
3481 break;
3482
3483 case VPPCOM_ATTR_GET_TCP_USER_MSS:
3484 if (buffer && buflen && (*buflen >= sizeof (u32)))
3485 {
3486 /* VPP-TBD */
3487 *(u32 *) buffer = session->user_mss;
3488 *buflen = sizeof (int);
3489
Florin Coras0d427d82018-06-27 03:24:07 -07003490 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d,"
3491 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003492 }
3493 else
3494 rv = VPPCOM_EINVAL;
3495 break;
3496
3497 case VPPCOM_ATTR_SET_TCP_USER_MSS:
3498 if (buffer && buflen && (*buflen == sizeof (u32)))
3499 {
3500 /* VPP-TBD */
3501 session->user_mss = *(u32 *) buffer;
3502
Florin Coras0d427d82018-06-27 03:24:07 -07003503 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_USER_MSS: %u, buflen %d, "
3504 "#VPP-TBD#", getpid (), session->user_mss, *buflen);
Dave Wallace048b1d62018-01-03 22:24:41 -05003505 }
3506 else
3507 rv = VPPCOM_EINVAL;
Stevenbccd3392017-10-12 20:42:21 -07003508 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003509
Florin Coras47c40e22018-11-26 17:01:36 -08003510 case VPPCOM_ATTR_GET_REFCNT:
3511 rv = vcl_session_get_refcnt (session);
3512 break;
3513
Florin Coras7baeb712019-01-04 17:05:43 -08003514 case VPPCOM_ATTR_SET_SHUT:
3515 if (*flags == SHUT_RD || *flags == SHUT_RDWR)
3516 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_SHUT_RD);
3517 if (*flags == SHUT_WR || *flags == SHUT_RDWR)
3518 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_SHUT_WR);
3519 break;
3520
3521 case VPPCOM_ATTR_GET_SHUT:
3522 if (VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_SHUT_RD))
3523 tmp_flags = 1;
3524 if (VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_SHUT_WR))
3525 tmp_flags |= 2;
3526 if (tmp_flags == 1)
3527 *(int *) buffer = SHUT_RD;
3528 else if (tmp_flags == 2)
3529 *(int *) buffer = SHUT_WR;
3530 else if (tmp_flags == 3)
3531 *(int *) buffer = SHUT_RDWR;
3532 *buflen = sizeof (int);
3533 break;
Dave Wallacee22aa742017-10-20 12:30:38 -04003534 default:
3535 rv = VPPCOM_EINVAL;
3536 break;
Dave Wallace35830af2017-10-09 01:43:42 -04003537 }
3538
Dave Wallace35830af2017-10-09 01:43:42 -04003539 return rv;
3540}
3541
Stevenac1f96d2017-10-24 16:03:58 -07003542int
Florin Coras134a9962018-08-28 11:32:04 -07003543vppcom_session_recvfrom (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003544 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3545{
Florin Coras134a9962018-08-28 11:32:04 -07003546 vcl_worker_t *wrk = vcl_worker_get_current ();
Stevenac1f96d2017-10-24 16:03:58 -07003547 int rv = VPPCOM_OK;
Florin Coras7e12d942018-06-27 14:32:43 -07003548 vcl_session_t *session = 0;
Stevenac1f96d2017-10-24 16:03:58 -07003549
3550 if (ep)
3551 {
Florin Coras134a9962018-08-28 11:32:04 -07003552 session = vcl_session_get_w_handle (wrk, session_handle);
Florin Coras070453d2018-08-24 17:04:27 -07003553 if (PREDICT_FALSE (!session))
Stevenac1f96d2017-10-24 16:03:58 -07003554 {
Florin Coras0d427d82018-06-27 03:24:07 -07003555 VDBG (0, "VCL<%d>: invalid session, sid (%u) has been closed!",
Florin Coras134a9962018-08-28 11:32:04 -07003556 getpid (), session_handle);
Florin Coras460dce62018-07-27 05:45:06 -07003557 return VPPCOM_EBADFD;
Stevenac1f96d2017-10-24 16:03:58 -07003558 }
Florin Coras7e12d942018-06-27 14:32:43 -07003559 ep->is_ip4 = session->transport.is_ip4;
3560 ep->port = session->transport.rmt_port;
Stevenac1f96d2017-10-24 16:03:58 -07003561 }
Steven58f464e2017-10-25 12:33:12 -07003562
3563 if (flags == 0)
Florin Coras134a9962018-08-28 11:32:04 -07003564 rv = vppcom_session_read (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003565 else if (flags & MSG_PEEK)
Florin Coras134a9962018-08-28 11:32:04 -07003566 rv = vppcom_session_peek (session_handle, buffer, buflen);
Stevenac1f96d2017-10-24 16:03:58 -07003567 else
3568 {
Florin Corasa7a1a222018-12-30 17:11:31 -08003569 VDBG (0, "Unsupport flags for recvfrom %d", flags);
Florin Coras460dce62018-07-27 05:45:06 -07003570 return VPPCOM_EAFNOSUPPORT;
Stevenac1f96d2017-10-24 16:03:58 -07003571 }
3572
Florin Coras99368312018-08-02 10:45:44 -07003573 if (ep)
3574 {
3575 if (session->transport.is_ip4)
Dave Barach178cf492018-11-13 16:34:13 -05003576 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
3577 sizeof (ip4_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003578 else
Dave Barach178cf492018-11-13 16:34:13 -05003579 clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
3580 sizeof (ip6_address_t));
Florin Coras99368312018-08-02 10:45:44 -07003581 }
Florin Coras460dce62018-07-27 05:45:06 -07003582
Stevenac1f96d2017-10-24 16:03:58 -07003583 return rv;
3584}
3585
3586int
Florin Coras134a9962018-08-28 11:32:04 -07003587vppcom_session_sendto (uint32_t session_handle, void *buffer,
Stevenac1f96d2017-10-24 16:03:58 -07003588 uint32_t buflen, int flags, vppcom_endpt_t * ep)
3589{
Dave Wallace617dffa2017-10-26 14:47:06 -04003590 if (!buffer)
3591 return VPPCOM_EINVAL;
3592
3593 if (ep)
3594 {
3595 // TBD
3596 return VPPCOM_EINVAL;
3597 }
3598
3599 if (flags)
3600 {
3601 // TBD check the flags and do the right thing
Florin Coras0d427d82018-06-27 03:24:07 -07003602 VDBG (2, "VCL<%d>: handling flags 0x%u (%d) not implemented yet.",
3603 getpid (), flags, flags);
Dave Wallace617dffa2017-10-26 14:47:06 -04003604 }
3605
Florin Coras42ceddb2018-12-12 10:56:01 -08003606 return (vppcom_session_write_inline (session_handle, buffer, buflen, 1));
Stevenac1f96d2017-10-24 16:03:58 -07003607}
3608
Dave Wallace048b1d62018-01-03 22:24:41 -05003609int
3610vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time)
3611{
Florin Coras134a9962018-08-28 11:32:04 -07003612 vcl_worker_t *wrk = vcl_worker_get_current ();
3613 f64 timeout = clib_time_now (&wrk->clib_time) + wait_for_time;
Dave Wallace048b1d62018-01-03 22:24:41 -05003614 u32 i, keep_trying = 1;
Florin Coras6917b942018-11-13 22:44:54 -08003615 svm_msg_q_msg_t msg;
3616 session_event_t *e;
Dave Wallace048b1d62018-01-03 22:24:41 -05003617 int rv, num_ev = 0;
3618
Florin Coras0d427d82018-06-27 03:24:07 -07003619 VDBG (3, "VCL<%d>: vp %p, nsids %u, wait_for_time %f",
3620 getpid (), vp, n_sids, wait_for_time);
Dave Wallace048b1d62018-01-03 22:24:41 -05003621
3622 if (!vp)
3623 return VPPCOM_EFAULT;
3624
3625 do
3626 {
Florin Coras7e12d942018-06-27 14:32:43 -07003627 vcl_session_t *session;
Dave Wallace048b1d62018-01-03 22:24:41 -05003628
Florin Coras6917b942018-11-13 22:44:54 -08003629 /* Dequeue all events and drop all unhandled io events */
3630 while (svm_msg_q_sub (wrk->app_event_queue, &msg, SVM_Q_NOWAIT, 0) == 0)
3631 {
3632 e = svm_msg_q_msg_data (wrk->app_event_queue, &msg);
3633 vcl_handle_mq_event (wrk, e);
3634 svm_msg_q_free_msg (wrk->app_event_queue, &msg);
3635 }
3636 vec_reset_length (wrk->unhandled_evts_vector);
3637
Dave Wallace048b1d62018-01-03 22:24:41 -05003638 for (i = 0; i < n_sids; i++)
3639 {
Florin Coras7baeb712019-01-04 17:05:43 -08003640 session = vcl_session_get (wrk, vp[i].sh);
Florin Coras070453d2018-08-24 17:04:27 -07003641 if (!session)
Florin Coras6917b942018-11-13 22:44:54 -08003642 {
3643 vp[i].revents = POLLHUP;
3644 num_ev++;
3645 continue;
3646 }
Dave Wallace048b1d62018-01-03 22:24:41 -05003647
Florin Coras6917b942018-11-13 22:44:54 -08003648 vp[i].revents = 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003649
3650 if (POLLIN & vp[i].events)
3651 {
Florin Coras54693d22018-07-17 10:46:29 -07003652 rv = vppcom_session_read_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003653 if (rv > 0)
3654 {
Florin Coras6917b942018-11-13 22:44:54 -08003655 vp[i].revents |= POLLIN;
Dave Wallace048b1d62018-01-03 22:24:41 -05003656 num_ev++;
3657 }
3658 else if (rv < 0)
3659 {
3660 switch (rv)
3661 {
3662 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003663 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003664 break;
3665
3666 default:
Florin Coras6917b942018-11-13 22:44:54 -08003667 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003668 break;
3669 }
3670 num_ev++;
3671 }
3672 }
3673
3674 if (POLLOUT & vp[i].events)
3675 {
Florin Coras134a9962018-08-28 11:32:04 -07003676 rv = vppcom_session_write_ready (session);
Dave Wallace048b1d62018-01-03 22:24:41 -05003677 if (rv > 0)
3678 {
Florin Coras6917b942018-11-13 22:44:54 -08003679 vp[i].revents |= POLLOUT;
Dave Wallace048b1d62018-01-03 22:24:41 -05003680 num_ev++;
3681 }
3682 else if (rv < 0)
3683 {
3684 switch (rv)
3685 {
3686 case VPPCOM_ECONNRESET:
Florin Coras6917b942018-11-13 22:44:54 -08003687 vp[i].revents = POLLHUP;
Dave Wallace048b1d62018-01-03 22:24:41 -05003688 break;
3689
3690 default:
Florin Coras6917b942018-11-13 22:44:54 -08003691 vp[i].revents = POLLERR;
Dave Wallace048b1d62018-01-03 22:24:41 -05003692 break;
3693 }
3694 num_ev++;
3695 }
3696 }
3697
Dave Wallace7e607a72018-06-18 18:41:32 -04003698 if (0) // Note "done:" label used by VCL_SESSION_LOCK_AND_GET()
Dave Wallace048b1d62018-01-03 22:24:41 -05003699 {
Florin Coras6917b942018-11-13 22:44:54 -08003700 vp[i].revents = POLLNVAL;
Dave Wallace048b1d62018-01-03 22:24:41 -05003701 num_ev++;
3702 }
3703 }
3704 if (wait_for_time != -1)
Florin Coras134a9962018-08-28 11:32:04 -07003705 keep_trying = (clib_time_now (&wrk->clib_time) <= timeout) ? 1 : 0;
Dave Wallace048b1d62018-01-03 22:24:41 -05003706 }
3707 while ((num_ev == 0) && keep_trying);
3708
3709 if (VPPCOM_DEBUG > 3)
3710 {
3711 clib_warning ("VCL<%d>: returning %d", getpid (), num_ev);
3712 for (i = 0; i < n_sids; i++)
3713 {
3714 clib_warning ("VCL<%d>: vp[%d].sid %d (0x%x), .events 0x%x, "
Florin Coras7baeb712019-01-04 17:05:43 -08003715 ".revents 0x%x", getpid (), i, vp[i].sh, vp[i].sh,
Florin Coras6917b942018-11-13 22:44:54 -08003716 vp[i].events, vp[i].revents);
Dave Wallace048b1d62018-01-03 22:24:41 -05003717 }
3718 }
3719 return num_ev;
3720}
3721
Florin Coras99368312018-08-02 10:45:44 -07003722int
3723vppcom_mq_epoll_fd (void)
3724{
Florin Coras134a9962018-08-28 11:32:04 -07003725 vcl_worker_t *wrk = vcl_worker_get_current ();
3726 return wrk->mqs_epfd;
3727}
3728
3729int
Florin Coras30e79c22019-01-02 19:31:22 -08003730vppcom_session_index (vcl_session_handle_t session_handle)
Florin Coras134a9962018-08-28 11:32:04 -07003731{
3732 return session_handle & 0xFFFFFF;
3733}
3734
3735int
Florin Coras30e79c22019-01-02 19:31:22 -08003736vppcom_session_worker (vcl_session_handle_t session_handle)
3737{
3738 return session_handle >> 24;
3739}
3740
3741int
Florin Coras30e273b2018-11-27 00:04:59 -08003742vppcom_session_handle (uint32_t session_index)
3743{
Florin Coras47c40e22018-11-26 17:01:36 -08003744 return (vcl_get_worker_index () << 24) | session_index;
Florin Coras30e273b2018-11-27 00:04:59 -08003745}
3746
3747int
Florin Coras134a9962018-08-28 11:32:04 -07003748vppcom_worker_register (void)
3749{
Florin Coras47c40e22018-11-26 17:01:36 -08003750 if (!vcl_worker_alloc_and_init ())
3751 return VPPCOM_EEXIST;
3752
3753 if (vcl_worker_set_bapi ())
3754 return VPPCOM_EEXIST;
3755
3756 if (vcl_worker_register_with_vpp ())
3757 return VPPCOM_EEXIST;
3758
3759 return VPPCOM_OK;
Florin Coras99368312018-08-02 10:45:44 -07003760}
3761
Florin Corasdfe4cf42018-11-28 22:13:45 -08003762int
3763vppcom_worker_index (void)
3764{
3765 return vcl_get_worker_index ();
3766}
3767
Dave Wallacee22aa742017-10-20 12:30:38 -04003768/*
3769 * fd.io coding-style-patch-verification: ON
3770 *
3771 * Local Variables:
3772 * eval: (c-set-style "gnu")
3773 * End:
3774 */