blob: fa33ad37f1e995510c42b5a01b74e214bcece978 [file] [log] [blame]
Dave Barach68b0fb02017-02-28 15:15:56 -05001/*
Florin Coras288eaab2019-02-03 15:26:14 -08002 * Copyright (c) 2017-2019 Cisco and/or its affiliates.
Dave Barach68b0fb02017-02-28 15:15:56 -05003 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
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
Florin Coras6792ec02017-03-13 03:49:51 -070016#include <math.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050017#include <vlib/vlib.h>
18#include <vnet/vnet.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050019#include <vppinfra/elog.h>
Florin Coras561af9b2017-12-09 10:19:43 -080020#include <vnet/session/transport.h>
Florin Coras8e43d042018-05-04 15:46:57 -070021#include <vnet/session/session.h>
Florin Coras6792ec02017-03-13 03:49:51 -070022#include <vnet/session/application.h>
Florin Coras52207f12018-07-12 14:48:06 -070023#include <vnet/session/application_interface.h>
Florin Corase69f4952017-03-07 10:06:24 -080024#include <vnet/session/session_debug.h>
Florin Corase86a8ed2018-01-05 03:20:25 -080025#include <svm/queue.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050026
Florin Coras52207f12018-07-12 14:48:06 -070027static void
28session_mq_accepted_reply_handler (void *data)
29{
30 session_accepted_reply_msg_t *mp = (session_accepted_reply_msg_t *) data;
31 vnet_disconnect_args_t _a = { 0 }, *a = &_a;
Florin Coras288eaab2019-02-03 15:26:14 -080032 session_state_t old_state;
Florin Coras21795132018-09-09 09:40:51 -070033 app_worker_t *app_wrk;
Florin Coras52207f12018-07-12 14:48:06 -070034 local_session_t *ls;
Florin Coras288eaab2019-02-03 15:26:14 -080035 session_t *s;
Florin Coras52207f12018-07-12 14:48:06 -070036
37 /* Server isn't interested, kill the session */
38 if (mp->retval)
39 {
40 a->app_index = mp->context;
41 a->handle = mp->handle;
42 vnet_disconnect_session (a);
43 return;
44 }
45
46 if (session_handle_is_local (mp->handle))
47 {
Florin Coras623eb562019-02-03 19:28:34 -080048 ls = app_worker_get_local_session_from_handle (mp->handle);
Florin Corasab2f6db2018-08-31 14:31:41 -070049 if (!ls)
Florin Coras52207f12018-07-12 14:48:06 -070050 {
Florin Corasab2f6db2018-08-31 14:31:41 -070051 clib_warning ("unknown local handle 0x%lx", mp->handle);
52 return;
53 }
54 app_wrk = app_worker_get (ls->app_wrk_index);
Florin Coras21795132018-09-09 09:40:51 -070055 if (app_wrk->app_index != mp->context)
Florin Corasab2f6db2018-08-31 14:31:41 -070056 {
57 clib_warning ("server %u doesn't own local handle 0x%lx",
Florin Coras52207f12018-07-12 14:48:06 -070058 mp->context, mp->handle);
59 return;
60 }
Florin Coras623eb562019-02-03 19:28:34 -080061 if (app_worker_local_session_connect_notify (ls))
Florin Coras52207f12018-07-12 14:48:06 -070062 return;
63 ls->session_state = SESSION_STATE_READY;
64 }
65 else
66 {
67 s = session_get_from_handle_if_valid (mp->handle);
Florin Corasb0f662f2018-12-27 14:51:46 -080068 if (!s)
Florin Corase2ea1932018-12-17 23:08:14 -080069 return;
Florin Corasb0f662f2018-12-27 14:51:46 -080070
Florin Coras21795132018-09-09 09:40:51 -070071 app_wrk = app_worker_get (s->app_wrk_index);
72 if (app_wrk->app_index != mp->context)
Florin Coras52207f12018-07-12 14:48:06 -070073 {
74 clib_warning ("app doesn't own session");
75 return;
76 }
Florin Corasb0f662f2018-12-27 14:51:46 -080077
78 old_state = s->session_state;
Florin Coras52207f12018-07-12 14:48:06 -070079 s->session_state = SESSION_STATE_READY;
Florin Coras288eaab2019-02-03 15:26:14 -080080 if (!svm_fifo_is_empty (s->rx_fifo))
Florin Coras21795132018-09-09 09:40:51 -070081 app_worker_lock_and_send_event (app_wrk, s, FIFO_EVENT_APP_RX);
Florin Corasb0f662f2018-12-27 14:51:46 -080082
83 /* Closed while waiting for app to reply. Resend disconnect */
84 if (old_state >= SESSION_STATE_TRANSPORT_CLOSING)
85 {
86 application_t *app = application_get (app_wrk->app_index);
87 app->cb_fns.session_disconnect_callback (s);
88 s->session_state = old_state;
89 return;
90 }
Florin Coras52207f12018-07-12 14:48:06 -070091 }
92}
93
94static void
95session_mq_reset_reply_handler (void *data)
96{
Florin Coras4af830c2018-12-04 09:21:36 -080097 vnet_disconnect_args_t _a = { 0 }, *a = &_a;
Florin Coras52207f12018-07-12 14:48:06 -070098 session_reset_reply_msg_t *mp;
Florin Coras15531972018-08-12 23:50:53 -070099 app_worker_t *app_wrk;
Florin Coras288eaab2019-02-03 15:26:14 -0800100 session_t *s;
Florin Coras15531972018-08-12 23:50:53 -0700101 application_t *app;
Florin Coras52207f12018-07-12 14:48:06 -0700102 u32 index, thread_index;
103
104 mp = (session_reset_reply_msg_t *) data;
Florin Coras3c7d4f92018-12-14 11:28:43 -0800105 app = application_lookup (mp->context);
Florin Coras52207f12018-07-12 14:48:06 -0700106 if (!app)
107 return;
108
109 session_parse_handle (mp->handle, &index, &thread_index);
110 s = session_get_if_valid (index, thread_index);
Florin Coras3c7d4f92018-12-14 11:28:43 -0800111
112 /* Session was already closed or already cleaned up */
113 if (!s || s->session_state != SESSION_STATE_TRANSPORT_CLOSING)
114 return;
115
Florin Coras15531972018-08-12 23:50:53 -0700116 app_wrk = app_worker_get (s->app_wrk_index);
117 if (!app_wrk || app_wrk->app_index != app->app_index)
118 {
119 clib_warning ("App % does not own handle 0x%lx!", app->app_index,
120 mp->handle);
121 return;
122 }
Florin Coras52207f12018-07-12 14:48:06 -0700123
124 /* Client objected to resetting the session, log and continue */
125 if (mp->retval)
126 {
127 clib_warning ("client retval %d", mp->retval);
128 return;
129 }
130
131 /* This comes as a response to a reset, transport only waiting for
132 * confirmation to remove connection state, no need to disconnect */
Florin Coras4af830c2018-12-04 09:21:36 -0800133 a->handle = mp->handle;
134 a->app_index = app->app_index;
135 vnet_disconnect_session (a);
Florin Coras52207f12018-07-12 14:48:06 -0700136}
137
138static void
139session_mq_disconnected_handler (void *data)
140{
141 session_disconnected_reply_msg_t *rmp;
142 vnet_disconnect_args_t _a, *a = &_a;
143 svm_msg_q_msg_t _msg, *msg = &_msg;
144 session_disconnected_msg_t *mp;
Florin Coras15531972018-08-12 23:50:53 -0700145 app_worker_t *app_wrk;
Florin Coras52207f12018-07-12 14:48:06 -0700146 session_event_t *evt;
Florin Coras288eaab2019-02-03 15:26:14 -0800147 session_t *s;
Florin Coras52207f12018-07-12 14:48:06 -0700148 application_t *app;
149 int rv = 0;
150
151 mp = (session_disconnected_msg_t *) data;
Florin Corasc3638fe2018-08-24 13:58:49 -0700152 if (!(s = session_get_from_handle_if_valid (mp->handle)))
153 {
154 clib_warning ("could not disconnect handle %llu", mp->handle);
155 return;
156 }
Florin Coras15531972018-08-12 23:50:53 -0700157 app_wrk = app_worker_get (s->app_wrk_index);
158 app = application_lookup (mp->client_index);
Florin Corasc3638fe2018-08-24 13:58:49 -0700159 if (!(app_wrk && app && app->app_index == app_wrk->app_index))
Florin Coras52207f12018-07-12 14:48:06 -0700160 {
Florin Corasc3638fe2018-08-24 13:58:49 -0700161 clib_warning ("could not disconnect session: %llu app: %u",
Florin Coras15531972018-08-12 23:50:53 -0700162 mp->handle, mp->client_index);
Florin Coras3d0fadc2018-07-17 05:35:47 -0700163 return;
Florin Coras52207f12018-07-12 14:48:06 -0700164 }
Florin Coras3d0fadc2018-07-17 05:35:47 -0700165
166 a->handle = mp->handle;
Florin Coras15531972018-08-12 23:50:53 -0700167 a->app_index = app_wrk->wrk_index;
Florin Coras3d0fadc2018-07-17 05:35:47 -0700168 rv = vnet_disconnect_session (a);
Florin Coras52207f12018-07-12 14:48:06 -0700169
Florin Coras15531972018-08-12 23:50:53 -0700170 svm_msg_q_lock_and_alloc_msg_w_ring (app_wrk->event_queue,
Florin Coras52207f12018-07-12 14:48:06 -0700171 SESSION_MQ_CTRL_EVT_RING,
172 SVM_Q_WAIT, msg);
Florin Coras15531972018-08-12 23:50:53 -0700173 svm_msg_q_unlock (app_wrk->event_queue);
174 evt = svm_msg_q_msg_data (app_wrk->event_queue, msg);
Dave Barachb7b92992018-10-17 10:38:51 -0400175 clib_memset (evt, 0, sizeof (*evt));
Florin Coras30e79c22019-01-02 19:31:22 -0800176 evt->event_type = SESSION_CTRL_EVT_DISCONNECTED_REPLY;
Florin Coras52207f12018-07-12 14:48:06 -0700177 rmp = (session_disconnected_reply_msg_t *) evt->data;
178 rmp->handle = mp->handle;
179 rmp->context = mp->context;
180 rmp->retval = rv;
Florin Coras15531972018-08-12 23:50:53 -0700181 svm_msg_q_add (app_wrk->event_queue, msg, SVM_Q_WAIT);
Florin Coras52207f12018-07-12 14:48:06 -0700182}
183
184static void
185session_mq_disconnected_reply_handler (void *data)
186{
187 session_disconnected_reply_msg_t *mp;
188 vnet_disconnect_args_t _a, *a = &_a;
189 application_t *app;
190
191 mp = (session_disconnected_reply_msg_t *) data;
192
193 /* Client objected to disconnecting the session, log and continue */
194 if (mp->retval)
195 {
196 clib_warning ("client retval %d", mp->retval);
197 return;
198 }
199
200 /* Disconnect has been confirmed. Confirm close to transport */
201 app = application_lookup (mp->context);
202 if (app)
203 {
204 a->handle = mp->handle;
Florin Coras15531972018-08-12 23:50:53 -0700205 a->app_index = app->app_index;
Florin Coras52207f12018-07-12 14:48:06 -0700206 vnet_disconnect_session (a);
207 }
208}
209
Florin Coras30e79c22019-01-02 19:31:22 -0800210static void
211session_mq_worker_update_handler (void *data)
212{
213 session_worker_update_msg_t *mp = (session_worker_update_msg_t *) data;
214 session_worker_update_reply_msg_t *rmp;
215 svm_msg_q_msg_t _msg, *msg = &_msg;
216 app_worker_t *app_wrk;
217 u32 owner_app_wrk_map;
218 session_event_t *evt;
Florin Coras288eaab2019-02-03 15:26:14 -0800219 session_t *s;
Florin Coras30e79c22019-01-02 19:31:22 -0800220 application_t *app;
221
222 app = application_lookup (mp->client_index);
223 if (!app)
224 return;
225 if (!(s = session_get_from_handle_if_valid (mp->handle)))
226 {
227 clib_warning ("invalid handle %llu", mp->handle);
228 return;
229 }
230 app_wrk = app_worker_get (s->app_wrk_index);
231 if (app_wrk->app_index != app->app_index)
232 {
233 clib_warning ("app %u does not own session %llu", app->app_index,
234 mp->handle);
235 return;
236 }
237 owner_app_wrk_map = app_wrk->wrk_map_index;
238 app_wrk = application_get_worker (app, mp->wrk_index);
239
240 /* This needs to come from the new owner */
241 if (mp->req_wrk_index == owner_app_wrk_map)
242 {
243 session_req_worker_update_msg_t *wump;
244
245 svm_msg_q_lock_and_alloc_msg_w_ring (app_wrk->event_queue,
246 SESSION_MQ_CTRL_EVT_RING,
247 SVM_Q_WAIT, msg);
248 svm_msg_q_unlock (app_wrk->event_queue);
249 evt = svm_msg_q_msg_data (app_wrk->event_queue, msg);
250 clib_memset (evt, 0, sizeof (*evt));
251 evt->event_type = SESSION_CTRL_EVT_REQ_WORKER_UPDATE;
252 wump = (session_req_worker_update_msg_t *) evt->data;
253 wump->session_handle = mp->handle;
254 svm_msg_q_add (app_wrk->event_queue, msg, SVM_Q_WAIT);
255 return;
256 }
257
258 app_worker_own_session (app_wrk, s);
259
260 /*
261 * Send reply
262 */
263 svm_msg_q_lock_and_alloc_msg_w_ring (app_wrk->event_queue,
264 SESSION_MQ_CTRL_EVT_RING,
265 SVM_Q_WAIT, msg);
266 svm_msg_q_unlock (app_wrk->event_queue);
267 evt = svm_msg_q_msg_data (app_wrk->event_queue, msg);
268 clib_memset (evt, 0, sizeof (*evt));
269 evt->event_type = SESSION_CTRL_EVT_WORKER_UPDATE_REPLY;
270 rmp = (session_worker_update_reply_msg_t *) evt->data;
271 rmp->handle = mp->handle;
Florin Coras288eaab2019-02-03 15:26:14 -0800272 rmp->rx_fifo = pointer_to_uword (s->rx_fifo);
273 rmp->tx_fifo = pointer_to_uword (s->tx_fifo);
Florin Coras30e79c22019-01-02 19:31:22 -0800274 rmp->segment_handle = session_segment_handle (s);
275 svm_msg_q_add (app_wrk->event_queue, msg, SVM_Q_WAIT);
276
277 /*
278 * Retransmit messages that may have been lost
279 */
Florin Coras288eaab2019-02-03 15:26:14 -0800280 if (s->tx_fifo && !svm_fifo_is_empty (s->tx_fifo))
281 session_send_io_evt_to_thread (s->tx_fifo, FIFO_EVENT_APP_TX);
Florin Coras30e79c22019-01-02 19:31:22 -0800282
Florin Coras288eaab2019-02-03 15:26:14 -0800283 if (s->rx_fifo && !svm_fifo_is_empty (s->rx_fifo))
Florin Coras30e79c22019-01-02 19:31:22 -0800284 app_worker_lock_and_send_event (app_wrk, s, FIFO_EVENT_APP_RX);
285
286 if (s->session_state >= SESSION_STATE_TRANSPORT_CLOSING)
287 app->cb_fns.session_disconnect_callback (s);
288}
289
Dave Barach68b0fb02017-02-28 15:15:56 -0500290vlib_node_registration_t session_queue_node;
291
292typedef struct
293{
294 u32 session_index;
295 u32 server_thread_index;
296} session_queue_trace_t;
297
298/* packet trace format function */
299static u8 *
300format_session_queue_trace (u8 * s, va_list * args)
301{
302 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
303 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
304 session_queue_trace_t *t = va_arg (*args, session_queue_trace_t *);
305
306 s = format (s, "SESSION_QUEUE: session index %d, server thread index %d",
307 t->session_index, t->server_thread_index);
308 return s;
309}
310
Florin Coras6792ec02017-03-13 03:49:51 -0700311#define foreach_session_queue_error \
312_(TX, "Packets transmitted") \
Florin Coras93992a92017-05-24 18:03:56 -0700313_(TIMER, "Timer events") \
314_(NO_BUFFER, "Out of buffers")
Dave Barach68b0fb02017-02-28 15:15:56 -0500315
316typedef enum
317{
318#define _(sym,str) SESSION_QUEUE_ERROR_##sym,
319 foreach_session_queue_error
320#undef _
321 SESSION_QUEUE_N_ERROR,
322} session_queue_error_t;
323
324static char *session_queue_error_strings[] = {
325#define _(sym,string) string,
326 foreach_session_queue_error
327#undef _
328};
329
Florin Coras0d60a0f2018-06-29 02:02:08 -0700330enum
331{
332 SESSION_TX_NO_BUFFERS = -2,
333 SESSION_TX_NO_DATA,
334 SESSION_TX_OK
335};
336
Florin Coras66cf5e02018-06-08 09:17:39 -0700337static void
338session_tx_trace_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
339 u32 next_index, u32 * to_next, u16 n_segs,
Florin Coras288eaab2019-02-03 15:26:14 -0800340 session_t * s, u32 n_trace)
Florin Corasf6d68ed2017-05-07 19:12:02 -0700341{
Florin Coras8e43d042018-05-04 15:46:57 -0700342 session_queue_trace_t *t;
Florin Coras66cf5e02018-06-08 09:17:39 -0700343 vlib_buffer_t *b;
344 int i;
345
346 for (i = 0; i < clib_min (n_trace, n_segs); i++)
347 {
348 b = vlib_get_buffer (vm, to_next[i - n_segs]);
349 vlib_trace_buffer (vm, node, next_index, b, 1 /* follow_chain */ );
Florin Coras66cf5e02018-06-08 09:17:39 -0700350 t = vlib_add_trace (vm, node, b, sizeof (*t));
351 t->session_index = s->session_index;
352 t->server_thread_index = s->thread_index;
353 }
Florin Coras4df38712018-06-20 12:44:16 -0700354 vlib_set_trace_count (vm, node, n_trace - i);
Florin Coras8e43d042018-05-04 15:46:57 -0700355}
Florin Corasf6d68ed2017-05-07 19:12:02 -0700356
Florin Coras8e43d042018-05-04 15:46:57 -0700357always_inline void
358session_tx_fifo_chain_tail (vlib_main_t * vm, session_tx_context_t * ctx,
359 vlib_buffer_t * b, u16 * n_bufs, u8 peek_data)
360{
Florin Coras8e43d042018-05-04 15:46:57 -0700361 vlib_buffer_t *chain_b, *prev_b;
362 u32 chain_bi0, to_deq, left_from_seg;
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700363 session_manager_worker_t *wrk;
Florin Coras8e43d042018-05-04 15:46:57 -0700364 u16 len_to_deq, n_bytes_read;
365 u8 *data, j;
Florin Corasb2215d62017-08-01 16:56:58 -0700366
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700367 wrk = session_manager_get_worker (ctx->s->thread_index);
Florin Coras8e43d042018-05-04 15:46:57 -0700368 b->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
369 b->total_length_not_including_first_buffer = 0;
370
371 chain_b = b;
372 left_from_seg = clib_min (ctx->snd_mss - b->current_length,
373 ctx->left_to_snd);
Florin Corasb2215d62017-08-01 16:56:58 -0700374 to_deq = left_from_seg;
Florin Coras8e43d042018-05-04 15:46:57 -0700375 for (j = 1; j < ctx->n_bufs_per_seg; j++)
Florin Corasf6d68ed2017-05-07 19:12:02 -0700376 {
Florin Coras8e43d042018-05-04 15:46:57 -0700377 prev_b = chain_b;
378 len_to_deq = clib_min (to_deq, ctx->deq_per_buf);
Florin Corasf6d68ed2017-05-07 19:12:02 -0700379
380 *n_bufs -= 1;
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700381 chain_bi0 = wrk->tx_buffers[*n_bufs];
Florin Coras8e43d042018-05-04 15:46:57 -0700382 chain_b = vlib_get_buffer (vm, chain_bi0);
383 chain_b->current_data = 0;
384 data = vlib_buffer_get_current (chain_b);
Florin Corasf6d68ed2017-05-07 19:12:02 -0700385 if (peek_data)
386 {
Florin Coras288eaab2019-02-03 15:26:14 -0800387 n_bytes_read = svm_fifo_peek (ctx->s->tx_fifo,
Florin Coras8e43d042018-05-04 15:46:57 -0700388 ctx->tx_offset, len_to_deq, data);
389 ctx->tx_offset += n_bytes_read;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700390 }
391 else
392 {
Florin Coras8e43d042018-05-04 15:46:57 -0700393 if (ctx->transport_vft->tx_type == TRANSPORT_TX_DGRAM)
Florin Coras7fb0fe12018-04-09 09:24:52 -0700394 {
Florin Coras288eaab2019-02-03 15:26:14 -0800395 svm_fifo_t *f = ctx->s->tx_fifo;
Florin Coras8e43d042018-05-04 15:46:57 -0700396 session_dgram_hdr_t *hdr = &ctx->hdr;
Florin Coras7fb0fe12018-04-09 09:24:52 -0700397 u16 deq_now;
Florin Coras7fb0fe12018-04-09 09:24:52 -0700398 deq_now = clib_min (hdr->data_length - hdr->data_offset,
Florin Coras8e43d042018-05-04 15:46:57 -0700399 len_to_deq);
400 n_bytes_read = svm_fifo_peek (f, hdr->data_offset, deq_now,
401 data);
Florin Coras7fb0fe12018-04-09 09:24:52 -0700402 ASSERT (n_bytes_read > 0);
403
404 hdr->data_offset += n_bytes_read;
405 if (hdr->data_offset == hdr->data_length)
shubing guoaea5f392018-08-30 13:29:49 +0800406 {
407 u32 offset = hdr->data_length + SESSION_CONN_HDR_LEN;
408 svm_fifo_dequeue_drop (f, offset);
409 }
Florin Coras7fb0fe12018-04-09 09:24:52 -0700410 }
411 else
Florin Coras288eaab2019-02-03 15:26:14 -0800412 n_bytes_read = svm_fifo_dequeue_nowait (ctx->s->tx_fifo,
Florin Coras8e43d042018-05-04 15:46:57 -0700413 len_to_deq, data);
Florin Corasf6d68ed2017-05-07 19:12:02 -0700414 }
Florin Coras8e43d042018-05-04 15:46:57 -0700415 ASSERT (n_bytes_read == len_to_deq);
416 chain_b->current_length = n_bytes_read;
417 b->total_length_not_including_first_buffer += chain_b->current_length;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700418
419 /* update previous buffer */
Florin Coras8e43d042018-05-04 15:46:57 -0700420 prev_b->next_buffer = chain_bi0;
421 prev_b->flags |= VLIB_BUFFER_NEXT_PRESENT;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700422
423 /* update current buffer */
Florin Coras8e43d042018-05-04 15:46:57 -0700424 chain_b->next_buffer = 0;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700425
Florin Corasb2215d62017-08-01 16:56:58 -0700426 to_deq -= n_bytes_read;
427 if (to_deq == 0)
Florin Corasf6d68ed2017-05-07 19:12:02 -0700428 break;
429 }
Florin Coras1f152cd2017-08-18 19:28:03 -0700430 ASSERT (to_deq == 0
Florin Coras8e43d042018-05-04 15:46:57 -0700431 && b->total_length_not_including_first_buffer == left_from_seg);
432 ctx->left_to_snd -= left_from_seg;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700433}
434
Florin Coras8e43d042018-05-04 15:46:57 -0700435always_inline void
436session_tx_fill_buffer (vlib_main_t * vm, session_tx_context_t * ctx,
437 vlib_buffer_t * b, u16 * n_bufs, u8 peek_data)
438{
439 u32 len_to_deq;
440 u8 *data0;
441 int n_bytes_read;
442
443 /*
444 * Start with the first buffer in chain
445 */
446 b->error = 0;
447 b->flags = VNET_BUFFER_F_LOCALLY_ORIGINATED;
448 b->current_data = 0;
Florin Coras8e43d042018-05-04 15:46:57 -0700449
450 data0 = vlib_buffer_make_headroom (b, MAX_HDRS_LEN);
451 len_to_deq = clib_min (ctx->left_to_snd, ctx->deq_per_first_buf);
452
Florin Coras7fb0fe12018-04-09 09:24:52 -0700453 if (peek_data)
454 {
Florin Coras288eaab2019-02-03 15:26:14 -0800455 n_bytes_read = svm_fifo_peek (ctx->s->tx_fifo, ctx->tx_offset,
Florin Coras8e43d042018-05-04 15:46:57 -0700456 len_to_deq, data0);
457 ASSERT (n_bytes_read > 0);
458 /* Keep track of progress locally, transport is also supposed to
459 * increment it independently when pushing the header */
460 ctx->tx_offset += n_bytes_read;
Florin Coras7fb0fe12018-04-09 09:24:52 -0700461 }
462 else
463 {
Florin Coras8e43d042018-05-04 15:46:57 -0700464 if (ctx->transport_vft->tx_type == TRANSPORT_TX_DGRAM)
465 {
466 session_dgram_hdr_t *hdr = &ctx->hdr;
Florin Coras288eaab2019-02-03 15:26:14 -0800467 svm_fifo_t *f = ctx->s->tx_fifo;
Florin Coras8e43d042018-05-04 15:46:57 -0700468 u16 deq_now;
469 u32 offset;
470
471 ASSERT (hdr->data_length > hdr->data_offset);
472 deq_now = clib_min (hdr->data_length - hdr->data_offset,
473 len_to_deq);
474 offset = hdr->data_offset + SESSION_CONN_HDR_LEN;
475 n_bytes_read = svm_fifo_peek (f, offset, deq_now, data0);
476 ASSERT (n_bytes_read > 0);
477
478 if (ctx->s->session_state == SESSION_STATE_LISTENING)
479 {
480 ip_copy (&ctx->tc->rmt_ip, &hdr->rmt_ip, ctx->tc->is_ip4);
481 ctx->tc->rmt_port = hdr->rmt_port;
482 }
483 hdr->data_offset += n_bytes_read;
484 if (hdr->data_offset == hdr->data_length)
485 {
486 offset = hdr->data_length + SESSION_CONN_HDR_LEN;
487 svm_fifo_dequeue_drop (f, offset);
488 }
489 }
Florin Coras7fb0fe12018-04-09 09:24:52 -0700490 else
491 {
Florin Coras288eaab2019-02-03 15:26:14 -0800492 n_bytes_read = svm_fifo_dequeue_nowait (ctx->s->tx_fifo,
Florin Coras8e43d042018-05-04 15:46:57 -0700493 len_to_deq, data0);
494 ASSERT (n_bytes_read > 0);
Florin Coras7fb0fe12018-04-09 09:24:52 -0700495 }
496 }
Florin Coras8e43d042018-05-04 15:46:57 -0700497 b->current_length = n_bytes_read;
498 ctx->left_to_snd -= n_bytes_read;
Dave Barach68b0fb02017-02-28 15:15:56 -0500499
Florin Coras8e43d042018-05-04 15:46:57 -0700500 /*
501 * Fill in the remaining buffers in the chain, if any
502 */
503 if (PREDICT_FALSE (ctx->n_bufs_per_seg > 1 && ctx->left_to_snd))
504 session_tx_fifo_chain_tail (vm, ctx, b, n_bufs, peek_data);
Dave Barach68b0fb02017-02-28 15:15:56 -0500505
Florin Coras8e43d042018-05-04 15:46:57 -0700506 /* *INDENT-OFF* */
Florin Coras8b20bf52018-06-14 14:55:50 -0700507 SESSION_EVT_DBG(SESSION_EVT_DEQ, ctx->s, ({
508 ed->data[0] = FIFO_EVENT_APP_TX;
509 ed->data[1] = ctx->max_dequeue;
Florin Coras8e43d042018-05-04 15:46:57 -0700510 ed->data[2] = len_to_deq;
Florin Coras8b20bf52018-06-14 14:55:50 -0700511 ed->data[3] = ctx->left_to_snd;
Florin Coras8e43d042018-05-04 15:46:57 -0700512 }));
513 /* *INDENT-ON* */
514}
515
516always_inline u8
Florin Coras288eaab2019-02-03 15:26:14 -0800517session_tx_not_ready (session_t * s, u8 peek_data)
Florin Coras8e43d042018-05-04 15:46:57 -0700518{
519 if (peek_data)
Florin Corase04c2992017-03-01 08:17:34 -0800520 {
Florin Coras8e43d042018-05-04 15:46:57 -0700521 /* Can retransmit for closed sessions but can't send new data if
522 * session is not ready or closed */
523 if (s->session_state < SESSION_STATE_READY)
524 return 1;
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800525 if (s->session_state >= SESSION_STATE_TRANSPORT_CLOSED)
Florin Corasca1c8f32018-05-23 21:01:30 -0700526 return 2;
Florin Corase04c2992017-03-01 08:17:34 -0800527 }
Florin Coras8e43d042018-05-04 15:46:57 -0700528 return 0;
529}
Dave Barach68b0fb02017-02-28 15:15:56 -0500530
Florin Coras8e43d042018-05-04 15:46:57 -0700531always_inline transport_connection_t *
532session_tx_get_transport (session_tx_context_t * ctx, u8 peek_data)
533{
534 if (peek_data)
535 {
536 return ctx->transport_vft->get_connection (ctx->s->connection_index,
537 ctx->s->thread_index);
538 }
539 else
540 {
541 if (ctx->s->session_state == SESSION_STATE_LISTENING)
542 return ctx->transport_vft->get_listener (ctx->s->connection_index);
543 else
544 {
545 return ctx->transport_vft->get_connection (ctx->s->connection_index,
546 ctx->s->thread_index);
547 }
548 }
549}
Florin Coras6a9b68b2017-11-21 04:20:42 -0800550
Florin Coras8e43d042018-05-04 15:46:57 -0700551always_inline void
552session_tx_set_dequeue_params (vlib_main_t * vm, session_tx_context_t * ctx,
Florin Corasf08f26d2018-05-10 13:20:47 -0700553 u32 max_segs, u8 peek_data)
Florin Coras8e43d042018-05-04 15:46:57 -0700554{
555 u32 n_bytes_per_buf, n_bytes_per_seg;
Florin Coras288eaab2019-02-03 15:26:14 -0800556 ctx->max_dequeue = svm_fifo_max_dequeue (ctx->s->tx_fifo);
Dave Barach68b0fb02017-02-28 15:15:56 -0500557 if (peek_data)
558 {
Florin Coras9d063042017-09-14 03:08:00 -0400559 /* Offset in rx fifo from where to peek data */
Florin Coras8e43d042018-05-04 15:46:57 -0700560 ctx->tx_offset = ctx->transport_vft->tx_fifo_offset (ctx->tc);
561 if (PREDICT_FALSE (ctx->tx_offset >= ctx->max_dequeue))
562 {
563 ctx->max_len_to_snd = 0;
564 return;
565 }
566 ctx->max_dequeue -= ctx->tx_offset;
Dave Barach68b0fb02017-02-28 15:15:56 -0500567 }
Florin Coras7fb0fe12018-04-09 09:24:52 -0700568 else
569 {
Florin Coras8e43d042018-05-04 15:46:57 -0700570 if (ctx->transport_vft->tx_type == TRANSPORT_TX_DGRAM)
Florin Coras7fb0fe12018-04-09 09:24:52 -0700571 {
Florin Coras8e43d042018-05-04 15:46:57 -0700572 if (ctx->max_dequeue <= sizeof (ctx->hdr))
573 {
574 ctx->max_len_to_snd = 0;
575 return;
576 }
Florin Coras288eaab2019-02-03 15:26:14 -0800577 svm_fifo_peek (ctx->s->tx_fifo, 0, sizeof (ctx->hdr),
Florin Coras8e43d042018-05-04 15:46:57 -0700578 (u8 *) & ctx->hdr);
579 ASSERT (ctx->hdr.data_length > ctx->hdr.data_offset);
580 ctx->max_dequeue = ctx->hdr.data_length - ctx->hdr.data_offset;
Florin Coras7fb0fe12018-04-09 09:24:52 -0700581 }
582 }
Florin Coras8e43d042018-05-04 15:46:57 -0700583 ASSERT (ctx->max_dequeue > 0);
Florin Coras6792ec02017-03-13 03:49:51 -0700584
585 /* Ensure we're not writing more than transport window allows */
Florin Coras8e43d042018-05-04 15:46:57 -0700586 if (ctx->max_dequeue < ctx->snd_space)
Florin Coras3e350af2017-03-30 02:54:28 -0700587 {
588 /* Constrained by tx queue. Try to send only fully formed segments */
Florin Coras8e43d042018-05-04 15:46:57 -0700589 ctx->max_len_to_snd =
590 (ctx->max_dequeue > ctx->snd_mss) ?
591 ctx->max_dequeue - ctx->max_dequeue % ctx->snd_mss : ctx->max_dequeue;
Florin Coras3e350af2017-03-30 02:54:28 -0700592 /* TODO Nagle ? */
593 }
594 else
595 {
Florin Coras1f152cd2017-08-18 19:28:03 -0700596 /* Expectation is that snd_space0 is already a multiple of snd_mss */
Florin Coras8e43d042018-05-04 15:46:57 -0700597 ctx->max_len_to_snd = ctx->snd_space;
Florin Coras3e350af2017-03-30 02:54:28 -0700598 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500599
Florin Corasf08f26d2018-05-10 13:20:47 -0700600 /* Check if we're tx constrained by the node */
601 ctx->n_segs_per_evt = ceil ((f64) ctx->max_len_to_snd / ctx->snd_mss);
602 if (ctx->n_segs_per_evt > max_segs)
603 {
604 ctx->n_segs_per_evt = max_segs;
605 ctx->max_len_to_snd = max_segs * ctx->snd_mss;
606 }
607
Damjan Marion671e60e2018-12-30 18:09:59 +0100608 n_bytes_per_buf = VLIB_BUFFER_DATA_SIZE;
Florin Corase87216f2017-08-17 16:59:22 -0700609 ASSERT (n_bytes_per_buf > MAX_HDRS_LEN);
Florin Coras8e43d042018-05-04 15:46:57 -0700610 n_bytes_per_seg = MAX_HDRS_LEN + ctx->snd_mss;
Florin Corasf08f26d2018-05-10 13:20:47 -0700611 ctx->n_bufs_per_seg = ceil ((f64) n_bytes_per_seg / n_bytes_per_buf);
Florin Coras8e43d042018-05-04 15:46:57 -0700612 ctx->deq_per_buf = clib_min (ctx->snd_mss, n_bytes_per_buf);
613 ctx->deq_per_first_buf = clib_min (ctx->snd_mss,
614 n_bytes_per_buf - MAX_HDRS_LEN);
615}
Florin Corasf6d68ed2017-05-07 19:12:02 -0700616
Florin Coras8e43d042018-05-04 15:46:57 -0700617always_inline int
618session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node,
Florin Coras1bcad5c2019-01-09 20:04:38 -0800619 session_manager_worker_t * wrk,
620 session_event_t * e, int *n_tx_packets,
Florin Coras8e43d042018-05-04 15:46:57 -0700621 u8 peek_data)
622{
Florin Coras2068fd42019-01-31 14:35:50 -0800623 u32 next_index, next0, next1, *to_next, n_left_to_next, n_left, pbi;
Florin Corasf08f26d2018-05-10 13:20:47 -0700624 u32 n_trace = vlib_get_trace_count (vm, node), n_bufs_needed = 0;
Florin Coras8e43d042018-05-04 15:46:57 -0700625 session_manager_main_t *smm = &session_manager_main;
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700626 session_tx_context_t *ctx = &wrk->ctx;
Florin Coras8e43d042018-05-04 15:46:57 -0700627 transport_proto_t tp;
628 vlib_buffer_t *pb;
Florin Corasca1c8f32018-05-23 21:01:30 -0700629 u16 n_bufs, rv;
Florin Coras8e43d042018-05-04 15:46:57 -0700630
Florin Coras1bcad5c2019-01-09 20:04:38 -0800631 if (PREDICT_FALSE ((rv = session_tx_not_ready (ctx->s, peek_data))))
Florin Coras8e43d042018-05-04 15:46:57 -0700632 {
Florin Corasca1c8f32018-05-23 21:01:30 -0700633 if (rv < 2)
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700634 vec_add1 (wrk->pending_event_vector, *e);
Florin Coras0d60a0f2018-06-29 02:02:08 -0700635 return SESSION_TX_NO_DATA;
Florin Coras8e43d042018-05-04 15:46:57 -0700636 }
637
Florin Coras1bcad5c2019-01-09 20:04:38 -0800638 next_index = smm->session_type_to_next[ctx->s->session_type];
Florin Coras66cf5e02018-06-08 09:17:39 -0700639 next0 = next1 = next_index;
Florin Coras8e43d042018-05-04 15:46:57 -0700640
Florin Coras1bcad5c2019-01-09 20:04:38 -0800641 tp = session_get_transport_proto (ctx->s);
Florin Coras8e43d042018-05-04 15:46:57 -0700642 ctx->transport_vft = transport_protocol_get_vft (tp);
643 ctx->tc = session_tx_get_transport (ctx, peek_data);
644 ctx->snd_mss = ctx->transport_vft->send_mss (ctx->tc);
Florin Coras42ceddb2018-12-12 10:56:01 -0800645
646 if (PREDICT_FALSE (e->event_type == SESSION_IO_EVT_TX_FLUSH))
647 {
648 if (ctx->transport_vft->flush_data)
649 ctx->transport_vft->flush_data (ctx->tc);
650 }
651
652 ctx->snd_space = transport_connection_snd_space (ctx->tc,
David Johnsond9818dd2018-12-14 14:53:41 -0500653 vm->clib_time.
654 last_cpu_time,
Florin Coras42ceddb2018-12-12 10:56:01 -0800655 ctx->snd_mss);
Florin Coras8e43d042018-05-04 15:46:57 -0700656 if (ctx->snd_space == 0 || ctx->snd_mss == 0)
657 {
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700658 vec_add1 (wrk->pending_event_vector, *e);
Florin Coras0d60a0f2018-06-29 02:02:08 -0700659 return SESSION_TX_NO_DATA;
Florin Coras8e43d042018-05-04 15:46:57 -0700660 }
661
662 /* Allow enqueuing of a new event */
Florin Coras288eaab2019-02-03 15:26:14 -0800663 svm_fifo_unset_event (ctx->s->tx_fifo);
Florin Coras8e43d042018-05-04 15:46:57 -0700664
665 /* Check how much we can pull. */
Florin Corasf08f26d2018-05-10 13:20:47 -0700666 session_tx_set_dequeue_params (vm, ctx, VLIB_FRAME_SIZE - *n_tx_packets,
667 peek_data);
668
Florin Coras8e43d042018-05-04 15:46:57 -0700669 if (PREDICT_FALSE (!ctx->max_len_to_snd))
Florin Coras0d60a0f2018-06-29 02:02:08 -0700670 return SESSION_TX_NO_DATA;
Dave Barach68b0fb02017-02-28 15:15:56 -0500671
Florin Corasf08f26d2018-05-10 13:20:47 -0700672 n_bufs_needed = ctx->n_segs_per_evt * ctx->n_bufs_per_seg;
Florin Coras2068fd42019-01-31 14:35:50 -0800673 vec_validate_aligned (wrk->tx_buffers, n_bufs_needed - 1,
674 CLIB_CACHE_LINE_BYTES);
675 n_bufs = vlib_buffer_alloc (vm, wrk->tx_buffers, n_bufs_needed);
676 if (PREDICT_FALSE (n_bufs < n_bufs_needed))
Dave Barach68b0fb02017-02-28 15:15:56 -0500677 {
Florin Coras2068fd42019-01-31 14:35:50 -0800678 if (n_bufs)
679 vlib_buffer_free (vm, wrk->tx_buffers, n_bufs);
680 vec_add1 (wrk->pending_event_vector, *e);
681 return SESSION_TX_NO_BUFFERS;
Florin Coras8e43d042018-05-04 15:46:57 -0700682 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500683
Florin Coras8e43d042018-05-04 15:46:57 -0700684 /*
685 * Write until we fill up a frame
686 */
687 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
Florin Corasf08f26d2018-05-10 13:20:47 -0700688 if (PREDICT_FALSE (ctx->n_segs_per_evt > n_left_to_next))
Florin Coras8e43d042018-05-04 15:46:57 -0700689 {
Florin Corasf08f26d2018-05-10 13:20:47 -0700690 ctx->n_segs_per_evt = n_left_to_next;
691 ctx->max_len_to_snd = ctx->snd_mss * n_left_to_next;
692 }
693 ctx->left_to_snd = ctx->max_len_to_snd;
694 n_left = ctx->n_segs_per_evt;
Florin Coras66cf5e02018-06-08 09:17:39 -0700695
696 while (n_left >= 4)
697 {
698 vlib_buffer_t *b0, *b1;
699 u32 bi0, bi1;
700
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700701 pbi = wrk->tx_buffers[n_bufs - 3];
Florin Coras66cf5e02018-06-08 09:17:39 -0700702 pb = vlib_get_buffer (vm, pbi);
703 vlib_prefetch_buffer_header (pb, STORE);
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700704 pbi = wrk->tx_buffers[n_bufs - 4];
Florin Coras66cf5e02018-06-08 09:17:39 -0700705 pb = vlib_get_buffer (vm, pbi);
706 vlib_prefetch_buffer_header (pb, STORE);
707
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700708 to_next[0] = bi0 = wrk->tx_buffers[--n_bufs];
709 to_next[1] = bi1 = wrk->tx_buffers[--n_bufs];
Florin Coras66cf5e02018-06-08 09:17:39 -0700710
711 b0 = vlib_get_buffer (vm, bi0);
712 b1 = vlib_get_buffer (vm, bi1);
713
714 session_tx_fill_buffer (vm, ctx, b0, &n_bufs, peek_data);
715 session_tx_fill_buffer (vm, ctx, b1, &n_bufs, peek_data);
716
717 ctx->transport_vft->push_header (ctx->tc, b0);
718 ctx->transport_vft->push_header (ctx->tc, b1);
719
720 to_next += 2;
721 n_left_to_next -= 2;
722 n_left -= 2;
723
724 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
725 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b1);
726
727 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
728 n_left_to_next, bi0, bi1, next0,
729 next1);
730 }
Florin Corasf08f26d2018-05-10 13:20:47 -0700731 while (n_left)
732 {
Florin Coras66cf5e02018-06-08 09:17:39 -0700733 vlib_buffer_t *b0;
734 u32 bi0;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700735
Florin Coras91ca4622018-06-30 11:27:59 -0700736 if (n_left > 1)
737 {
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700738 pbi = wrk->tx_buffers[n_bufs - 2];
Florin Coras91ca4622018-06-30 11:27:59 -0700739 pb = vlib_get_buffer (vm, pbi);
740 vlib_prefetch_buffer_header (pb, STORE);
741 }
742
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700743 to_next[0] = bi0 = wrk->tx_buffers[--n_bufs];
Florin Coras66cf5e02018-06-08 09:17:39 -0700744 b0 = vlib_get_buffer (vm, bi0);
745 session_tx_fill_buffer (vm, ctx, b0, &n_bufs, peek_data);
Florin Coras81a13db2018-03-16 08:48:31 -0700746
Florin Coras66cf5e02018-06-08 09:17:39 -0700747 /* Ask transport to push header after current_length and
748 * total_length_not_including_first_buffer are updated */
749 ctx->transport_vft->push_header (ctx->tc, b0);
Florin Corasf6359c82017-06-19 12:26:09 -0400750
Florin Coras66cf5e02018-06-08 09:17:39 -0700751 to_next += 1;
752 n_left_to_next -= 1;
753 n_left -= 1;
Dave Barach68b0fb02017-02-28 15:15:56 -0500754
Florin Coras66cf5e02018-06-08 09:17:39 -0700755 VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
Florin Coras7fb0fe12018-04-09 09:24:52 -0700756
Florin Coras66cf5e02018-06-08 09:17:39 -0700757 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
758 n_left_to_next, bi0, next0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500759 }
Florin Coras66cf5e02018-06-08 09:17:39 -0700760
761 if (PREDICT_FALSE (n_trace > 0))
762 session_tx_trace_frame (vm, node, next_index, to_next,
Florin Coras1bcad5c2019-01-09 20:04:38 -0800763 ctx->n_segs_per_evt, ctx->s, n_trace);
Florin Coras2068fd42019-01-31 14:35:50 -0800764 if (PREDICT_FALSE (n_bufs))
765 {
766 clib_warning ("not all buffers consumed");
767 vlib_buffer_free (vm, wrk->tx_buffers, n_bufs);
768 }
Florin Corasf08f26d2018-05-10 13:20:47 -0700769 *n_tx_packets += ctx->n_segs_per_evt;
Florin Corasd67f1122018-05-21 17:47:40 -0700770 transport_connection_update_tx_stats (ctx->tc, ctx->max_len_to_snd);
Florin Coras8e43d042018-05-04 15:46:57 -0700771 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
Dave Barach68b0fb02017-02-28 15:15:56 -0500772
Florin Coras6792ec02017-03-13 03:49:51 -0700773 /* If we couldn't dequeue all bytes mark as partially read */
Florin Corasf08f26d2018-05-10 13:20:47 -0700774 ASSERT (ctx->left_to_snd == 0);
Florin Coras8e43d042018-05-04 15:46:57 -0700775 if (ctx->max_len_to_snd < ctx->max_dequeue)
Florin Coras288eaab2019-02-03 15:26:14 -0800776 if (svm_fifo_set_event (ctx->s->tx_fifo))
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700777 vec_add1 (wrk->pending_event_vector, *e);
Florin Coras7fb0fe12018-04-09 09:24:52 -0700778
Florin Coras8e43d042018-05-04 15:46:57 -0700779 if (!peek_data && ctx->transport_vft->tx_type == TRANSPORT_TX_DGRAM)
Dave Barach68b0fb02017-02-28 15:15:56 -0500780 {
Florin Coras7fb0fe12018-04-09 09:24:52 -0700781 /* Fix dgram pre header */
Florin Coras8e43d042018-05-04 15:46:57 -0700782 if (ctx->max_len_to_snd < ctx->max_dequeue)
Florin Coras288eaab2019-02-03 15:26:14 -0800783 svm_fifo_overwrite_head (ctx->s->tx_fifo, (u8 *) & ctx->hdr,
Florin Coras7fb0fe12018-04-09 09:24:52 -0700784 sizeof (session_dgram_pre_hdr_t));
785 /* More data needs to be read */
Florin Coras288eaab2019-02-03 15:26:14 -0800786 else if (svm_fifo_max_dequeue (ctx->s->tx_fifo) > 0)
787 if (svm_fifo_set_event (ctx->s->tx_fifo))
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700788 vec_add1 (wrk->pending_event_vector, *e);
Dave Barach68b0fb02017-02-28 15:15:56 -0500789 }
Florin Coras0d60a0f2018-06-29 02:02:08 -0700790 return SESSION_TX_OK;
Dave Barach68b0fb02017-02-28 15:15:56 -0500791}
792
793int
Florin Corasd79b41e2017-03-04 05:37:52 -0800794session_tx_fifo_peek_and_snd (vlib_main_t * vm, vlib_node_runtime_t * node,
Florin Coras1bcad5c2019-01-09 20:04:38 -0800795 session_manager_worker_t * wrk,
796 session_event_t * e, int *n_tx_pkts)
Dave Barach68b0fb02017-02-28 15:15:56 -0500797{
Florin Coras1bcad5c2019-01-09 20:04:38 -0800798 return session_tx_fifo_read_and_snd_i (vm, node, wrk, e, n_tx_pkts, 1);
Dave Barach68b0fb02017-02-28 15:15:56 -0500799}
800
801int
Florin Corasd79b41e2017-03-04 05:37:52 -0800802session_tx_fifo_dequeue_and_snd (vlib_main_t * vm, vlib_node_runtime_t * node,
Florin Coras1bcad5c2019-01-09 20:04:38 -0800803 session_manager_worker_t * wrk,
804 session_event_t * e, int *n_tx_pkts)
Dave Barach68b0fb02017-02-28 15:15:56 -0500805{
Florin Coras1bcad5c2019-01-09 20:04:38 -0800806 return session_tx_fifo_read_and_snd_i (vm, node, wrk, e, n_tx_pkts, 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500807}
808
Florin Coras371ca502018-02-21 12:07:41 -0800809int
810session_tx_fifo_dequeue_internal (vlib_main_t * vm,
811 vlib_node_runtime_t * node,
Florin Coras1bcad5c2019-01-09 20:04:38 -0800812 session_manager_worker_t * wrk,
813 session_event_t * e, int *n_tx_pkts)
Florin Coras371ca502018-02-21 12:07:41 -0800814{
Florin Coras288eaab2019-02-03 15:26:14 -0800815 session_t *s = wrk->ctx.s;
Florin Coras371ca502018-02-21 12:07:41 -0800816 application_t *app;
Florin Coras1bcad5c2019-01-09 20:04:38 -0800817
Florin Corasef915342018-09-29 10:23:06 -0700818 if (PREDICT_FALSE (s->session_state == SESSION_STATE_CLOSED))
819 return 0;
Florin Corasab2f6db2018-08-31 14:31:41 -0700820 app = application_get (s->t_app_index);
Florin Coras288eaab2019-02-03 15:26:14 -0800821 svm_fifo_unset_event (s->tx_fifo);
Florin Coras0d60a0f2018-06-29 02:02:08 -0700822 return app->cb_fns.builtin_app_tx_callback (s);
Florin Coras371ca502018-02-21 12:07:41 -0800823}
824
Florin Coras288eaab2019-02-03 15:26:14 -0800825always_inline session_t *
Florin Coras52207f12018-07-12 14:48:06 -0700826session_event_get_session (session_event_t * e, u8 thread_index)
Florin Corasa5464812017-04-19 13:00:05 -0700827{
Florin Coras3cbc04b2017-10-02 00:18:51 -0700828 return session_get_if_valid (e->fifo->master_session_index, thread_index);
Florin Corasa5464812017-04-19 13:00:05 -0700829}
830
Florin Corasd67f1122018-05-21 17:47:40 -0700831static void
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700832session_update_dispatch_period (session_manager_worker_t * wrk, f64 now,
Florin Corasd67f1122018-05-21 17:47:40 -0700833 u32 thread_index)
834{
Florin Corasefefc6b2018-11-07 12:49:19 -0800835 if (wrk->last_tx_packets)
Florin Corasc44a5582018-11-01 16:30:54 -0700836 {
837 f64 sample = now - wrk->last_vlib_time;
Florin Corasc44a5582018-11-01 16:30:54 -0700838 wrk->dispatch_period = (wrk->dispatch_period + sample) * 0.5;
839 }
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700840 wrk->last_vlib_time = now;
Florin Corasd67f1122018-05-21 17:47:40 -0700841}
842
Florin Coras0d60a0f2018-06-29 02:02:08 -0700843static uword
844session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
845 vlib_frame_t * frame)
846{
847 session_manager_main_t *smm = vnet_get_session_manager_main ();
Florin Coras3c2fed52018-07-04 04:15:05 -0700848 u32 thread_index = vm->thread_index, n_to_dequeue, n_events;
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700849 session_manager_worker_t *wrk = &smm->wrk[thread_index];
Florin Coras5f56d732018-10-30 10:21:59 -0700850 session_event_t *e, *fifo_events;
Florin Coras3c2fed52018-07-04 04:15:05 -0700851 svm_msg_q_msg_t _msg, *msg = &_msg;
Florin Coras0d60a0f2018-06-29 02:02:08 -0700852 f64 now = vlib_time_now (vm);
Florin Coras3c2fed52018-07-04 04:15:05 -0700853 int n_tx_packets = 0, i, rv;
Florin Coras15531972018-08-12 23:50:53 -0700854 app_worker_t *app_wrk;
Florin Coras3c2fed52018-07-04 04:15:05 -0700855 application_t *app;
856 svm_msg_q_t *mq;
Florin Coras0d60a0f2018-06-29 02:02:08 -0700857 void (*fp) (void *);
858
859 SESSION_EVT_DBG (SESSION_EVT_POLL_GAP_TRACK, smm, thread_index);
860
861 /*
862 * Update transport time
863 */
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700864 session_update_dispatch_period (wrk, now, thread_index);
Florin Coras0d60a0f2018-06-29 02:02:08 -0700865 transport_update_time (now, thread_index);
866
Florin Coras0d60a0f2018-06-29 02:02:08 -0700867 SESSION_EVT_DBG (SESSION_EVT_DEQ_NODE, 0);
868
Florin Coras5f56d732018-10-30 10:21:59 -0700869 /* Make sure postponed events are handled first */
870 fifo_events = wrk->free_event_vector;
871 vec_append (fifo_events, wrk->postponed_event_vector);
Florin Coras36ee9f12018-11-02 12:52:10 -0700872 _vec_len (wrk->postponed_event_vector) = 0;
Florin Coras0d60a0f2018-06-29 02:02:08 -0700873
Florin Coras5f56d732018-10-30 10:21:59 -0700874 /* Try to dequeue what is available. Don't wait for lock.
875 * XXX: we may need priorities here */
876 mq = wrk->vpp_event_queue;
877 n_to_dequeue = svm_msg_q_size (mq);
878 if (n_to_dequeue && svm_msg_q_try_lock (mq) == 0)
879 {
880 for (i = 0; i < n_to_dequeue; i++)
881 {
882 vec_add2 (fifo_events, e, 1);
883 svm_msg_q_sub_w_lock (mq, msg);
Florin Coras3c7d4f92018-12-14 11:28:43 -0800884 /* Works because reply messages are smaller than a session evt.
885 * If we ever need to support bigger messages this needs to be
886 * fixed */
Dave Barach178cf492018-11-13 16:34:13 -0500887 clib_memcpy_fast (e, svm_msg_q_msg_data (mq, msg), sizeof (*e));
Florin Coras5f56d732018-10-30 10:21:59 -0700888 svm_msg_q_free_msg (mq, msg);
889 }
890 svm_msg_q_unlock (mq);
891 }
892
893 vec_append (fifo_events, wrk->pending_event_vector);
894 vec_append (fifo_events, wrk->pending_disconnects);
895
Florin Coras5f56d732018-10-30 10:21:59 -0700896 _vec_len (wrk->pending_event_vector) = 0;
Florin Coras36ee9f12018-11-02 12:52:10 -0700897 _vec_len (wrk->pending_disconnects) = 0;
Florin Coras5f56d732018-10-30 10:21:59 -0700898
Florin Coras0d60a0f2018-06-29 02:02:08 -0700899 n_events = vec_len (fifo_events);
Florin Coras5f56d732018-10-30 10:21:59 -0700900 if (PREDICT_FALSE (!n_events))
901 return 0;
902
Florin Coras0d60a0f2018-06-29 02:02:08 -0700903 for (i = 0; i < n_events; i++)
904 {
Florin Coras288eaab2019-02-03 15:26:14 -0800905 session_t *s; /* $$$ prefetch 1 ahead maybe */
Florin Coras52207f12018-07-12 14:48:06 -0700906 session_event_t *e;
Florin Coras1bcad5c2019-01-09 20:04:38 -0800907 u8 need_tx_ntf;
Florin Coras0d60a0f2018-06-29 02:02:08 -0700908
909 e = &fifo_events[i];
910 switch (e->event_type)
911 {
Florin Coras42ceddb2018-12-12 10:56:01 -0800912 case SESSION_IO_EVT_TX_FLUSH:
Florin Coras0d60a0f2018-06-29 02:02:08 -0700913 case FIFO_EVENT_APP_TX:
914 /* Don't try to send more that one frame per dispatch cycle */
915 if (n_tx_packets == VLIB_FRAME_SIZE)
916 {
Florin Coras5f56d732018-10-30 10:21:59 -0700917 vec_add1 (wrk->postponed_event_vector, *e);
Florin Coras0d60a0f2018-06-29 02:02:08 -0700918 break;
919 }
920
921 s = session_event_get_session (e, thread_index);
922 if (PREDICT_FALSE (!s))
923 {
Florin Coras326b81e2018-10-04 19:03:05 -0700924 clib_warning ("session was freed!");
Florin Coras0d60a0f2018-06-29 02:02:08 -0700925 continue;
926 }
Florin Coras1bcad5c2019-01-09 20:04:38 -0800927 wrk->ctx.s = s;
Florin Coras0d60a0f2018-06-29 02:02:08 -0700928 /* Spray packets in per session type frames, since they go to
929 * different nodes */
Florin Coras1bcad5c2019-01-09 20:04:38 -0800930 rv = (smm->session_tx_fns[s->session_type]) (vm, node, wrk, e,
Florin Coras0d60a0f2018-06-29 02:02:08 -0700931 &n_tx_packets);
932 if (PREDICT_TRUE (rv == SESSION_TX_OK))
933 {
Florin Coras288eaab2019-02-03 15:26:14 -0800934 need_tx_ntf = svm_fifo_needs_tx_ntf (s->tx_fifo,
Florin Coras1bcad5c2019-01-09 20:04:38 -0800935 wrk->ctx.max_len_to_snd);
936 if (PREDICT_FALSE (need_tx_ntf))
937 session_dequeue_notify (s);
Florin Coras0d60a0f2018-06-29 02:02:08 -0700938 }
939 else if (PREDICT_FALSE (rv == SESSION_TX_NO_BUFFERS))
940 {
941 vlib_node_increment_counter (vm, node->node_index,
942 SESSION_QUEUE_ERROR_NO_BUFFER, 1);
943 continue;
944 }
945 break;
946 case FIFO_EVENT_DISCONNECT:
Florin Coras3c7d4f92018-12-14 11:28:43 -0800947 s = session_get_from_handle_if_valid (e->session_handle);
948 if (PREDICT_FALSE (!s))
949 break;
950
Florin Corase96bf632018-12-18 22:44:27 -0800951 /* Make sure session disconnects run after the pending list is
952 * drained, i.e., postpone if the first time. If not the first
953 * and the tx queue is still not empty, try to wait for some
954 * dispatch cycles */
955 if (!e->postponed
Florin Coras288eaab2019-02-03 15:26:14 -0800956 || (e->postponed < 200 && svm_fifo_max_dequeue (s->tx_fifo)))
Florin Coras0d60a0f2018-06-29 02:02:08 -0700957 {
Florin Corase96bf632018-12-18 22:44:27 -0800958 e->postponed += 1;
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700959 vec_add1 (wrk->pending_disconnects, *e);
Florin Coras0d60a0f2018-06-29 02:02:08 -0700960 continue;
961 }
962
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800963 session_transport_close (s);
Florin Coras0d60a0f2018-06-29 02:02:08 -0700964 break;
965 case FIFO_EVENT_BUILTIN_RX:
966 s = session_event_get_session (e, thread_index);
Florin Corasef915342018-09-29 10:23:06 -0700967 if (PREDICT_FALSE (!s || s->session_state >= SESSION_STATE_CLOSING))
Florin Coras0d60a0f2018-06-29 02:02:08 -0700968 continue;
Florin Coras288eaab2019-02-03 15:26:14 -0800969 svm_fifo_unset_event (s->rx_fifo);
Florin Coras15531972018-08-12 23:50:53 -0700970 app_wrk = app_worker_get (s->app_wrk_index);
971 app = application_get (app_wrk->app_index);
Florin Coras0d60a0f2018-06-29 02:02:08 -0700972 app->cb_fns.builtin_app_rx_callback (s);
973 break;
Florin Corasef915342018-09-29 10:23:06 -0700974 case FIFO_EVENT_BUILTIN_TX:
975 s = session_get_from_handle_if_valid (e->session_handle);
Florin Coras1bcad5c2019-01-09 20:04:38 -0800976 wrk->ctx.s = s;
Florin Corasef915342018-09-29 10:23:06 -0700977 if (PREDICT_TRUE (s != 0))
Florin Coras1bcad5c2019-01-09 20:04:38 -0800978 session_tx_fifo_dequeue_internal (vm, node, wrk, e,
979 &n_tx_packets);
Florin Corasef915342018-09-29 10:23:06 -0700980 break;
Florin Coras0d60a0f2018-06-29 02:02:08 -0700981 case FIFO_EVENT_RPC:
982 fp = e->rpc_args.fp;
983 (*fp) (e->rpc_args.arg);
984 break;
Florin Coras52207f12018-07-12 14:48:06 -0700985 case SESSION_CTRL_EVT_DISCONNECTED:
986 session_mq_disconnected_handler (e->data);
987 break;
988 case SESSION_CTRL_EVT_ACCEPTED_REPLY:
989 session_mq_accepted_reply_handler (e->data);
990 break;
991 case SESSION_CTRL_EVT_CONNECTED_REPLY:
992 break;
993 case SESSION_CTRL_EVT_DISCONNECTED_REPLY:
994 session_mq_disconnected_reply_handler (e->data);
995 break;
996 case SESSION_CTRL_EVT_RESET_REPLY:
997 session_mq_reset_reply_handler (e->data);
998 break;
Florin Coras30e79c22019-01-02 19:31:22 -0800999 case SESSION_CTRL_EVT_WORKER_UPDATE:
1000 session_mq_worker_update_handler (e->data);
1001 break;
Florin Coras0d60a0f2018-06-29 02:02:08 -07001002 default:
1003 clib_warning ("unhandled event type %d", e->event_type);
1004 }
1005 }
1006
1007 _vec_len (fifo_events) = 0;
Florin Coras5a7ca7b2018-10-30 12:01:48 -07001008 wrk->free_event_vector = fifo_events;
Florin Corasc44a5582018-11-01 16:30:54 -07001009 wrk->last_tx_packets = n_tx_packets;
Florin Coras0d60a0f2018-06-29 02:02:08 -07001010
1011 vlib_node_increment_counter (vm, session_queue_node.index,
1012 SESSION_QUEUE_ERROR_TX, n_tx_packets);
1013
1014 SESSION_EVT_DBG (SESSION_EVT_DISPATCH_END, smm, thread_index);
1015
1016 return n_tx_packets;
1017}
1018
1019/* *INDENT-OFF* */
1020VLIB_REGISTER_NODE (session_queue_node) =
1021{
1022 .function = session_queue_node_fn,
1023 .name = "session-queue",
1024 .format_trace = format_session_queue_trace,
1025 .type = VLIB_NODE_TYPE_INPUT,
1026 .n_errors = ARRAY_LEN (session_queue_error_strings),
1027 .error_strings = session_queue_error_strings,
1028 .state = VLIB_NODE_STATE_DISABLED,
1029};
1030/* *INDENT-ON* */
1031
Dave Barachacd2a6a2017-05-16 17:41:34 -04001032void
1033dump_thread_0_event_queue (void)
1034{
1035 session_manager_main_t *smm = vnet_get_session_manager_main ();
1036 vlib_main_t *vm = &vlib_global_main;
1037 u32 my_thread_index = vm->thread_index;
Florin Coras52207f12018-07-12 14:48:06 -07001038 session_event_t _e, *e = &_e;
Florin Coras3c2fed52018-07-04 04:15:05 -07001039 svm_msg_q_ring_t *ring;
Florin Coras288eaab2019-02-03 15:26:14 -08001040 session_t *s0;
Florin Coras3c2fed52018-07-04 04:15:05 -07001041 svm_msg_q_msg_t *msg;
1042 svm_msg_q_t *mq;
Dave Barachacd2a6a2017-05-16 17:41:34 -04001043 int i, index;
Dave Barachacd2a6a2017-05-16 17:41:34 -04001044
Florin Coras5a7ca7b2018-10-30 12:01:48 -07001045 mq = smm->wrk[my_thread_index].vpp_event_queue;
Florin Coras3c2fed52018-07-04 04:15:05 -07001046 index = mq->q->head;
Dave Barachacd2a6a2017-05-16 17:41:34 -04001047
Florin Coras3c2fed52018-07-04 04:15:05 -07001048 for (i = 0; i < mq->q->cursize; i++)
Dave Barachacd2a6a2017-05-16 17:41:34 -04001049 {
Florin Coras3c2fed52018-07-04 04:15:05 -07001050 msg = (svm_msg_q_msg_t *) (&mq->q->data[0] + mq->q->elsize * index);
1051 ring = svm_msg_q_ring (mq, msg->ring_index);
Dave Barach178cf492018-11-13 16:34:13 -05001052 clib_memcpy_fast (e, svm_msg_q_msg_data (mq, msg), ring->elsize);
Dave Barachacd2a6a2017-05-16 17:41:34 -04001053
1054 switch (e->event_type)
1055 {
1056 case FIFO_EVENT_APP_TX:
1057 s0 = session_event_get_session (e, my_thread_index);
1058 fformat (stdout, "[%04d] TX session %d\n", i, s0->session_index);
1059 break;
1060
1061 case FIFO_EVENT_DISCONNECT:
Florin Corascea194d2017-10-02 00:18:51 -07001062 s0 = session_get_from_handle (e->session_handle);
Dave Barachacd2a6a2017-05-16 17:41:34 -04001063 fformat (stdout, "[%04d] disconnect session %d\n", i,
1064 s0->session_index);
1065 break;
1066
1067 case FIFO_EVENT_BUILTIN_RX:
1068 s0 = session_event_get_session (e, my_thread_index);
1069 fformat (stdout, "[%04d] builtin_rx %d\n", i, s0->session_index);
1070 break;
1071
1072 case FIFO_EVENT_RPC:
1073 fformat (stdout, "[%04d] RPC call %llx with %llx\n",
David Johnsond9818dd2018-12-14 14:53:41 -05001074 i, (u64) (uword) (e->rpc_args.fp),
1075 (u64) (uword) (e->rpc_args.arg));
Dave Barachacd2a6a2017-05-16 17:41:34 -04001076 break;
1077
1078 default:
1079 fformat (stdout, "[%04d] unhandled event type %d\n",
1080 i, e->event_type);
1081 break;
1082 }
1083
1084 index++;
1085
Florin Coras3c2fed52018-07-04 04:15:05 -07001086 if (index == mq->q->maxsize)
Dave Barachacd2a6a2017-05-16 17:41:34 -04001087 index = 0;
1088 }
1089}
1090
Florin Coras6534b7a2017-07-18 05:38:03 -04001091static u8
Florin Coras52207f12018-07-12 14:48:06 -07001092session_node_cmp_event (session_event_t * e, svm_fifo_t * f)
Florin Coras6534b7a2017-07-18 05:38:03 -04001093{
Florin Coras288eaab2019-02-03 15:26:14 -08001094 session_t *s;
Florin Coras6534b7a2017-07-18 05:38:03 -04001095 switch (e->event_type)
1096 {
1097 case FIFO_EVENT_APP_RX:
1098 case FIFO_EVENT_APP_TX:
1099 case FIFO_EVENT_BUILTIN_RX:
1100 if (e->fifo == f)
1101 return 1;
1102 break;
1103 case FIFO_EVENT_DISCONNECT:
1104 break;
1105 case FIFO_EVENT_RPC:
Florin Corascea194d2017-10-02 00:18:51 -07001106 s = session_get_from_handle (e->session_handle);
Florin Coras6534b7a2017-07-18 05:38:03 -04001107 if (!s)
1108 {
1109 clib_warning ("session has event but doesn't exist!");
1110 break;
1111 }
Florin Coras288eaab2019-02-03 15:26:14 -08001112 if (s->rx_fifo == f || s->tx_fifo == f)
Florin Coras6534b7a2017-07-18 05:38:03 -04001113 return 1;
1114 break;
1115 default:
1116 break;
1117 }
1118 return 0;
1119}
1120
1121u8
Florin Coras52207f12018-07-12 14:48:06 -07001122session_node_lookup_fifo_event (svm_fifo_t * f, session_event_t * e)
Florin Coras6534b7a2017-07-18 05:38:03 -04001123{
Florin Coras52207f12018-07-12 14:48:06 -07001124 session_event_t *pending_event_vector, *evt;
Florin Coras5a7ca7b2018-10-30 12:01:48 -07001125 session_manager_worker_t *wrk;
Florin Coras6534b7a2017-07-18 05:38:03 -04001126 int i, index, found = 0;
Florin Coras3c2fed52018-07-04 04:15:05 -07001127 svm_msg_q_msg_t *msg;
1128 svm_msg_q_ring_t *ring;
Florin Coras5a7ca7b2018-10-30 12:01:48 -07001129 svm_msg_q_t *mq;
Florin Coras6534b7a2017-07-18 05:38:03 -04001130 u8 thread_index;
1131
1132 ASSERT (e);
1133 thread_index = f->master_thread_index;
Florin Coras5a7ca7b2018-10-30 12:01:48 -07001134 wrk = session_manager_get_worker (thread_index);
1135
Florin Coras6534b7a2017-07-18 05:38:03 -04001136 /*
1137 * Search evt queue
1138 */
Florin Coras5a7ca7b2018-10-30 12:01:48 -07001139 mq = wrk->vpp_event_queue;
Florin Coras3c2fed52018-07-04 04:15:05 -07001140 index = mq->q->head;
1141 for (i = 0; i < mq->q->cursize; i++)
Florin Coras6534b7a2017-07-18 05:38:03 -04001142 {
Florin Coras3c2fed52018-07-04 04:15:05 -07001143 msg = (svm_msg_q_msg_t *) (&mq->q->data[0] + mq->q->elsize * index);
1144 ring = svm_msg_q_ring (mq, msg->ring_index);
Dave Barach178cf492018-11-13 16:34:13 -05001145 clib_memcpy_fast (e, svm_msg_q_msg_data (mq, msg), ring->elsize);
Florin Coras6534b7a2017-07-18 05:38:03 -04001146 found = session_node_cmp_event (e, f);
1147 if (found)
Florin Coras371ca502018-02-21 12:07:41 -08001148 return 1;
Florin Coras3c2fed52018-07-04 04:15:05 -07001149 if (++index == mq->q->maxsize)
Florin Coras6534b7a2017-07-18 05:38:03 -04001150 index = 0;
1151 }
1152 /*
1153 * Search pending events vector
1154 */
Florin Coras5a7ca7b2018-10-30 12:01:48 -07001155 pending_event_vector = wrk->pending_event_vector;
Florin Coras6534b7a2017-07-18 05:38:03 -04001156 vec_foreach (evt, pending_event_vector)
1157 {
1158 found = session_node_cmp_event (evt, f);
1159 if (found)
1160 {
Dave Barach178cf492018-11-13 16:34:13 -05001161 clib_memcpy_fast (e, evt, sizeof (*evt));
Florin Coras6534b7a2017-07-18 05:38:03 -04001162 break;
1163 }
1164 }
1165 return found;
1166}
1167
Dave Barach2a863912017-11-28 10:11:42 -05001168static clib_error_t *
1169session_queue_exit (vlib_main_t * vm)
1170{
1171 if (vec_len (vlib_mains) < 2)
1172 return 0;
1173
1174 /*
1175 * Shut off (especially) worker-thread session nodes.
1176 * Otherwise, vpp can crash as the main thread unmaps the
1177 * API segment.
1178 */
1179 vlib_worker_thread_barrier_sync (vm);
1180 session_node_enable_disable (0 /* is_enable */ );
1181 vlib_worker_thread_barrier_release (vm);
1182 return 0;
1183}
1184
1185VLIB_MAIN_LOOP_EXIT_FUNCTION (session_queue_exit);
1186
Florin Corasfd542f12018-05-16 19:28:24 -07001187static uword
1188session_queue_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
1189 vlib_frame_t * f)
1190{
1191 f64 now, timeout = 1.0;
1192 uword *event_data = 0;
1193 uword event_type;
1194
1195 while (1)
1196 {
1197 vlib_process_wait_for_event_or_clock (vm, timeout);
1198 now = vlib_time_now (vm);
1199 event_type = vlib_process_get_events (vm, (uword **) & event_data);
1200
1201 switch (event_type)
1202 {
1203 case SESSION_Q_PROCESS_FLUSH_FRAMES:
1204 /* Flush the frames by updating all transports times */
1205 transport_update_time (now, 0);
1206 break;
1207 case SESSION_Q_PROCESS_STOP:
1208 timeout = 100000.0;
1209 break;
1210 case ~0:
1211 /* Timed out. Update time for all transports to trigger all
1212 * outstanding retransmits. */
1213 transport_update_time (now, 0);
1214 break;
1215 }
1216 vec_reset_length (event_data);
1217 }
1218 return 0;
1219}
1220
1221/* *INDENT-OFF* */
1222VLIB_REGISTER_NODE (session_queue_process_node) =
1223{
1224 .function = session_queue_process,
1225 .type = VLIB_NODE_TYPE_PROCESS,
1226 .name = "session-queue-process",
1227 .state = VLIB_NODE_STATE_DISABLED,
1228};
1229/* *INDENT-ON* */
1230
Dave Barach68b0fb02017-02-28 15:15:56 -05001231/*
1232 * fd.io coding-style-patch-verification: ON
1233 *
1234 * Local Variables:
1235 * eval: (c-set-style "gnu")
1236 * End:
1237 */