blob: c1becf2c5ea06c5fd062812e5700e0728be24850 [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/**
16 * @file
17 * @brief Session and session manager
18 */
19
qinyangaf9b7152023-06-27 01:11:53 -070020#include <vnet/plugin/plugin.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050021#include <vnet/session/session.h>
Florin Coras04e53442017-07-16 17:12:15 -070022#include <vnet/session/application.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050023#include <vnet/dpo/load_balance.h>
24#include <vnet/fib/ip4_fib.h>
Florin Corasd82f4712022-04-25 16:15:02 -070025#include <vlib/stats/stats.h>
Marvin Liu06542422022-08-16 06:49:09 +000026#include <vlib/dma/dma.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050027
Florin Coras31c99552019-03-01 13:00:58 -080028session_main_t session_main;
Florin Coras3eb50622017-07-13 01:24:57 -040029
Florin Coras3c2fed52018-07-04 04:15:05 -070030static inline int
31session_send_evt_to_thread (void *data, void *args, u32 thread_index,
32 session_evt_type_t evt_type)
Florin Coras3cbc04b2017-10-02 00:18:51 -070033{
Florin Coras7da88292021-03-18 15:04:34 -070034 session_worker_t *wrk = session_main_get_worker (thread_index);
Florin Coras52207f12018-07-12 14:48:06 -070035 session_event_t *evt;
Florin Coras3c2fed52018-07-04 04:15:05 -070036 svm_msg_q_msg_t msg;
37 svm_msg_q_t *mq;
Florin Coras3cbc04b2017-10-02 00:18:51 -070038
Florin Coras7da88292021-03-18 15:04:34 -070039 mq = wrk->vpp_event_queue;
Nathan Skrzypczakb4c67752019-06-20 09:58:37 +020040 if (PREDICT_FALSE (svm_msg_q_lock (mq)))
41 return -1;
Florin Coras80d100c2022-04-19 18:57:24 -070042 if (PREDICT_FALSE (svm_msg_q_or_ring_is_full (mq, SESSION_MQ_IO_EVT_RING)))
Florin Coras3c2fed52018-07-04 04:15:05 -070043 {
44 svm_msg_q_unlock (mq);
45 return -2;
46 }
Florin Coras3c2fed52018-07-04 04:15:05 -070047 switch (evt_type)
48 {
Florin Corasf6c43132019-03-01 12:41:21 -080049 case SESSION_CTRL_EVT_RPC:
Nathan Skrzypczak1afa7af2019-09-13 17:14:57 +020050 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
51 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Coras3c2fed52018-07-04 04:15:05 -070052 evt->rpc_args.fp = data;
53 evt->rpc_args.arg = args;
54 break;
Aloys Augustin0c7f54d2019-07-03 16:59:43 +020055 case SESSION_IO_EVT_RX:
Florin Corasf6c43132019-03-01 12:41:21 -080056 case SESSION_IO_EVT_TX:
Florin Coras844a36d2018-12-20 09:50:50 -080057 case SESSION_IO_EVT_TX_FLUSH:
Florin Corasf6c43132019-03-01 12:41:21 -080058 case SESSION_IO_EVT_BUILTIN_RX:
Nathan Skrzypczak1afa7af2019-09-13 17:14:57 +020059 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
60 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Corasc0737e92019-03-04 14:19:39 -080061 evt->session_index = *(u32 *) data;
Florin Coras3c2fed52018-07-04 04:15:05 -070062 break;
Florin Corasaeb7c1c2023-03-10 10:22:21 -080063 case SESSION_IO_EVT_TX_MAIN:
Florin Corasf6c43132019-03-01 12:41:21 -080064 case SESSION_CTRL_EVT_CLOSE:
Florin Coras73cad332019-08-28 17:12:32 -070065 case SESSION_CTRL_EVT_RESET:
Nathan Skrzypczak1afa7af2019-09-13 17:14:57 +020066 msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
67 evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
Florin Coras288eaab2019-02-03 15:26:14 -080068 evt->session_handle = session_handle ((session_t *) data);
Florin Coras3c2fed52018-07-04 04:15:05 -070069 break;
70 default:
71 clib_warning ("evt unhandled!");
72 svm_msg_q_unlock (mq);
73 return -1;
74 }
Nathan Skrzypczak1afa7af2019-09-13 17:14:57 +020075 evt->event_type = evt_type;
Florin Coras3c2fed52018-07-04 04:15:05 -070076
Florin Coras52207f12018-07-12 14:48:06 -070077 svm_msg_q_add_and_unlock (mq, &msg);
Florin Coras7da88292021-03-18 15:04:34 -070078
79 if (PREDICT_FALSE (wrk->state == SESSION_WRK_INTERRUPT))
80 vlib_node_set_interrupt_pending (wrk->vm, session_queue_node.index);
81
Florin Coras3c2fed52018-07-04 04:15:05 -070082 return 0;
Florin Coras3cbc04b2017-10-02 00:18:51 -070083}
84
Florin Coras3c2fed52018-07-04 04:15:05 -070085int
86session_send_io_evt_to_thread (svm_fifo_t * f, session_evt_type_t evt_type)
Florin Coras3cbc04b2017-10-02 00:18:51 -070087{
Florin Corasc547e912020-12-08 17:50:45 -080088 return session_send_evt_to_thread (&f->shr->master_session_index, 0,
Florin Corasc0737e92019-03-04 14:19:39 -080089 f->master_thread_index, evt_type);
Florin Coras3c2fed52018-07-04 04:15:05 -070090}
91
92int
Florin Corasef915342018-09-29 10:23:06 -070093session_send_io_evt_to_thread_custom (void *data, u32 thread_index,
Florin Coras3c2fed52018-07-04 04:15:05 -070094 session_evt_type_t evt_type)
95{
Florin Corasef915342018-09-29 10:23:06 -070096 return session_send_evt_to_thread (data, 0, thread_index, evt_type);
Florin Coras3c2fed52018-07-04 04:15:05 -070097}
98
99int
Florin Coras7e9e2bd2024-03-22 16:29:09 -0700100session_program_tx_io_evt (session_handle_tu_t sh, session_evt_type_t evt_type)
101{
102 return session_send_evt_to_thread ((void *) &sh.session_index, 0,
103 (u32) sh.thread_index, evt_type);
104}
105
106int
Florin Coras129ff042024-07-08 15:15:07 -0700107session_program_rx_io_evt (session_handle_tu_t sh)
108{
109 if (sh.thread_index == vlib_get_thread_index ())
110 {
111 session_t *s = session_get_from_handle (sh);
112 return session_enqueue_notify (s);
113 }
114 else
115 {
116 return session_send_evt_to_thread ((void *) &sh.session_index, 0,
117 (u32) sh.thread_index,
118 SESSION_IO_EVT_BUILTIN_RX);
119 }
120}
121
122int
Florin Coras288eaab2019-02-03 15:26:14 -0800123session_send_ctrl_evt_to_thread (session_t * s, session_evt_type_t evt_type)
Florin Coras3c2fed52018-07-04 04:15:05 -0700124{
liuyacan534468e2021-05-09 03:50:40 +0000125 /* only events supported are disconnect, shutdown and reset */
126 ASSERT (evt_type == SESSION_CTRL_EVT_CLOSE ||
127 evt_type == SESSION_CTRL_EVT_HALF_CLOSE ||
128 evt_type == SESSION_CTRL_EVT_RESET);
Florin Coras458089b2019-08-21 16:20:44 -0700129 return session_send_evt_to_thread (s, 0, s->thread_index, evt_type);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700130}
131
132void
Nathan Skrzypczak60f3e652019-03-19 13:57:31 +0100133session_send_rpc_evt_to_thread_force (u32 thread_index, void *fp,
134 void *rpc_args)
135{
136 session_send_evt_to_thread (fp, rpc_args, thread_index,
137 SESSION_CTRL_EVT_RPC);
138}
139
140void
Florin Coras3cbc04b2017-10-02 00:18:51 -0700141session_send_rpc_evt_to_thread (u32 thread_index, void *fp, void *rpc_args)
142{
143 if (thread_index != vlib_get_thread_index ())
Nathan Skrzypczak60f3e652019-03-19 13:57:31 +0100144 session_send_rpc_evt_to_thread_force (thread_index, fp, rpc_args);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700145 else
146 {
147 void (*fnp) (void *) = fp;
148 fnp (rpc_args);
149 }
150}
151
Florin Coras26dd6de2019-07-23 23:54:47 -0700152void
153session_add_self_custom_tx_evt (transport_connection_t * tc, u8 has_prio)
154{
Florin Coras7da88292021-03-18 15:04:34 -0700155 session_t *s = session_get (tc->s_index, tc->thread_index);
Florin Coras26dd6de2019-07-23 23:54:47 -0700156
Florin Coras26dd6de2019-07-23 23:54:47 -0700157 ASSERT (s->thread_index == vlib_get_thread_index ());
Florin Corasbe237bf2019-09-27 08:16:40 -0700158 ASSERT (s->session_state != SESSION_STATE_TRANSPORT_DELETED);
Florin Coras7da88292021-03-18 15:04:34 -0700159
Florin Coras26dd6de2019-07-23 23:54:47 -0700160 if (!(s->flags & SESSION_F_CUSTOM_TX))
161 {
162 s->flags |= SESSION_F_CUSTOM_TX;
Florin Coras6080e0d2020-03-13 20:39:43 +0000163 if (svm_fifo_set_event (s->tx_fifo)
164 || transport_connection_is_descheduled (tc))
Florin Coras26dd6de2019-07-23 23:54:47 -0700165 {
Florin Coras26dd6de2019-07-23 23:54:47 -0700166 session_evt_elt_t *elt;
Florin Coras7da88292021-03-18 15:04:34 -0700167 session_worker_t *wrk;
168
Florin Coras26dd6de2019-07-23 23:54:47 -0700169 wrk = session_main_get_worker (tc->thread_index);
170 if (has_prio)
171 elt = session_evt_alloc_new (wrk);
172 else
173 elt = session_evt_alloc_old (wrk);
174 elt->evt.session_index = tc->s_index;
175 elt->evt.event_type = SESSION_IO_EVT_TX;
Florin Coras6080e0d2020-03-13 20:39:43 +0000176 tc->flags &= ~TRANSPORT_CONNECTION_F_DESCHED;
Florin Coras7da88292021-03-18 15:04:34 -0700177
178 if (PREDICT_FALSE (wrk->state == SESSION_WRK_INTERRUPT))
179 vlib_node_set_interrupt_pending (wrk->vm,
180 session_queue_node.index);
Florin Coras26dd6de2019-07-23 23:54:47 -0700181 }
182 }
183}
184
Florin Coras70f879d2020-03-13 17:54:42 +0000185void
186sesssion_reschedule_tx (transport_connection_t * tc)
187{
188 session_worker_t *wrk = session_main_get_worker (tc->thread_index);
189 session_evt_elt_t *elt;
190
191 ASSERT (tc->thread_index == vlib_get_thread_index ());
192
193 elt = session_evt_alloc_new (wrk);
194 elt->evt.session_index = tc->s_index;
195 elt->evt.event_type = SESSION_IO_EVT_TX;
Florin Coras7da88292021-03-18 15:04:34 -0700196
197 if (PREDICT_FALSE (wrk->state == SESSION_WRK_INTERRUPT))
198 vlib_node_set_interrupt_pending (wrk->vm, session_queue_node.index);
Florin Coras70f879d2020-03-13 17:54:42 +0000199}
200
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800201static void
Florin Corasdfb3b872019-08-16 17:48:44 -0700202session_program_transport_ctrl_evt (session_t * s, session_evt_type_t evt)
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800203{
204 u32 thread_index = vlib_get_thread_index ();
Florin Coras2062ec02019-07-15 13:15:18 -0700205 session_evt_elt_t *elt;
Florin Coras31c99552019-03-01 13:00:58 -0800206 session_worker_t *wrk;
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800207
208 /* If we are in the handler thread, or being called with the worker barrier
209 * held, just append a new event to pending disconnects vector. */
210 if (vlib_thread_is_main_w_barrier () || thread_index == s->thread_index)
211 {
Florin Coras31c99552019-03-01 13:00:58 -0800212 wrk = session_main_get_worker (s->thread_index);
Florin Corasb0ffbee2019-07-21 19:23:46 -0700213 elt = session_evt_alloc_ctrl (wrk);
Florin Coras2062ec02019-07-15 13:15:18 -0700214 clib_memset (&elt->evt, 0, sizeof (session_event_t));
215 elt->evt.session_handle = session_handle (s);
Florin Corasdfb3b872019-08-16 17:48:44 -0700216 elt->evt.event_type = evt;
Florin Coras7da88292021-03-18 15:04:34 -0700217
218 if (PREDICT_FALSE (wrk->state == SESSION_WRK_INTERRUPT))
219 vlib_node_set_interrupt_pending (wrk->vm, session_queue_node.index);
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800220 }
221 else
Florin Corasdfb3b872019-08-16 17:48:44 -0700222 session_send_ctrl_evt_to_thread (s, evt);
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800223}
224
Florin Coras288eaab2019-02-03 15:26:14 -0800225session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -0700226session_alloc (u32 thread_index)
Dave Barach68b0fb02017-02-28 15:15:56 -0500227{
Florin Coras31c99552019-03-01 13:00:58 -0800228 session_worker_t *wrk = &session_main.wrk[thread_index];
Florin Coras288eaab2019-02-03 15:26:14 -0800229 session_t *s;
Damjan Marion66d4cb52022-03-17 18:59:46 +0100230
Florin Corasd3915dc2022-03-31 15:42:17 -0700231 pool_get_aligned_safe (wrk->sessions, s, CLIB_CACHE_LINE_BYTES);
Dave Barachb7b92992018-10-17 10:38:51 -0400232 clib_memset (s, 0, sizeof (*s));
Florin Coras5a7ca7b2018-10-30 12:01:48 -0700233 s->session_index = s - wrk->sessions;
Florin Coras3cbc04b2017-10-02 00:18:51 -0700234 s->thread_index = thread_index;
Florin Coras97fef282023-12-21 19:41:12 -0800235 s->al_index = APP_INVALID_INDEX;
Florin Coras6bd8d3f2022-03-14 21:17:25 -0700236
Florin Coras3cbc04b2017-10-02 00:18:51 -0700237 return s;
238}
239
Florin Coras371ca502018-02-21 12:07:41 -0800240void
Florin Coras288eaab2019-02-03 15:26:14 -0800241session_free (session_t * s)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700242{
Steven Luong20de85b2022-10-17 10:39:06 -0700243 session_worker_t *wrk = &session_main.wrk[s->thread_index];
244
Florin Corascca96182019-07-19 07:34:13 -0700245 SESSION_EVT (SESSION_EVT_FREE, s);
Steven Luong20de85b2022-10-17 10:39:06 -0700246 if (CLIB_DEBUG)
247 clib_memset (s, 0xFA, sizeof (*s));
248 pool_put (wrk->sessions, s);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700249}
250
Srikanth Akulae140d5d2019-11-18 11:49:58 -0800251u8
252session_is_valid (u32 si, u8 thread_index)
253{
254 session_t *s;
255 transport_connection_t *tc;
256
257 s = pool_elt_at_index (session_main.wrk[thread_index].sessions, si);
258
Srikanth Akulae140d5d2019-11-18 11:49:58 -0800259 if (s->thread_index != thread_index || s->session_index != si)
260 return 0;
261
262 if (s->session_state == SESSION_STATE_TRANSPORT_DELETED
263 || s->session_state <= SESSION_STATE_LISTENING)
264 return 1;
265
Florin Coras0242d302022-12-22 15:03:44 -0800266 if ((s->session_state == SESSION_STATE_CONNECTING ||
267 s->session_state == SESSION_STATE_TRANSPORT_CLOSED) &&
Florin Corasea727642021-05-07 19:39:43 -0700268 (s->flags & SESSION_F_HALF_OPEN))
269 return 1;
270
Srikanth Akulae140d5d2019-11-18 11:49:58 -0800271 tc = session_get_transport (s);
Florin Coras0242d302022-12-22 15:03:44 -0800272 if (s->connection_index != tc->c_index ||
273 s->thread_index != tc->thread_index || tc->s_index != si)
Srikanth Akulae140d5d2019-11-18 11:49:58 -0800274 return 0;
275
276 return 1;
277}
278
Florin Coras0242d302022-12-22 15:03:44 -0800279void
280session_cleanup (session_t *s)
281{
282 segment_manager_dealloc_fifos (s->rx_fifo, s->tx_fifo);
283 session_free (s);
284}
285
Florin Coras70f26d52019-07-08 11:47:18 -0700286static void
287session_cleanup_notify (session_t * s, session_cleanup_ntf_t ntf)
288{
289 app_worker_t *app_wrk;
290
291 app_wrk = app_worker_get_if_valid (s->app_wrk_index);
Florin Coras9a5caec2024-04-16 16:53:14 -0700292 if (PREDICT_FALSE (!app_wrk))
Florin Coras0242d302022-12-22 15:03:44 -0800293 {
294 if (ntf == SESSION_CLEANUP_TRANSPORT)
295 return;
296
297 session_cleanup (s);
298 return;
299 }
Florin Coras70f26d52019-07-08 11:47:18 -0700300 app_worker_cleanup_notify (app_wrk, s, ntf);
301}
302
Florin Coraseb97e5f2018-10-15 21:35:42 -0700303void
Florin Coras0242d302022-12-22 15:03:44 -0800304session_program_cleanup (session_t *s)
Florin Coras568ebc72018-09-18 16:12:50 -0700305{
Florin Coras0242d302022-12-22 15:03:44 -0800306 ASSERT (s->session_state == SESSION_STATE_TRANSPORT_DELETED);
Florin Coras70f26d52019-07-08 11:47:18 -0700307 session_cleanup_notify (s, SESSION_CLEANUP_SESSION);
Florin Coras568ebc72018-09-18 16:12:50 -0700308}
309
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800310/**
311 * Cleans up session and lookup table.
312 *
313 * Transport connection must still be valid.
314 */
315static void
Florin Coras288eaab2019-02-03 15:26:14 -0800316session_delete (session_t * s)
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800317{
318 int rv;
319
320 /* Delete from the main lookup table. */
321 if ((rv = session_lookup_del_session (s)))
Florin Corasd09236d2019-08-08 17:38:26 -0700322 clib_warning ("session %u hash delete rv %d", s->session_index, rv);
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800323
Florin Coras0242d302022-12-22 15:03:44 -0800324 session_program_cleanup (s);
Florin Coras5a2ec8f2018-12-27 11:53:11 -0800325}
326
Florin Corasd50ff7f2020-04-16 04:30:22 +0000327void
Florin Corasea727642021-05-07 19:39:43 -0700328session_cleanup_half_open (session_handle_t ho_handle)
Florin Corasd50ff7f2020-04-16 04:30:22 +0000329{
Florin Corasbab6c522021-05-13 08:36:56 -0700330 session_t *ho = session_get_from_handle (ho_handle);
331
332 /* App transports can migrate their half-opens */
333 if (ho->flags & SESSION_F_IS_MIGRATING)
334 {
335 /* Session still migrating, move to closed state to signal that the
336 * session should be removed. */
337 if (ho->connection_index == ~0)
338 {
Steven Luongd810a6e2022-10-25 13:09:11 -0700339 session_set_state (ho, SESSION_STATE_CLOSED);
Florin Corasbab6c522021-05-13 08:36:56 -0700340 return;
341 }
342 /* Migrated transports are no longer half-opens */
343 transport_cleanup (session_get_transport_proto (ho),
Florin Coras97fef282023-12-21 19:41:12 -0800344 ho->connection_index, ho->al_index /* overloaded */);
Florin Corasbab6c522021-05-13 08:36:56 -0700345 }
Florin Coras0242d302022-12-22 15:03:44 -0800346 else if (ho->session_state != SESSION_STATE_TRANSPORT_DELETED)
Florin Corasc9fb9872023-03-19 22:03:57 -0700347 {
348 /* Cleanup half-open session lookup table if need be */
Florin Coras4aeba372023-06-20 16:50:51 -0700349 if (ho->session_state != SESSION_STATE_TRANSPORT_CLOSED)
Florin Corasc9fb9872023-03-19 22:03:57 -0700350 {
351 transport_connection_t *tc;
352 tc = transport_get_half_open (session_get_transport_proto (ho),
353 ho->connection_index);
354 if (tc && !(tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
355 session_lookup_del_half_open (tc);
356 }
357 transport_cleanup_half_open (session_get_transport_proto (ho),
358 ho->connection_index);
359 }
Florin Coras374df7a2021-05-13 11:37:43 -0700360 session_free (ho);
Florin Corasbab6c522021-05-13 08:36:56 -0700361}
362
363static void
Florin Coras374df7a2021-05-13 11:37:43 -0700364session_half_open_free (session_t *ho)
Florin Corasbab6c522021-05-13 08:36:56 -0700365{
366 app_worker_t *app_wrk;
Florin Corasbab6c522021-05-13 08:36:56 -0700367
Florin Corasc9fb9872023-03-19 22:03:57 -0700368 ASSERT (vlib_get_thread_index () <= transport_cl_thread ());
369 app_wrk = app_worker_get_if_valid (ho->app_wrk_index);
370 if (app_wrk)
371 app_worker_del_half_open (app_wrk, ho);
Florin Coras0242d302022-12-22 15:03:44 -0800372 else
373 session_free (ho);
Florin Corasbab6c522021-05-13 08:36:56 -0700374}
375
376static void
377session_half_open_free_rpc (void *args)
378{
Florin Coras374df7a2021-05-13 11:37:43 -0700379 session_t *ho = ho_session_get (pointer_to_uword (args));
380 session_half_open_free (ho);
Florin Corasd50ff7f2020-04-16 04:30:22 +0000381}
382
383void
Florin Corasea727642021-05-07 19:39:43 -0700384session_half_open_delete_notify (transport_connection_t *tc)
Florin Corasd50ff7f2020-04-16 04:30:22 +0000385{
Florin Corasc9fb9872023-03-19 22:03:57 -0700386 session_t *ho = ho_session_get (tc->s_index);
387
388 /* Cleanup half-open lookup table if need be */
Florin Coras4aeba372023-06-20 16:50:51 -0700389 if (ho->session_state != SESSION_STATE_TRANSPORT_CLOSED)
Florin Corasc9fb9872023-03-19 22:03:57 -0700390 {
391 if (!(tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
392 session_lookup_del_half_open (tc);
393 }
Florin Coras0242d302022-12-22 15:03:44 -0800394 session_set_state (ho, SESSION_STATE_TRANSPORT_DELETED);
Florin Corasc9fb9872023-03-19 22:03:57 -0700395
Florin Coras374df7a2021-05-13 11:37:43 -0700396 /* Notification from ctrl thread accepted without rpc */
Florin Coras309f7aa2022-03-18 08:33:08 -0700397 if (tc->thread_index == transport_cl_thread ())
Florin Coras374df7a2021-05-13 11:37:43 -0700398 {
Florin Corasc9fb9872023-03-19 22:03:57 -0700399 session_half_open_free (ho);
Florin Coras374df7a2021-05-13 11:37:43 -0700400 }
401 else
402 {
403 void *args = uword_to_pointer ((uword) tc->s_index, void *);
Florin Coras309f7aa2022-03-18 08:33:08 -0700404 session_send_rpc_evt_to_thread_force (transport_cl_thread (),
405 session_half_open_free_rpc, args);
Florin Coras374df7a2021-05-13 11:37:43 -0700406 }
Florin Corasbab6c522021-05-13 08:36:56 -0700407}
Florin Corasea727642021-05-07 19:39:43 -0700408
Florin Corasbab6c522021-05-13 08:36:56 -0700409void
410session_half_open_migrate_notify (transport_connection_t *tc)
411{
412 session_t *ho;
413
Florin Corasc9fb9872023-03-19 22:03:57 -0700414 /* Support half-open migrations only for transports with no lookup */
415 ASSERT (tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP);
416
Florin Corasbab6c522021-05-13 08:36:56 -0700417 ho = ho_session_get (tc->s_index);
418 ho->flags |= SESSION_F_IS_MIGRATING;
419 ho->connection_index = ~0;
420}
421
422int
423session_half_open_migrated_notify (transport_connection_t *tc)
424{
425 session_t *ho;
426
427 ho = ho_session_get (tc->s_index);
428
429 /* App probably detached so the half-open must be cleaned up */
430 if (ho->session_state == SESSION_STATE_CLOSED)
431 {
432 session_half_open_delete_notify (tc);
433 return -1;
434 }
435 ho->connection_index = tc->c_index;
Florin Coras97fef282023-12-21 19:41:12 -0800436 /* Overload al_index for half-open with new thread */
437 ho->al_index = tc->thread_index;
Florin Corasbab6c522021-05-13 08:36:56 -0700438 return 0;
Florin Corasd50ff7f2020-04-16 04:30:22 +0000439}
440
Andreas Schultz1a8c4372020-03-20 09:39:59 +0100441session_t *
Florin Coras3cbc04b2017-10-02 00:18:51 -0700442session_alloc_for_connection (transport_connection_t * tc)
443{
Florin Coras288eaab2019-02-03 15:26:14 -0800444 session_t *s;
Florin Coras3cbc04b2017-10-02 00:18:51 -0700445 u32 thread_index = tc->thread_index;
446
Florin Coras40903ac2018-06-10 14:41:23 -0700447 ASSERT (thread_index == vlib_get_thread_index ()
448 || transport_protocol_is_cl (tc->proto));
Dave Barach2c25a622017-06-26 11:35:07 -0400449
Florin Coras3cbc04b2017-10-02 00:18:51 -0700450 s = session_alloc (thread_index);
451 s->session_type = session_type_from_proto_and_ip (tc->proto, tc->is_ip4);
Steven Luongd810a6e2022-10-25 13:09:11 -0700452 session_set_state (s, SESSION_STATE_CLOSED);
Dave Barach68b0fb02017-02-28 15:15:56 -0500453
Florin Coras3cbc04b2017-10-02 00:18:51 -0700454 /* Attach transport to session and vice versa */
Dave Barach68b0fb02017-02-28 15:15:56 -0500455 s->connection_index = tc->c_index;
Dave Barach68b0fb02017-02-28 15:15:56 -0500456 tc->s_index = s->session_index;
Florin Coras3cbc04b2017-10-02 00:18:51 -0700457 return s;
458}
459
Florin Coras2c876f92021-05-10 21:12:27 -0700460session_t *
Florin Corasea727642021-05-07 19:39:43 -0700461session_alloc_for_half_open (transport_connection_t *tc)
462{
463 session_t *s;
464
465 s = ho_session_alloc ();
466 s->session_type = session_type_from_proto_and_ip (tc->proto, tc->is_ip4);
467 s->connection_index = tc->c_index;
468 tc->s_index = s->session_index;
469 return s;
470}
471
Florin Coras1f152cd2017-08-18 19:28:03 -0700472/**
473 * Discards bytes from buffer chain
474 *
475 * It discards n_bytes_to_drop starting at first buffer after chain_b
476 */
477always_inline void
478session_enqueue_discard_chain_bytes (vlib_main_t * vm, vlib_buffer_t * b,
479 vlib_buffer_t ** chain_b,
480 u32 n_bytes_to_drop)
481{
482 vlib_buffer_t *next = *chain_b;
483 u32 to_drop = n_bytes_to_drop;
484 ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
485 while (to_drop && (next->flags & VLIB_BUFFER_NEXT_PRESENT))
486 {
487 next = vlib_get_buffer (vm, next->next_buffer);
488 if (next->current_length > to_drop)
489 {
490 vlib_buffer_advance (next, to_drop);
491 to_drop = 0;
492 }
493 else
494 {
495 to_drop -= next->current_length;
496 next->current_length = 0;
497 }
498 }
499 *chain_b = next;
500
501 if (to_drop == 0)
502 b->total_length_not_including_first_buffer -= n_bytes_to_drop;
503}
504
505/**
506 * Enqueue buffer chain tail
507 */
Florin Corasf6d68ed2017-05-07 19:12:02 -0700508always_inline int
Florin Coras288eaab2019-02-03 15:26:14 -0800509session_enqueue_chain_tail (session_t * s, vlib_buffer_t * b,
Florin Corasf6d68ed2017-05-07 19:12:02 -0700510 u32 offset, u8 is_in_order)
511{
512 vlib_buffer_t *chain_b;
Florin Coras1f152cd2017-08-18 19:28:03 -0700513 u32 chain_bi, len, diff;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700514 vlib_main_t *vm = vlib_get_main ();
Florin Corasb2215d62017-08-01 16:56:58 -0700515 u8 *data;
Florin Coras1f152cd2017-08-18 19:28:03 -0700516 u32 written = 0;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700517 int rv = 0;
518
Florin Coras1f152cd2017-08-18 19:28:03 -0700519 if (is_in_order && offset)
520 {
521 diff = offset - b->current_length;
522 if (diff > b->total_length_not_including_first_buffer)
523 return 0;
524 chain_b = b;
525 session_enqueue_discard_chain_bytes (vm, b, &chain_b, diff);
526 chain_bi = vlib_get_buffer_index (vm, chain_b);
527 }
528 else
529 chain_bi = b->next_buffer;
530
Florin Corasf6d68ed2017-05-07 19:12:02 -0700531 do
532 {
533 chain_b = vlib_get_buffer (vm, chain_bi);
534 data = vlib_buffer_get_current (chain_b);
535 len = chain_b->current_length;
Florin Coras1f152cd2017-08-18 19:28:03 -0700536 if (!len)
537 continue;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700538 if (is_in_order)
539 {
Florin Coras87b15ce2019-04-28 21:16:30 -0700540 rv = svm_fifo_enqueue (s->rx_fifo, len, data);
Florin Coras1f152cd2017-08-18 19:28:03 -0700541 if (rv == len)
542 {
543 written += rv;
544 }
545 else if (rv < len)
Florin Corasf6d68ed2017-05-07 19:12:02 -0700546 {
547 return (rv > 0) ? (written + rv) : written;
548 }
Florin Coras1f152cd2017-08-18 19:28:03 -0700549 else if (rv > len)
550 {
551 written += rv;
552
553 /* written more than what was left in chain */
554 if (written > b->total_length_not_including_first_buffer)
555 return written;
556
557 /* drop the bytes that have already been delivered */
558 session_enqueue_discard_chain_bytes (vm, b, &chain_b, rv - len);
559 }
Florin Corasf6d68ed2017-05-07 19:12:02 -0700560 }
561 else
562 {
Florin Coras288eaab2019-02-03 15:26:14 -0800563 rv = svm_fifo_enqueue_with_offset (s->rx_fifo, offset, len, data);
Florin Corasf6d68ed2017-05-07 19:12:02 -0700564 if (rv)
Florin Coras1f152cd2017-08-18 19:28:03 -0700565 {
566 clib_warning ("failed to enqueue multi-buffer seg");
567 return -1;
568 }
Florin Corasf6d68ed2017-05-07 19:12:02 -0700569 offset += len;
570 }
571 }
572 while ((chain_bi = (chain_b->flags & VLIB_BUFFER_NEXT_PRESENT)
573 ? chain_b->next_buffer : 0));
574
575 if (is_in_order)
576 return written;
577
578 return 0;
579}
580
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000581void
582session_fifo_tuning (session_t * s, svm_fifo_t * f,
583 session_ft_action_t act, u32 len)
584{
585 if (s->flags & SESSION_F_CUSTOM_FIFO_TUNING)
586 {
587 app_worker_t *app_wrk = app_worker_get (s->app_wrk_index);
588 app_worker_session_fifo_tuning (app_wrk, s, f, act, len);
589 if (CLIB_ASSERT_ENABLE)
590 {
591 segment_manager_t *sm;
592 sm = segment_manager_get (f->segment_manager);
Florin Corasc547e912020-12-08 17:50:45 -0800593 ASSERT (f->shr->size >= 4096);
594 ASSERT (f->shr->size <= sm->max_fifo_size);
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000595 }
596 }
597}
598
Florin Coras0242d302022-12-22 15:03:44 -0800599void
600session_wrk_program_app_wrk_evts (session_worker_t *wrk, u32 app_wrk_index)
601{
602 u8 need_interrupt;
603
604 ASSERT ((wrk - session_main.wrk) == vlib_get_thread_index ());
605 need_interrupt = clib_bitmap_is_zero (wrk->app_wrks_pending_ntf);
606 wrk->app_wrks_pending_ntf =
607 clib_bitmap_set (wrk->app_wrks_pending_ntf, app_wrk_index, 1);
608
609 if (need_interrupt)
610 vlib_node_set_interrupt_pending (wrk->vm, session_input_node.index);
611}
612
613always_inline void
614session_program_io_event (app_worker_t *app_wrk, session_t *s,
615 session_evt_type_t et, u8 is_cl)
616{
617 if (is_cl)
618 {
619 /* Special events for connectionless sessions */
620 et += SESSION_IO_EVT_BUILTIN_RX - SESSION_IO_EVT_RX;
621
Florin Corasfa9f37c2023-10-10 10:21:01 -0700622 ASSERT (s->thread_index == 0 || et == SESSION_IO_EVT_TX_MAIN);
Florin Coras0242d302022-12-22 15:03:44 -0800623 session_event_t evt = {
624 .event_type = et,
625 .session_handle = session_handle (s),
626 };
627
628 app_worker_add_event_custom (app_wrk, vlib_get_thread_index (), &evt);
629 }
630 else
631 {
632 app_worker_add_event (app_wrk, s, et);
633 }
634}
635
636static inline int
637session_notify_subscribers (u32 app_index, session_t *s, svm_fifo_t *f,
638 session_evt_type_t evt_type)
639{
640 app_worker_t *app_wrk;
641 application_t *app;
642 u8 is_cl;
643 int i;
644
645 app = application_get (app_index);
646 if (!app)
647 return -1;
648
649 is_cl = s->thread_index != vlib_get_thread_index ();
650 for (i = 0; i < f->shr->n_subscribers; i++)
651 {
652 app_wrk = application_get_worker (app, f->shr->subscribers[i]);
653 if (!app_wrk)
654 continue;
655 session_program_io_event (app_wrk, s, evt_type, is_cl ? 1 : 0);
656 }
657
658 return 0;
659}
660
661always_inline int
662session_enqueue_notify_inline (session_t *s, u8 is_cl)
663{
664 app_worker_t *app_wrk;
665
666 app_wrk = app_worker_get_if_valid (s->app_wrk_index);
667 if (PREDICT_FALSE (!app_wrk))
668 return -1;
669
670 session_program_io_event (app_wrk, s, SESSION_IO_EVT_RX, is_cl);
671
672 if (PREDICT_FALSE (svm_fifo_n_subscribers (s->rx_fifo)))
673 return session_notify_subscribers (app_wrk->app_index, s, s->rx_fifo,
674 SESSION_IO_EVT_RX);
675
676 return 0;
677}
678
679int
680session_enqueue_notify (session_t *s)
681{
682 return session_enqueue_notify_inline (s, 0 /* is_cl */);
683}
684
685int
686session_enqueue_notify_cl (session_t *s)
687{
688 return session_enqueue_notify_inline (s, 1 /* is_cl */);
689}
690
691int
692session_dequeue_notify (session_t *s)
693{
694 app_worker_t *app_wrk;
695 u8 is_cl;
696
697 /* Unset as soon as event is requested */
698 svm_fifo_clear_deq_ntf (s->tx_fifo);
699
700 app_wrk = app_worker_get_if_valid (s->app_wrk_index);
701 if (PREDICT_FALSE (!app_wrk))
702 return -1;
703
704 is_cl = s->session_state == SESSION_STATE_LISTENING ||
705 s->session_state == SESSION_STATE_OPENED;
706 session_program_io_event (app_wrk, s, SESSION_IO_EVT_TX, is_cl ? 1 : 0);
707
708 if (PREDICT_FALSE (svm_fifo_n_subscribers (s->tx_fifo)))
709 return session_notify_subscribers (app_wrk->app_index, s, s->tx_fifo,
710 SESSION_IO_EVT_TX);
711
712 return 0;
713}
714
715/**
716 * Flushes queue of sessions that are to be notified of new data
717 * enqueued events.
718 *
719 * @param transport_proto transport protocol for which queue to be flushed
720 * @param thread_index Thread index for which the flush is to be performed.
721 * @return 0 on success or a positive number indicating the number of
722 * failures due to API queue being full.
723 */
724void
725session_main_flush_enqueue_events (transport_proto_t transport_proto,
726 u32 thread_index)
727{
728 session_worker_t *wrk = session_main_get_worker (thread_index);
729 session_handle_t *handles;
730 session_t *s;
Florin Coras44d9cbc2023-12-21 13:50:53 -0800731 u32 i, is_cl;
Florin Coras0242d302022-12-22 15:03:44 -0800732
733 handles = wrk->session_to_enqueue[transport_proto];
734
735 for (i = 0; i < vec_len (handles); i++)
736 {
737 s = session_get_from_handle (handles[i]);
738 session_fifo_tuning (s, s->rx_fifo, SESSION_FT_ACTION_ENQUEUED,
739 0 /* TODO/not needed */);
Florin Coras44d9cbc2023-12-21 13:50:53 -0800740 is_cl =
741 s->thread_index != thread_index || (s->flags & SESSION_F_IS_CLESS);
742 if (!is_cl)
743 session_enqueue_notify_inline (s, 0);
744 else
745 session_enqueue_notify_inline (s, 1);
Florin Coras0242d302022-12-22 15:03:44 -0800746 }
747
748 vec_reset_length (handles);
749 wrk->session_to_enqueue[transport_proto] = handles;
750}
751
Dave Barach68b0fb02017-02-28 15:15:56 -0500752/*
Florin Coras0242d302022-12-22 15:03:44 -0800753 * Enqueue data for delivery to app. If requested, it queues app notification
754 * event for later delivery.
Dave Barach68b0fb02017-02-28 15:15:56 -0500755 *
756 * @param tc Transport connection which is to be enqueued data
Florin Corasf6d68ed2017-05-07 19:12:02 -0700757 * @param b Buffer to be enqueued
758 * @param offset Offset at which to start enqueueing if out-of-order
Dave Barach68b0fb02017-02-28 15:15:56 -0500759 * @param queue_event Flag to indicate if peer is to be notified or if event
760 * is to be queued. The former is useful when more data is
761 * enqueued and only one event is to be generated.
Florin Corasf6d68ed2017-05-07 19:12:02 -0700762 * @param is_in_order Flag to indicate if data is in order
Dave Barach68b0fb02017-02-28 15:15:56 -0500763 * @return Number of bytes enqueued or a negative value if enqueueing failed.
764 */
765int
Florin Coras3cbc04b2017-10-02 00:18:51 -0700766session_enqueue_stream_connection (transport_connection_t * tc,
767 vlib_buffer_t * b, u32 offset,
768 u8 queue_event, u8 is_in_order)
Dave Barach68b0fb02017-02-28 15:15:56 -0500769{
Florin Coras288eaab2019-02-03 15:26:14 -0800770 session_t *s;
Florin Coras1f152cd2017-08-18 19:28:03 -0700771 int enqueued = 0, rv, in_order_off;
Dave Barach68b0fb02017-02-28 15:15:56 -0500772
Florin Corascea194d2017-10-02 00:18:51 -0700773 s = session_get (tc->s_index, tc->thread_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500774
Florin Corasf6d68ed2017-05-07 19:12:02 -0700775 if (is_in_order)
776 {
Florin Coras87b15ce2019-04-28 21:16:30 -0700777 enqueued = svm_fifo_enqueue (s->rx_fifo,
778 b->current_length,
779 vlib_buffer_get_current (b));
Florin Coras1f152cd2017-08-18 19:28:03 -0700780 if (PREDICT_FALSE ((b->flags & VLIB_BUFFER_NEXT_PRESENT)
781 && enqueued >= 0))
Florin Corasf6d68ed2017-05-07 19:12:02 -0700782 {
Florin Coras1f152cd2017-08-18 19:28:03 -0700783 in_order_off = enqueued > b->current_length ? enqueued : 0;
784 rv = session_enqueue_chain_tail (s, b, in_order_off, 1);
785 if (rv > 0)
786 enqueued += rv;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700787 }
788 }
789 else
790 {
Florin Coras288eaab2019-02-03 15:26:14 -0800791 rv = svm_fifo_enqueue_with_offset (s->rx_fifo, offset,
Florin Corasf6d68ed2017-05-07 19:12:02 -0700792 b->current_length,
793 vlib_buffer_get_current (b));
794 if (PREDICT_FALSE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) && !rv))
Florin Coras1f152cd2017-08-18 19:28:03 -0700795 session_enqueue_chain_tail (s, b, offset + b->current_length, 0);
796 /* if something was enqueued, report even this as success for ooo
797 * segment handling */
798 return rv;
Florin Corasf6d68ed2017-05-07 19:12:02 -0700799 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500800
801 if (queue_event)
802 {
Florin Coras0242d302022-12-22 15:03:44 -0800803 /* Queue RX event on this fifo. Eventually these will need to be
804 * flushed by calling @ref session_main_flush_enqueue_events () */
Florin Corasd5c604d2019-03-18 09:06:35 -0700805 if (!(s->flags & SESSION_F_RX_EVT))
Dave Barach68b0fb02017-02-28 15:15:56 -0500806 {
Florin Coras0242d302022-12-22 15:03:44 -0800807 session_worker_t *wrk = session_main_get_worker (s->thread_index);
808 ASSERT (s->thread_index == vlib_get_thread_index ());
Florin Corasd5c604d2019-03-18 09:06:35 -0700809 s->flags |= SESSION_F_RX_EVT;
Florin Coras0242d302022-12-22 15:03:44 -0800810 vec_add1 (wrk->session_to_enqueue[tc->proto], session_handle (s));
Dave Barach68b0fb02017-02-28 15:15:56 -0500811 }
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000812
813 session_fifo_tuning (s, s->rx_fifo, SESSION_FT_ACTION_ENQUEUED, 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500814 }
815
Chris Lukeb2bcad62017-09-18 08:51:22 -0400816 return enqueued;
Dave Barach68b0fb02017-02-28 15:15:56 -0500817}
818
Florin Coras0242d302022-12-22 15:03:44 -0800819always_inline int
820session_enqueue_dgram_connection_inline (session_t *s,
821 session_dgram_hdr_t *hdr,
822 vlib_buffer_t *b, u8 proto,
823 u8 queue_event, u32 is_cl)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700824{
Florin Corasc95cfa22020-11-24 08:41:17 -0800825 int rv;
Florin Coras3cbc04b2017-10-02 00:18:51 -0700826
Sirshak Das28aa5392019-02-05 01:33:33 -0600827 ASSERT (svm_fifo_max_enqueue_prod (s->rx_fifo)
Florin Coras7fb0fe12018-04-09 09:24:52 -0700828 >= b->current_length + sizeof (*hdr));
829
Florin Corasc95cfa22020-11-24 08:41:17 -0800830 if (PREDICT_TRUE (!(b->flags & VLIB_BUFFER_NEXT_PRESENT)))
Florin Coras3cbc04b2017-10-02 00:18:51 -0700831 {
Florin Corasc95cfa22020-11-24 08:41:17 -0800832 svm_fifo_seg_t segs[2] = {
833 { (u8 *) hdr, sizeof (*hdr) },
834 { vlib_buffer_get_current (b), b->current_length }
835 };
Florin Corasc95cfa22020-11-24 08:41:17 -0800836
837 rv = svm_fifo_enqueue_segments (s->rx_fifo, segs, 2,
838 0 /* allow_partial */ );
Florin Coras3cbc04b2017-10-02 00:18:51 -0700839 }
Florin Corasc95cfa22020-11-24 08:41:17 -0800840 else
841 {
842 vlib_main_t *vm = vlib_get_main ();
843 svm_fifo_seg_t *segs = 0, *seg;
844 vlib_buffer_t *it = b;
845 u32 n_segs = 1;
846
847 vec_add2 (segs, seg, 1);
848 seg->data = (u8 *) hdr;
849 seg->len = sizeof (*hdr);
850 while (it)
851 {
852 vec_add2 (segs, seg, 1);
853 seg->data = vlib_buffer_get_current (it);
854 seg->len = it->current_length;
855 n_segs++;
856 if (!(it->flags & VLIB_BUFFER_NEXT_PRESENT))
857 break;
858 it = vlib_get_buffer (vm, it->next_buffer);
859 }
860 rv = svm_fifo_enqueue_segments (s->rx_fifo, segs, n_segs,
861 0 /* allow partial */ );
862 vec_free (segs);
863 }
864
865 if (queue_event && rv > 0)
Florin Coras3cbc04b2017-10-02 00:18:51 -0700866 {
Florin Coras0242d302022-12-22 15:03:44 -0800867 /* Queue RX event on this fifo. Eventually these will need to be
868 * flushed by calling @ref session_main_flush_enqueue_events () */
Florin Corasd5c604d2019-03-18 09:06:35 -0700869 if (!(s->flags & SESSION_F_RX_EVT))
Florin Coras3cbc04b2017-10-02 00:18:51 -0700870 {
Florin Coras0242d302022-12-22 15:03:44 -0800871 u32 thread_index =
872 is_cl ? vlib_get_thread_index () : s->thread_index;
873 session_worker_t *wrk = session_main_get_worker (thread_index);
874 ASSERT (s->thread_index == vlib_get_thread_index () || is_cl);
Florin Corasd5c604d2019-03-18 09:06:35 -0700875 s->flags |= SESSION_F_RX_EVT;
Florin Coras0242d302022-12-22 15:03:44 -0800876 vec_add1 (wrk->session_to_enqueue[proto], session_handle (s));
Florin Coras3cbc04b2017-10-02 00:18:51 -0700877 }
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000878
879 session_fifo_tuning (s, s->rx_fifo, SESSION_FT_ACTION_ENQUEUED, 0);
Florin Coras3cbc04b2017-10-02 00:18:51 -0700880 }
Florin Corasc95cfa22020-11-24 08:41:17 -0800881 return rv > 0 ? rv : 0;
Florin Coras3cbc04b2017-10-02 00:18:51 -0700882}
883
Florin Coras93992a92017-05-24 18:03:56 -0700884int
Florin Coras0242d302022-12-22 15:03:44 -0800885session_enqueue_dgram_connection (session_t *s, session_dgram_hdr_t *hdr,
886 vlib_buffer_t *b, u8 proto, u8 queue_event)
887{
888 return session_enqueue_dgram_connection_inline (s, hdr, b, proto,
889 queue_event, 0 /* is_cl */);
890}
891
892int
Florin Coras7428eaa2023-12-11 16:04:57 -0800893session_enqueue_dgram_connection2 (session_t *s, session_dgram_hdr_t *hdr,
894 vlib_buffer_t *b, u8 proto, u8 queue_event)
895{
896 return session_enqueue_dgram_connection_inline (s, hdr, b, proto,
897 queue_event, 1 /* is_cl */);
898}
899
900int
Florin Coras0242d302022-12-22 15:03:44 -0800901session_enqueue_dgram_connection_cl (session_t *s, session_dgram_hdr_t *hdr,
902 vlib_buffer_t *b, u8 proto,
903 u8 queue_event)
904{
Florin Coras7428eaa2023-12-11 16:04:57 -0800905 session_t *awls;
906
907 awls = app_listener_select_wrk_cl_session (s, hdr);
908 return session_enqueue_dgram_connection_inline (awls, hdr, b, proto,
Florin Coras0242d302022-12-22 15:03:44 -0800909 queue_event, 1 /* is_cl */);
910}
911
912int
Florin Coras31c99552019-03-01 13:00:58 -0800913session_tx_fifo_peek_bytes (transport_connection_t * tc, u8 * buffer,
914 u32 offset, u32 max_bytes)
Dave Barach68b0fb02017-02-28 15:15:56 -0500915{
Florin Coras288eaab2019-02-03 15:26:14 -0800916 session_t *s = session_get (tc->s_index, tc->thread_index);
917 return svm_fifo_peek (s->tx_fifo, offset, max_bytes, buffer);
Dave Barach68b0fb02017-02-28 15:15:56 -0500918}
919
920u32
Florin Coras31c99552019-03-01 13:00:58 -0800921session_tx_fifo_dequeue_drop (transport_connection_t * tc, u32 max_bytes)
Dave Barach68b0fb02017-02-28 15:15:56 -0500922{
Florin Coras288eaab2019-02-03 15:26:14 -0800923 session_t *s = session_get (tc->s_index, tc->thread_index);
Vladimir Kropylevf867cf12019-06-17 21:38:00 +0300924 u32 rv;
925
926 rv = svm_fifo_dequeue_drop (s->tx_fifo, max_bytes);
Ryujiro Shibuyad8f48e22020-01-22 12:11:42 +0000927 session_fifo_tuning (s, s->tx_fifo, SESSION_FT_ACTION_DEQUEUED, rv);
Florin Coras0e573f52019-05-07 16:28:16 -0700928
Florin Coras2d379d82019-06-28 12:45:12 -0700929 if (svm_fifo_needs_deq_ntf (s->tx_fifo, max_bytes))
Florin Coras0e573f52019-05-07 16:28:16 -0700930 session_dequeue_notify (s);
931
Vladimir Kropylevf867cf12019-06-17 21:38:00 +0300932 return rv;
Dave Barach68b0fb02017-02-28 15:15:56 -0500933}
934
Florin Coras4fde4ae2020-04-13 16:48:04 +0000935int
936session_stream_connect_notify (transport_connection_t * tc,
937 session_error_t err)
Dave Barach68b0fb02017-02-28 15:15:56 -0500938{
Florin Coras371ca502018-02-21 12:07:41 -0800939 u32 opaque = 0, new_ti, new_si;
Florin Coras15531972018-08-12 23:50:53 -0700940 app_worker_t *app_wrk;
Florin Corasea727642021-05-07 19:39:43 -0700941 session_t *s = 0, *ho;
Dave Barach68b0fb02017-02-28 15:15:56 -0500942
Florin Coras3cbc04b2017-10-02 00:18:51 -0700943 /*
Florin Corasea727642021-05-07 19:39:43 -0700944 * Cleanup half-open table
Florin Coras3cbc04b2017-10-02 00:18:51 -0700945 */
Florin Corascea194d2017-10-02 00:18:51 -0700946 session_lookup_del_half_open (tc);
Florin Coras4eeeaaf2017-09-05 14:03:37 -0400947
Florin Corasea727642021-05-07 19:39:43 -0700948 ho = ho_session_get (tc->s_index);
Florin Coras4aeba372023-06-20 16:50:51 -0700949 session_set_state (ho, SESSION_STATE_TRANSPORT_CLOSED);
Florin Corasea727642021-05-07 19:39:43 -0700950 opaque = ho->opaque;
951 app_wrk = app_worker_get_if_valid (ho->app_wrk_index);
Florin Coras15531972018-08-12 23:50:53 -0700952 if (!app_wrk)
Florin Corasc87c91d2017-08-16 19:55:49 -0700953 return -1;
Florin Corasa27a46e2019-02-18 13:02:28 -0800954
Florin Coras00e01d32019-10-21 16:07:46 -0700955 if (err)
956 return app_worker_connect_notify (app_wrk, s, err, opaque);
Florin Corasa27a46e2019-02-18 13:02:28 -0800957
958 s = session_alloc_for_connection (tc);
Steven Luongd810a6e2022-10-25 13:09:11 -0700959 session_set_state (s, SESSION_STATE_CONNECTING);
Florin Corasa27a46e2019-02-18 13:02:28 -0800960 s->app_wrk_index = app_wrk->wrk_index;
Florin Coras2ceb8182023-08-31 17:33:47 -0700961 s->opaque = opaque;
Florin Corasa27a46e2019-02-18 13:02:28 -0800962 new_si = s->session_index;
963 new_ti = s->thread_index;
964
Florin Coras00e01d32019-10-21 16:07:46 -0700965 if ((err = app_worker_init_connected (app_wrk, s)))
Dave Barach68b0fb02017-02-28 15:15:56 -0500966 {
Florin Corasa27a46e2019-02-18 13:02:28 -0800967 session_free (s);
Florin Coras00e01d32019-10-21 16:07:46 -0700968 app_worker_connect_notify (app_wrk, 0, err, opaque);
Florin Corasa27a46e2019-02-18 13:02:28 -0800969 return -1;
Dave Barach68b0fb02017-02-28 15:15:56 -0500970 }
971
Nathan Skrzypczaka26349d2019-06-26 13:53:08 +0200972 s = session_get (new_si, new_ti);
Steven Luongd810a6e2022-10-25 13:09:11 -0700973 session_set_state (s, SESSION_STATE_READY);
Nathan Skrzypczaka26349d2019-06-26 13:53:08 +0200974 session_lookup_add_connection (tc, session_handle (s));
975
Florin Coras00e01d32019-10-21 16:07:46 -0700976 if (app_worker_connect_notify (app_wrk, s, SESSION_E_NONE, opaque))
Florin Coras6534b7a2017-07-18 05:38:03 -0400977 {
Florin Corasc7fd24e2020-07-24 10:09:07 -0700978 session_lookup_del_connection (tc);
979 /* Avoid notifying app about rejected session cleanup */
Florin Corasa27a46e2019-02-18 13:02:28 -0800980 s = session_get (new_si, new_ti);
Florin Corasc7fd24e2020-07-24 10:09:07 -0700981 segment_manager_dealloc_fifos (s->rx_fifo, s->tx_fifo);
982 session_free (s);
Florin Corasa27a46e2019-02-18 13:02:28 -0800983 return -1;
Florin Coras6534b7a2017-07-18 05:38:03 -0400984 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500985
Florin Corasa27a46e2019-02-18 13:02:28 -0800986 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500987}
988
Florin Coras6d7552c2020-04-09 01:49:45 +0000989static void
Florin Coras0242d302022-12-22 15:03:44 -0800990session_switch_pool_closed_rpc (void *arg)
Florin Coras6d7552c2020-04-09 01:49:45 +0000991{
Florin Coras0242d302022-12-22 15:03:44 -0800992 session_handle_t sh;
Florin Coras6d7552c2020-04-09 01:49:45 +0000993 session_t *s;
994
Florin Coras0242d302022-12-22 15:03:44 -0800995 sh = pointer_to_uword (arg);
996 s = session_get_from_handle_if_valid (sh);
Florin Coras6d7552c2020-04-09 01:49:45 +0000997 if (!s)
998 return;
999
Florin Coras0242d302022-12-22 15:03:44 -08001000 transport_cleanup (session_get_transport_proto (s), s->connection_index,
1001 s->thread_index);
1002 session_cleanup (s);
Florin Coras6d7552c2020-04-09 01:49:45 +00001003}
1004
Florin Coras3cbc04b2017-10-02 00:18:51 -07001005typedef struct _session_switch_pool_args
1006{
1007 u32 session_index;
1008 u32 thread_index;
1009 u32 new_thread_index;
1010 u32 new_session_index;
1011} session_switch_pool_args_t;
1012
Florin Coras49568af2019-07-31 16:46:24 -07001013/**
1014 * Notify old thread of the session pool switch
1015 */
Florin Coras3cbc04b2017-10-02 00:18:51 -07001016static void
1017session_switch_pool (void *cb_args)
1018{
1019 session_switch_pool_args_t *args = (session_switch_pool_args_t *) cb_args;
Florin Coras0242d302022-12-22 15:03:44 -08001020 session_handle_t sh, new_sh;
Florin Coras6d7552c2020-04-09 01:49:45 +00001021 segment_manager_t *sm;
Florin Coras49568af2019-07-31 16:46:24 -07001022 app_worker_t *app_wrk;
Florin Coras288eaab2019-02-03 15:26:14 -08001023 session_t *s;
Florin Coras49568af2019-07-31 16:46:24 -07001024
Florin Coras3cbc04b2017-10-02 00:18:51 -07001025 ASSERT (args->thread_index == vlib_get_thread_index ());
1026 s = session_get (args->session_index, args->thread_index);
Florin Coras6d7552c2020-04-09 01:49:45 +00001027
Florin Coras49568af2019-07-31 16:46:24 -07001028 app_wrk = app_worker_get_if_valid (s->app_wrk_index);
Florin Coras0242d302022-12-22 15:03:44 -08001029 if (!app_wrk)
1030 goto app_closed;
Aloys Augustinb3392332019-08-06 16:09:01 +02001031
Florin Coras0242d302022-12-22 15:03:44 -08001032 /* Cleanup fifo segment slice state for fifos */
1033 sm = app_worker_get_connect_segment_manager (app_wrk);
1034 segment_manager_detach_fifo (sm, &s->rx_fifo);
1035 segment_manager_detach_fifo (sm, &s->tx_fifo);
Florin Coras49568af2019-07-31 16:46:24 -07001036
Florin Coras0242d302022-12-22 15:03:44 -08001037 /* Check if session closed during migration */
1038 if (s->session_state >= SESSION_STATE_TRANSPORT_CLOSING)
1039 goto app_closed;
1040
1041 new_sh =
1042 session_make_handle (args->new_session_index, args->new_thread_index);
1043 app_worker_migrate_notify (app_wrk, s, new_sh);
1044
1045 clib_mem_free (cb_args);
1046 return;
1047
1048app_closed:
1049 /* Session closed during migration. Clean everything up */
1050 sh = session_handle (s);
Florin Coras6d7552c2020-04-09 01:49:45 +00001051 session_send_rpc_evt_to_thread (args->new_thread_index,
Florin Coras0242d302022-12-22 15:03:44 -08001052 session_switch_pool_closed_rpc,
1053 uword_to_pointer (sh, void *));
Florin Coras3cbc04b2017-10-02 00:18:51 -07001054 clib_mem_free (cb_args);
1055}
1056
1057/**
1058 * Move dgram session to the right thread
1059 */
1060int
1061session_dgram_connect_notify (transport_connection_t * tc,
Florin Coras288eaab2019-02-03 15:26:14 -08001062 u32 old_thread_index, session_t ** new_session)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001063{
Florin Coras288eaab2019-02-03 15:26:14 -08001064 session_t *new_s;
Florin Coras3cbc04b2017-10-02 00:18:51 -07001065 session_switch_pool_args_t *rpc_args;
Florin Coras0bc78d82021-01-09 14:34:01 -08001066 segment_manager_t *sm;
1067 app_worker_t *app_wrk;
Florin Coras3cbc04b2017-10-02 00:18:51 -07001068
1069 /*
1070 * Clone half-open session to the right thread.
1071 */
1072 new_s = session_clone_safe (tc->s_index, old_thread_index);
1073 new_s->connection_index = tc->c_index;
Steven Luongd810a6e2022-10-25 13:09:11 -07001074 session_set_state (new_s, SESSION_STATE_READY);
Nathan Skrzypczakcaa7acf2019-10-02 10:02:05 +02001075 new_s->flags |= SESSION_F_IS_MIGRATING;
Florin Coras6d7552c2020-04-09 01:49:45 +00001076
Florin Coras0bc78d82021-01-09 14:34:01 -08001077 if (!(tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
1078 session_lookup_add_connection (tc, session_handle (new_s));
1079
1080 app_wrk = app_worker_get_if_valid (new_s->app_wrk_index);
1081 if (app_wrk)
1082 {
1083 /* New set of fifos attached to the same shared memory */
1084 sm = app_worker_get_connect_segment_manager (app_wrk);
1085 segment_manager_attach_fifo (sm, &new_s->rx_fifo, new_s);
1086 segment_manager_attach_fifo (sm, &new_s->tx_fifo, new_s);
1087 }
Florin Coras3cbc04b2017-10-02 00:18:51 -07001088
1089 /*
1090 * Ask thread owning the old session to clean it up and make us the tx
1091 * fifo owner
1092 */
1093 rpc_args = clib_mem_alloc (sizeof (*rpc_args));
1094 rpc_args->new_session_index = new_s->session_index;
1095 rpc_args->new_thread_index = new_s->thread_index;
1096 rpc_args->session_index = tc->s_index;
1097 rpc_args->thread_index = old_thread_index;
1098 session_send_rpc_evt_to_thread (rpc_args->thread_index, session_switch_pool,
1099 rpc_args);
1100
1101 tc->s_index = new_s->session_index;
1102 new_s->connection_index = tc->c_index;
1103 *new_session = new_s;
1104 return 0;
1105}
1106
Dave Barach68b0fb02017-02-28 15:15:56 -05001107/**
1108 * Notification from transport that connection is being closed.
1109 *
1110 * A disconnect is sent to application but state is not removed. Once
1111 * disconnect is acknowledged by application, session disconnect is called.
1112 * Ultimately this leads to close being called on transport (passive close).
1113 */
1114void
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001115session_transport_closing_notify (transport_connection_t * tc)
Dave Barach68b0fb02017-02-28 15:15:56 -05001116{
Florin Coras15531972018-08-12 23:50:53 -07001117 app_worker_t *app_wrk;
Florin Coras288eaab2019-02-03 15:26:14 -08001118 session_t *s;
Dave Barach68b0fb02017-02-28 15:15:56 -05001119
Florin Corascea194d2017-10-02 00:18:51 -07001120 s = session_get (tc->s_index, tc->thread_index);
Florin Coras400ded32018-10-03 01:00:57 -07001121 if (s->session_state >= SESSION_STATE_TRANSPORT_CLOSING)
1122 return;
Florin Corasdfd27bc2021-11-27 10:45:55 -08001123
1124 /* Wait for reply from app before sending notification as the
1125 * accept might be rejected */
1126 if (s->session_state == SESSION_STATE_ACCEPTING)
1127 {
Steven Luongd810a6e2022-10-25 13:09:11 -07001128 session_set_state (s, SESSION_STATE_TRANSPORT_CLOSING);
Florin Corasdfd27bc2021-11-27 10:45:55 -08001129 return;
1130 }
1131
Steven Luongd810a6e2022-10-25 13:09:11 -07001132 session_set_state (s, SESSION_STATE_TRANSPORT_CLOSING);
Florin Corasbf7ce2c2019-03-06 14:44:42 -08001133 app_wrk = app_worker_get (s->app_wrk_index);
1134 app_worker_close_notify (app_wrk, s);
Dave Barach68b0fb02017-02-28 15:15:56 -05001135}
1136
1137/**
Dave Barach68b0fb02017-02-28 15:15:56 -05001138 * Notification from transport that connection is being deleted
1139 *
Florin Coras4eeeaaf2017-09-05 14:03:37 -04001140 * This removes the session if it is still valid. It should be called only on
1141 * previously fully established sessions. For instance failed connects should
1142 * call stream_session_connect_notify and indicate that the connect has
1143 * failed.
Dave Barach68b0fb02017-02-28 15:15:56 -05001144 */
1145void
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001146session_transport_delete_notify (transport_connection_t * tc)
Dave Barach68b0fb02017-02-28 15:15:56 -05001147{
Florin Coras288eaab2019-02-03 15:26:14 -08001148 session_t *s;
Dave Barach68b0fb02017-02-28 15:15:56 -05001149
Florin Corase04c2992017-03-01 08:17:34 -08001150 /* App might've been removed already */
Florin Coras568ebc72018-09-18 16:12:50 -07001151 if (!(s = session_get_if_valid (tc->s_index, tc->thread_index)))
Florin Corasc87c91d2017-08-16 19:55:49 -07001152 return;
Florin Coras568ebc72018-09-18 16:12:50 -07001153
Florin Coras568ebc72018-09-18 16:12:50 -07001154 switch (s->session_state)
1155 {
Florin Coras222e1f412019-02-16 20:47:32 -08001156 case SESSION_STATE_CREATED:
1157 /* Session was created but accept notification was not yet sent to the
1158 * app. Cleanup everything. */
1159 session_lookup_del_session (s);
Zeyu Zhangcbbc4a22019-10-12 14:21:59 +08001160 segment_manager_dealloc_fifos (s->rx_fifo, s->tx_fifo);
1161 session_free (s);
Florin Coras222e1f412019-02-16 20:47:32 -08001162 break;
Florin Corasb0f662f2018-12-27 14:51:46 -08001163 case SESSION_STATE_ACCEPTING:
Florin Coras568ebc72018-09-18 16:12:50 -07001164 case SESSION_STATE_TRANSPORT_CLOSING:
Florin Coras692b9492019-07-12 15:01:53 -07001165 case SESSION_STATE_CLOSING:
Florin Coras5f066322019-07-22 19:03:03 -07001166 case SESSION_STATE_TRANSPORT_CLOSED:
Florin Coras568ebc72018-09-18 16:12:50 -07001167 /* If transport finishes or times out before we get a reply
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001168 * from the app, mark transport as closed and wait for reply
1169 * before removing the session. Cleanup session table in advance
Florin Corasa9d5bea2018-12-17 08:24:19 -08001170 * because transport will soon be closed and closed sessions
1171 * are assumed to have been removed from the lookup table */
1172 session_lookup_del_session (s);
Steven Luongd810a6e2022-10-25 13:09:11 -07001173 session_set_state (s, SESSION_STATE_TRANSPORT_DELETED);
Florin Coras70f26d52019-07-08 11:47:18 -07001174 session_cleanup_notify (s, SESSION_CLEANUP_TRANSPORT);
1175 svm_fifo_dequeue_drop_all (s->tx_fifo);
Florin Coras568ebc72018-09-18 16:12:50 -07001176 break;
Florin Coras692b9492019-07-12 15:01:53 -07001177 case SESSION_STATE_APP_CLOSED:
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001178 /* Cleanup lookup table as transport needs to still be valid.
1179 * Program transport close to ensure that all session events
1180 * have been cleaned up. Once transport close is called, the
1181 * session is just removed because both transport and app have
1182 * confirmed the close*/
Florin Coras568ebc72018-09-18 16:12:50 -07001183 session_lookup_del_session (s);
Steven Luongd810a6e2022-10-25 13:09:11 -07001184 session_set_state (s, SESSION_STATE_TRANSPORT_DELETED);
Florin Coras70f26d52019-07-08 11:47:18 -07001185 session_cleanup_notify (s, SESSION_CLEANUP_TRANSPORT);
1186 svm_fifo_dequeue_drop_all (s->tx_fifo);
Florin Corasdfb3b872019-08-16 17:48:44 -07001187 session_program_transport_ctrl_evt (s, SESSION_CTRL_EVT_CLOSE);
Florin Coras568ebc72018-09-18 16:12:50 -07001188 break;
Florin Coras5f066322019-07-22 19:03:03 -07001189 case SESSION_STATE_TRANSPORT_DELETED:
Florin Corasb0f662f2018-12-27 14:51:46 -08001190 break;
Florin Coras568ebc72018-09-18 16:12:50 -07001191 case SESSION_STATE_CLOSED:
Florin Coras70f26d52019-07-08 11:47:18 -07001192 session_cleanup_notify (s, SESSION_CLEANUP_TRANSPORT);
Florin Coras0242d302022-12-22 15:03:44 -08001193 session_set_state (s, SESSION_STATE_TRANSPORT_DELETED);
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001194 session_delete (s);
Florin Coras568ebc72018-09-18 16:12:50 -07001195 break;
Florin Corasc01d5782018-10-17 14:53:11 -07001196 default:
Florin Corasb0f662f2018-12-27 14:51:46 -08001197 clib_warning ("session state %u", s->session_state);
Florin Coras70f26d52019-07-08 11:47:18 -07001198 session_cleanup_notify (s, SESSION_CLEANUP_TRANSPORT);
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001199 session_delete (s);
Florin Corasc01d5782018-10-17 14:53:11 -07001200 break;
Florin Coras568ebc72018-09-18 16:12:50 -07001201 }
Dave Barach68b0fb02017-02-28 15:15:56 -05001202}
1203
1204/**
Florin Coras692b9492019-07-12 15:01:53 -07001205 * Notification from transport that it is closed
Florin Coras54ddf432018-12-21 13:54:09 -08001206 *
Florin Coras692b9492019-07-12 15:01:53 -07001207 * Should be called by transport, prior to calling delete notify, once it
1208 * knows that no more data will be exchanged. This could serve as an
1209 * early acknowledgment of an active close especially if transport delete
1210 * can be delayed a long time, e.g., tcp time-wait.
Florin Coras54ddf432018-12-21 13:54:09 -08001211 */
1212void
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001213session_transport_closed_notify (transport_connection_t * tc)
Florin Coras54ddf432018-12-21 13:54:09 -08001214{
Florin Coras692b9492019-07-12 15:01:53 -07001215 app_worker_t *app_wrk;
Florin Coras288eaab2019-02-03 15:26:14 -08001216 session_t *s;
Florin Coras54ddf432018-12-21 13:54:09 -08001217
1218 if (!(s = session_get_if_valid (tc->s_index, tc->thread_index)))
1219 return;
Florin Corasb0f662f2018-12-27 14:51:46 -08001220
Florin Coras5afc13d2023-12-12 14:01:43 -08001221 if (s->session_state >= SESSION_STATE_TRANSPORT_CLOSED)
1222 return;
1223
Florin Coras06a2eec2019-05-23 22:28:16 -07001224 /* Transport thinks that app requested close but it actually didn't.
liuyacan534468e2021-05-09 03:50:40 +00001225 * Can happen for tcp:
1226 * 1)if fin and rst are received in close succession.
1227 * 2)if app shutdown the connection. */
Florin Coras06a2eec2019-05-23 22:28:16 -07001228 if (s->session_state == SESSION_STATE_READY)
1229 {
1230 session_transport_closing_notify (tc);
1231 svm_fifo_dequeue_drop_all (s->tx_fifo);
Steven Luongd810a6e2022-10-25 13:09:11 -07001232 session_set_state (s, SESSION_STATE_TRANSPORT_CLOSED);
Florin Coras06a2eec2019-05-23 22:28:16 -07001233 }
Florin Corasb0f662f2018-12-27 14:51:46 -08001234 /* If app close has not been received or has not yet resulted in
1235 * a transport close, only mark the session transport as closed */
Florin Coras06a2eec2019-05-23 22:28:16 -07001236 else if (s->session_state <= SESSION_STATE_CLOSING)
Steven Luongd810a6e2022-10-25 13:09:11 -07001237 session_set_state (s, SESSION_STATE_TRANSPORT_CLOSED);
Florin Coras5f066322019-07-22 19:03:03 -07001238 /* If app also closed, switch to closed */
1239 else if (s->session_state == SESSION_STATE_APP_CLOSED)
Steven Luongd810a6e2022-10-25 13:09:11 -07001240 session_set_state (s, SESSION_STATE_CLOSED);
Florin Coras692b9492019-07-12 15:01:53 -07001241
1242 app_wrk = app_worker_get_if_valid (s->app_wrk_index);
1243 if (app_wrk)
1244 app_worker_transport_closed_notify (app_wrk, s);
Florin Coras54ddf432018-12-21 13:54:09 -08001245}
1246
1247/**
Dave Barach68b0fb02017-02-28 15:15:56 -05001248 * Notify application that connection has been reset.
1249 */
1250void
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001251session_transport_reset_notify (transport_connection_t * tc)
Dave Barach68b0fb02017-02-28 15:15:56 -05001252{
Florin Coras15531972018-08-12 23:50:53 -07001253 app_worker_t *app_wrk;
Florin Coras69b68ef2019-04-02 11:38:51 -07001254 session_t *s;
1255
Florin Corascea194d2017-10-02 00:18:51 -07001256 s = session_get (tc->s_index, tc->thread_index);
Florin Coras288eaab2019-02-03 15:26:14 -08001257 svm_fifo_dequeue_drop_all (s->tx_fifo);
Florin Coras3c7d4f92018-12-14 11:28:43 -08001258 if (s->session_state >= SESSION_STATE_TRANSPORT_CLOSING)
1259 return;
Florin Corasdfd27bc2021-11-27 10:45:55 -08001260 if (s->session_state == SESSION_STATE_ACCEPTING)
1261 {
Steven Luongd810a6e2022-10-25 13:09:11 -07001262 session_set_state (s, SESSION_STATE_TRANSPORT_CLOSING);
Florin Corasdfd27bc2021-11-27 10:45:55 -08001263 return;
1264 }
Steven Luongd810a6e2022-10-25 13:09:11 -07001265 session_set_state (s, SESSION_STATE_TRANSPORT_CLOSING);
Florin Coras15531972018-08-12 23:50:53 -07001266 app_wrk = app_worker_get (s->app_wrk_index);
Florin Coras69b68ef2019-04-02 11:38:51 -07001267 app_worker_reset_notify (app_wrk, s);
Dave Barach68b0fb02017-02-28 15:15:56 -05001268}
1269
Florin Corasa27a46e2019-02-18 13:02:28 -08001270int
1271session_stream_accept_notify (transport_connection_t * tc)
1272{
1273 app_worker_t *app_wrk;
1274 session_t *s;
1275
1276 s = session_get (tc->s_index, tc->thread_index);
1277 app_wrk = app_worker_get_if_valid (s->app_wrk_index);
1278 if (!app_wrk)
1279 return -1;
Florin Coras600d7a82021-04-29 11:55:23 -07001280 if (s->session_state != SESSION_STATE_CREATED)
1281 return 0;
Steven Luongd810a6e2022-10-25 13:09:11 -07001282 session_set_state (s, SESSION_STATE_ACCEPTING);
Florin Coras4dc10a42020-02-11 05:31:49 +00001283 if (app_worker_accept_notify (app_wrk, s))
1284 {
1285 /* On transport delete, no notifications should be sent. Unless, the
1286 * accept is retried and successful. */
Steven Luongd810a6e2022-10-25 13:09:11 -07001287 session_set_state (s, SESSION_STATE_CREATED);
Florin Coras4dc10a42020-02-11 05:31:49 +00001288 return -1;
1289 }
1290 return 0;
Florin Corasa27a46e2019-02-18 13:02:28 -08001291}
1292
Dave Barach68b0fb02017-02-28 15:15:56 -05001293/**
1294 * Accept a stream session. Optionally ping the server by callback.
1295 */
1296int
Florin Corasc9940fc2019-02-05 20:55:11 -08001297session_stream_accept (transport_connection_t * tc, u32 listener_index,
Nathan Skrzypczak2f0f96b2019-06-13 10:14:28 +02001298 u32 thread_index, u8 notify)
Dave Barach68b0fb02017-02-28 15:15:56 -05001299{
Florin Corasa27a46e2019-02-18 13:02:28 -08001300 session_t *s;
Dave Barach68b0fb02017-02-28 15:15:56 -05001301 int rv;
1302
Florin Corasa27a46e2019-02-18 13:02:28 -08001303 s = session_alloc_for_connection (tc);
Nathan Skrzypczak2f0f96b2019-06-13 10:14:28 +02001304 s->listener_handle = ((u64) thread_index << 32) | (u64) listener_index;
Steven Luongd810a6e2022-10-25 13:09:11 -07001305 session_set_state (s, SESSION_STATE_CREATED);
Dave Barach68b0fb02017-02-28 15:15:56 -05001306
Florin Corasa27a46e2019-02-18 13:02:28 -08001307 if ((rv = app_worker_init_accepted (s)))
Florin Coras12813d52020-04-09 20:59:20 +00001308 {
1309 session_free (s);
1310 return rv;
1311 }
Florin Corasa27a46e2019-02-18 13:02:28 -08001312
1313 session_lookup_add_connection (tc, session_handle (s));
1314
Dave Barach68b0fb02017-02-28 15:15:56 -05001315 /* Shoulder-tap the server */
1316 if (notify)
1317 {
Florin Corasa27a46e2019-02-18 13:02:28 -08001318 app_worker_t *app_wrk = app_worker_get (s->app_wrk_index);
Florin Coras12813d52020-04-09 20:59:20 +00001319 if ((rv = app_worker_accept_notify (app_wrk, s)))
1320 {
1321 session_lookup_del_session (s);
1322 segment_manager_dealloc_fifos (s->rx_fifo, s->tx_fifo);
1323 session_free (s);
1324 return rv;
1325 }
Dave Barach68b0fb02017-02-28 15:15:56 -05001326 }
1327
1328 return 0;
1329}
1330
Florin Coras371ca502018-02-21 12:07:41 -08001331int
Florin Corase759bb52020-04-08 01:55:39 +00001332session_dgram_accept (transport_connection_t * tc, u32 listener_index,
1333 u32 thread_index)
1334{
1335 app_worker_t *app_wrk;
1336 session_t *s;
1337 int rv;
1338
1339 s = session_alloc_for_connection (tc);
1340 s->listener_handle = ((u64) thread_index << 32) | (u64) listener_index;
1341
1342 if ((rv = app_worker_init_accepted (s)))
1343 {
1344 session_free (s);
1345 return rv;
1346 }
1347
Florin Coras473556d2020-11-23 15:59:36 -08001348 session_lookup_add_connection (tc, session_handle (s));
Steven Luongd810a6e2022-10-25 13:09:11 -07001349 session_set_state (s, SESSION_STATE_ACCEPTING);
Florin Coras473556d2020-11-23 15:59:36 -08001350
Florin Corase759bb52020-04-08 01:55:39 +00001351 app_wrk = app_worker_get (s->app_wrk_index);
1352 if ((rv = app_worker_accept_notify (app_wrk, s)))
1353 {
Florin Coras473556d2020-11-23 15:59:36 -08001354 session_lookup_del_session (s);
Florin Coras12813d52020-04-09 20:59:20 +00001355 segment_manager_dealloc_fifos (s->rx_fifo, s->tx_fifo);
1356 session_free (s);
Florin Corase759bb52020-04-08 01:55:39 +00001357 return rv;
1358 }
1359
Florin Corase759bb52020-04-08 01:55:39 +00001360 return 0;
1361}
1362
1363int
Florin Coras89a9f612021-05-11 11:55:07 -07001364session_open_cl (session_endpoint_cfg_t *rmt, session_handle_t *rsh)
Florin Coras371ca502018-02-21 12:07:41 -08001365{
1366 transport_connection_t *tc;
Florin Coras5665ced2018-10-25 18:03:45 -07001367 transport_endpoint_cfg_t *tep;
Florin Coras15531972018-08-12 23:50:53 -07001368 app_worker_t *app_wrk;
Aloys Augustin20ab31e2019-03-25 11:29:17 +01001369 session_handle_t sh;
Florin Coras288eaab2019-02-03 15:26:14 -08001370 session_t *s;
Florin Coras371ca502018-02-21 12:07:41 -08001371 int rv;
1372
Florin Coras5665ced2018-10-25 18:03:45 -07001373 tep = session_endpoint_to_transport_cfg (rmt);
Florin Coras1ee78302019-02-05 15:51:15 -08001374 rv = transport_connect (rmt->transport_proto, tep);
Florin Coras371ca502018-02-21 12:07:41 -08001375 if (rv < 0)
1376 {
1377 SESSION_DBG ("Transport failed to open connection.");
Florin Coras57660d92020-04-04 22:45:34 +00001378 return rv;
Florin Coras371ca502018-02-21 12:07:41 -08001379 }
1380
Florin Coras1ee78302019-02-05 15:51:15 -08001381 tc = transport_get_half_open (rmt->transport_proto, (u32) rv);
Florin Coras371ca502018-02-21 12:07:41 -08001382
Florin Corasa27a46e2019-02-18 13:02:28 -08001383 /* For dgram type of service, allocate session and fifos now */
Florin Coras89a9f612021-05-11 11:55:07 -07001384 app_wrk = app_worker_get (rmt->app_wrk_index);
Florin Corasa27a46e2019-02-18 13:02:28 -08001385 s = session_alloc_for_connection (tc);
Florin Coras15531972018-08-12 23:50:53 -07001386 s->app_wrk_index = app_wrk->wrk_index;
Florin Coras2ceb8182023-08-31 17:33:47 -07001387 s->opaque = rmt->opaque;
Steven Luongd810a6e2022-10-25 13:09:11 -07001388 session_set_state (s, SESSION_STATE_OPENED);
Florin Coras44d9cbc2023-12-21 13:50:53 -08001389 if (transport_connection_is_cless (tc))
1390 s->flags |= SESSION_F_IS_CLESS;
Florin Corasa27a46e2019-02-18 13:02:28 -08001391 if (app_worker_init_connected (app_wrk, s))
1392 {
1393 session_free (s);
1394 return -1;
1395 }
Florin Coras371ca502018-02-21 12:07:41 -08001396
Aloys Augustin20ab31e2019-03-25 11:29:17 +01001397 sh = session_handle (s);
Florin Coras89a9f612021-05-11 11:55:07 -07001398 *rsh = sh;
1399
Aloys Augustin20ab31e2019-03-25 11:29:17 +01001400 session_lookup_add_connection (tc, sh);
Florin Coras89a9f612021-05-11 11:55:07 -07001401 return app_worker_connect_notify (app_wrk, s, SESSION_E_NONE, rmt->opaque);
Florin Coras371ca502018-02-21 12:07:41 -08001402}
1403
1404int
Florin Coras89a9f612021-05-11 11:55:07 -07001405session_open_vc (session_endpoint_cfg_t *rmt, session_handle_t *rsh)
Florin Coras371ca502018-02-21 12:07:41 -08001406{
1407 transport_connection_t *tc;
Florin Coras5665ced2018-10-25 18:03:45 -07001408 transport_endpoint_cfg_t *tep;
Florin Corasea727642021-05-07 19:39:43 -07001409 app_worker_t *app_wrk;
Florin Coras89a9f612021-05-11 11:55:07 -07001410 session_t *ho;
Florin Coras371ca502018-02-21 12:07:41 -08001411 int rv;
1412
Florin Coras5665ced2018-10-25 18:03:45 -07001413 tep = session_endpoint_to_transport_cfg (rmt);
Florin Coras1ee78302019-02-05 15:51:15 -08001414 rv = transport_connect (rmt->transport_proto, tep);
Florin Coras371ca502018-02-21 12:07:41 -08001415 if (rv < 0)
1416 {
1417 SESSION_DBG ("Transport failed to open connection.");
Florin Coras57660d92020-04-04 22:45:34 +00001418 return rv;
Florin Coras371ca502018-02-21 12:07:41 -08001419 }
1420
Florin Coras1ee78302019-02-05 15:51:15 -08001421 tc = transport_get_half_open (rmt->transport_proto, (u32) rv);
Florin Coras371ca502018-02-21 12:07:41 -08001422
Florin Coras89a9f612021-05-11 11:55:07 -07001423 app_wrk = app_worker_get (rmt->app_wrk_index);
Florin Coras371ca502018-02-21 12:07:41 -08001424
Florin Corasea727642021-05-07 19:39:43 -07001425 /* If transport offers a vc service, only allocate established
1426 * session once the connection has been established.
1427 * In the meantime allocate half-open session for tracking purposes
1428 * associate half-open connection to it and add session to app-worker
1429 * half-open table. These are needed to allocate the established
1430 * session on transport notification, and to cleanup the half-open
1431 * session if the app detaches before connection establishment.
Florin Coras371ca502018-02-21 12:07:41 -08001432 */
Florin Coras89a9f612021-05-11 11:55:07 -07001433 ho = session_alloc_for_half_open (tc);
1434 ho->app_wrk_index = app_wrk->wrk_index;
1435 ho->ho_index = app_worker_add_half_open (app_wrk, session_handle (ho));
1436 ho->opaque = rmt->opaque;
1437 *rsh = session_handle (ho);
Florin Corasd50ff7f2020-04-16 04:30:22 +00001438
Florin Coras2c876f92021-05-10 21:12:27 -07001439 if (!(tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
1440 session_lookup_add_half_open (tc, tc->c_index);
Florin Coras4fde4ae2020-04-13 16:48:04 +00001441
Florin Coras371ca502018-02-21 12:07:41 -08001442 return 0;
1443}
1444
1445int
Florin Coras89a9f612021-05-11 11:55:07 -07001446session_open_app (session_endpoint_cfg_t *rmt, session_handle_t *rsh)
Florin Coras371ca502018-02-21 12:07:41 -08001447{
Florin Coras89a9f612021-05-11 11:55:07 -07001448 transport_endpoint_cfg_t *tep_cfg = session_endpoint_to_transport_cfg (rmt);
Florin Coras5665ced2018-10-25 18:03:45 -07001449
Florin Coras89a9f612021-05-11 11:55:07 -07001450 /* Not supported for now */
1451 *rsh = SESSION_INVALID_HANDLE;
Florin Coras1ee78302019-02-05 15:51:15 -08001452 return transport_connect (rmt->transport_proto, tep_cfg);
Florin Coras371ca502018-02-21 12:07:41 -08001453}
1454
Florin Coras89a9f612021-05-11 11:55:07 -07001455typedef int (*session_open_service_fn) (session_endpoint_cfg_t *,
1456 session_handle_t *);
Florin Coras371ca502018-02-21 12:07:41 -08001457
Florin Coras371ca502018-02-21 12:07:41 -08001458static session_open_service_fn session_open_srv_fns[TRANSPORT_N_SERVICES] = {
1459 session_open_vc,
1460 session_open_cl,
1461 session_open_app,
1462};
Florin Coras371ca502018-02-21 12:07:41 -08001463
Florin Coras6cf30ad2017-04-04 23:08:23 -07001464/**
1465 * Ask transport to open connection to remote transport endpoint.
1466 *
1467 * Stores handle for matching request with reply since the call can be
1468 * asynchronous. For instance, for TCP the 3-way handshake must complete
1469 * before reply comes. Session is only created once connection is established.
1470 *
1471 * @param app_index Index of the application requesting the connect
1472 * @param st Session type requested.
1473 * @param tep Remote transport endpoint
Florin Coras3cbc04b2017-10-02 00:18:51 -07001474 * @param opaque Opaque data (typically, api_context) the application expects
1475 * on open completion.
Florin Coras6cf30ad2017-04-04 23:08:23 -07001476 */
Florin Corase04c2992017-03-01 08:17:34 -08001477int
Florin Coras89a9f612021-05-11 11:55:07 -07001478session_open (session_endpoint_cfg_t *rmt, session_handle_t *rsh)
Dave Barach68b0fb02017-02-28 15:15:56 -05001479{
Florin Coras1ee78302019-02-05 15:51:15 -08001480 transport_service_type_t tst;
1481 tst = transport_protocol_service_type (rmt->transport_proto);
Florin Coras89a9f612021-05-11 11:55:07 -07001482 return session_open_srv_fns[tst](rmt, rsh);
Florin Coras6cf30ad2017-04-04 23:08:23 -07001483}
1484
Florin Coras7fb0fe12018-04-09 09:24:52 -07001485/**
Florin Corasab2f6db2018-08-31 14:31:41 -07001486 * Ask transport to listen on session endpoint.
Florin Coras7fb0fe12018-04-09 09:24:52 -07001487 *
1488 * @param s Session for which listen will be called. Note that unlike
1489 * established sessions, listen sessions are not associated to a
1490 * thread.
Florin Corasab2f6db2018-08-31 14:31:41 -07001491 * @param sep Local endpoint to be listened on.
Florin Coras7fb0fe12018-04-09 09:24:52 -07001492 */
Florin Coras371ca502018-02-21 12:07:41 -08001493int
Florin Coras288eaab2019-02-03 15:26:14 -08001494session_listen (session_t * ls, session_endpoint_cfg_t * sep)
Florin Coras371ca502018-02-21 12:07:41 -08001495{
Florin Coras0bce71e2022-02-10 11:57:06 -08001496 transport_endpoint_cfg_t *tep;
Florin Corasa8c3b862020-04-07 22:31:06 +00001497 int tc_index;
1498 u32 s_index;
Florin Corasab2f6db2018-08-31 14:31:41 -07001499
1500 /* Transport bind/listen */
Florin Coras0bce71e2022-02-10 11:57:06 -08001501 tep = session_endpoint_to_transport_cfg (sep);
Florin Coras74cac882018-09-07 09:13:15 -07001502 s_index = ls->session_index;
Florin Corasd4295e62019-02-22 13:11:38 -08001503 tc_index = transport_start_listen (session_get_transport_proto (ls),
1504 s_index, tep);
Florin Corasab2f6db2018-08-31 14:31:41 -07001505
Florin Corasa8c3b862020-04-07 22:31:06 +00001506 if (tc_index < 0)
1507 return tc_index;
Florin Corasab2f6db2018-08-31 14:31:41 -07001508
Florin Corasd4295e62019-02-22 13:11:38 -08001509 /* Attach transport to session. Lookup tables are populated by the app
1510 * worker because local tables (for ct sessions) are not backed by a fib */
Florin Coras74cac882018-09-07 09:13:15 -07001511 ls = listen_session_get (s_index);
Florin Corasab2f6db2018-08-31 14:31:41 -07001512 ls->connection_index = tc_index;
Mohammed Hawari472d0da2022-10-17 17:55:35 +02001513 ls->opaque = sep->opaque;
Florin Coras44d9cbc2023-12-21 13:50:53 -08001514 if (transport_connection_is_cless (session_get_transport (ls)))
1515 ls->flags |= SESSION_F_IS_CLESS;
Florin Corasab2f6db2018-08-31 14:31:41 -07001516
Florin Corasab2f6db2018-08-31 14:31:41 -07001517 return 0;
Florin Coras371ca502018-02-21 12:07:41 -08001518}
1519
Florin Coras6cf30ad2017-04-04 23:08:23 -07001520/**
1521 * Ask transport to stop listening on local transport endpoint.
1522 *
1523 * @param s Session to stop listening on. It must be in state LISTENING.
1524 */
1525int
Florin Coras288eaab2019-02-03 15:26:14 -08001526session_stop_listen (session_t * s)
Florin Coras6cf30ad2017-04-04 23:08:23 -07001527{
Florin Coras561af9b2017-12-09 10:19:43 -08001528 transport_proto_t tp = session_get_transport_proto (s);
Florin Coras6cf30ad2017-04-04 23:08:23 -07001529 transport_connection_t *tc;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001530
Florin Coras1ee78302019-02-05 15:51:15 -08001531 if (s->session_state != SESSION_STATE_LISTENING)
Florin Corasa8c3b862020-04-07 22:31:06 +00001532 return SESSION_E_NOLISTEN;
Florin Coras1ee78302019-02-05 15:51:15 -08001533
1534 tc = transport_get_listener (tp, s->connection_index);
Florin Corasa8c3b862020-04-07 22:31:06 +00001535
1536 /* If no transport, assume everything was cleaned up already */
Florin Coras6cf30ad2017-04-04 23:08:23 -07001537 if (!tc)
Florin Corasa8c3b862020-04-07 22:31:06 +00001538 return SESSION_E_NONE;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001539
Nathan Skrzypczak2eed1a12019-07-04 14:26:21 +02001540 if (!(tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
Florin Corasd96859f2023-06-24 14:43:42 -07001541 session_lookup_del_connection (tc);
Florin Corasa8c3b862020-04-07 22:31:06 +00001542
Florin Coras1ee78302019-02-05 15:51:15 -08001543 transport_stop_listen (tp, s->connection_index);
Florin Corase04c2992017-03-01 08:17:34 -08001544 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001545}
1546
1547/**
liuyacan534468e2021-05-09 03:50:40 +00001548 * Initialize session half-closing procedure.
1549 *
1550 * Note that half-closing will not change the state of the session.
1551 */
1552void
1553session_half_close (session_t *s)
1554{
1555 if (!s)
1556 return;
1557
1558 session_program_transport_ctrl_evt (s, SESSION_CTRL_EVT_HALF_CLOSE);
1559}
1560
1561/**
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001562 * Initialize session closing procedure.
Florin Corasa5464812017-04-19 13:00:05 -07001563 *
Florin Coras2f8d8fa2018-01-26 06:36:04 -08001564 * Request is always sent to session node to ensure that all outstanding
1565 * requests are served before transport is notified.
Dave Barach68b0fb02017-02-28 15:15:56 -05001566 */
1567void
Florin Coras288eaab2019-02-03 15:26:14 -08001568session_close (session_t * s)
Dave Barach68b0fb02017-02-28 15:15:56 -05001569{
Florin Coras7c06b572023-02-20 15:14:04 -08001570 if (!s || (s->flags & SESSION_F_APP_CLOSED))
Florin Coras2f8d8fa2018-01-26 06:36:04 -08001571 return;
Florin Coras25579b42018-06-06 17:55:02 -07001572
Florin Coras7c06b572023-02-20 15:14:04 -08001573 /* Transports can close and delete their state independent of app closes
1574 * and transport initiated state transitions can hide app closes. Instead
1575 * of extending the state machine to support separate tracking of app and
1576 * transport initiated closes, use a flag. */
1577 s->flags |= SESSION_F_APP_CLOSED;
1578
Florin Coras25579b42018-06-06 17:55:02 -07001579 if (s->session_state >= SESSION_STATE_CLOSING)
1580 {
Florin Coras5a2ec8f2018-12-27 11:53:11 -08001581 /* Session will only be removed once both app and transport
1582 * acknowledge the close */
Florin Coras5f066322019-07-22 19:03:03 -07001583 if (s->session_state == SESSION_STATE_TRANSPORT_CLOSED
1584 || s->session_state == SESSION_STATE_TRANSPORT_DELETED)
Florin Corasdfb3b872019-08-16 17:48:44 -07001585 session_program_transport_ctrl_evt (s, SESSION_CTRL_EVT_CLOSE);
Florin Coras25579b42018-06-06 17:55:02 -07001586 return;
1587 }
1588
Dongya Zhang7a87c712022-11-03 15:22:34 +08001589 /* App closed so stop propagating dequeue notifications.
1590 * App might disconnect session before connected, in this case,
1591 * tx_fifo may not be setup yet, so clear only it's inited. */
1592 if (s->tx_fifo)
1593 svm_fifo_clear_deq_ntf (s->tx_fifo);
Steven Luongd810a6e2022-10-25 13:09:11 -07001594 session_set_state (s, SESSION_STATE_CLOSING);
Florin Corasdfb3b872019-08-16 17:48:44 -07001595 session_program_transport_ctrl_evt (s, SESSION_CTRL_EVT_CLOSE);
1596}
1597
1598/**
1599 * Force a close without waiting for data to be flushed
1600 */
1601void
1602session_reset (session_t * s)
1603{
1604 if (s->session_state >= SESSION_STATE_CLOSING)
1605 return;
Dongya Zhang7a87c712022-11-03 15:22:34 +08001606 /* Drop all outstanding tx data
1607 * App might disconnect session before connected, in this case,
1608 * tx_fifo may not be setup yet, so clear only it's inited. */
1609 if (s->tx_fifo)
1610 svm_fifo_dequeue_drop_all (s->tx_fifo);
Steven Luongd810a6e2022-10-25 13:09:11 -07001611 session_set_state (s, SESSION_STATE_CLOSING);
Florin Corasdfb3b872019-08-16 17:48:44 -07001612 session_program_transport_ctrl_evt (s, SESSION_CTRL_EVT_RESET);
Florin Coras2f8d8fa2018-01-26 06:36:04 -08001613}
1614
Florin Corasaa786312024-04-09 13:27:53 -07001615void
1616session_detach_app (session_t *s)
1617{
1618 if (s->session_state < SESSION_STATE_TRANSPORT_CLOSING)
Florin Coras9a5caec2024-04-16 16:53:14 -07001619 {
1620 session_close (s);
1621 }
1622 else if (s->session_state < SESSION_STATE_TRANSPORT_DELETED)
1623 {
1624 transport_connection_t *tc;
1625
1626 /* Transport is closing but it's not yet deleted. Confirm close and
1627 * subsequently detach transport from session and enqueue a session
1628 * cleanup notification. Transport closed and cleanup notifications are
1629 * going to be dropped by session layer apis */
1630 transport_close (session_get_transport_proto (s), s->connection_index,
1631 s->thread_index);
1632 tc = session_get_transport (s);
1633 tc->s_index = SESSION_INVALID_INDEX;
1634 session_set_state (s, SESSION_STATE_TRANSPORT_DELETED);
1635 session_cleanup_notify (s, SESSION_CLEANUP_SESSION);
1636 }
1637 else
1638 {
1639 session_cleanup_notify (s, SESSION_CLEANUP_SESSION);
1640 }
Florin Corasaa786312024-04-09 13:27:53 -07001641
1642 s->flags |= SESSION_F_APP_CLOSED;
1643 s->app_wrk_index = APP_INVALID_INDEX;
1644}
1645
Florin Coras2f8d8fa2018-01-26 06:36:04 -08001646/**
liuyacan534468e2021-05-09 03:50:40 +00001647 * Notify transport the session can be half-disconnected.
1648 *
1649 * Must be called from the session's thread.
1650 */
1651void
1652session_transport_half_close (session_t *s)
1653{
1654 /* Only READY session can be half-closed */
1655 if (s->session_state != SESSION_STATE_READY)
1656 {
1657 return;
1658 }
1659
1660 transport_half_close (session_get_transport_proto (s), s->connection_index,
1661 s->thread_index);
1662}
1663
1664/**
Florin Coras2f8d8fa2018-01-26 06:36:04 -08001665 * Notify transport the session can be disconnected. This should eventually
1666 * result in a delete notification that allows us to cleanup session state.
1667 * Called for both active/passive disconnects.
1668 *
1669 * Must be called from the session's thread.
1670 */
1671void
Florin Coras288eaab2019-02-03 15:26:14 -08001672session_transport_close (session_t * s)
Florin Coras2f8d8fa2018-01-26 06:36:04 -08001673{
Florin Coras692b9492019-07-12 15:01:53 -07001674 if (s->session_state >= SESSION_STATE_APP_CLOSED)
Florin Coras568ebc72018-09-18 16:12:50 -07001675 {
Florin Coras5f066322019-07-22 19:03:03 -07001676 if (s->session_state == SESSION_STATE_TRANSPORT_CLOSED)
Steven Luongd810a6e2022-10-25 13:09:11 -07001677 session_set_state (s, SESSION_STATE_CLOSED);
Florin Coras70802942024-06-11 12:17:04 -07001678 /* If transport is already deleted, just free the session. Half-opens
1679 * expected to be already cleaning up at this point */
1680 else if (s->session_state >= SESSION_STATE_TRANSPORT_DELETED &&
1681 !(s->flags & SESSION_F_HALF_OPEN))
Florin Coras0242d302022-12-22 15:03:44 -08001682 session_program_cleanup (s);
Florin Coras568ebc72018-09-18 16:12:50 -07001683 return;
1684 }
Florin Coras78cc4b02018-12-20 18:24:49 -08001685
Florin Coras692b9492019-07-12 15:01:53 -07001686 /* If the tx queue wasn't drained, the transport can continue to try
1687 * sending the outstanding data (in closed state it cannot). It MUST however
1688 * at one point, either after sending everything or after a timeout, call
1689 * delete notify. This will finally lead to the complete cleanup of the
1690 * session.
Florin Coras78cc4b02018-12-20 18:24:49 -08001691 */
Steven Luongd810a6e2022-10-25 13:09:11 -07001692 session_set_state (s, SESSION_STATE_APP_CLOSED);
Florin Coras78cc4b02018-12-20 18:24:49 -08001693
Florin Coras1ee78302019-02-05 15:51:15 -08001694 transport_close (session_get_transport_proto (s), s->connection_index,
1695 s->thread_index);
Dave Barach68b0fb02017-02-28 15:15:56 -05001696}
1697
1698/**
Florin Corasdfb3b872019-08-16 17:48:44 -07001699 * Force transport close
1700 */
1701void
1702session_transport_reset (session_t * s)
1703{
1704 if (s->session_state >= SESSION_STATE_APP_CLOSED)
1705 {
1706 if (s->session_state == SESSION_STATE_TRANSPORT_CLOSED)
Steven Luongd810a6e2022-10-25 13:09:11 -07001707 session_set_state (s, SESSION_STATE_CLOSED);
Florin Coras6c378452024-06-12 10:14:40 -07001708 else if (s->session_state >= SESSION_STATE_TRANSPORT_DELETED &&
1709 !(s->flags & SESSION_F_HALF_OPEN))
Florin Coras0242d302022-12-22 15:03:44 -08001710 session_program_cleanup (s);
Florin Corasdfb3b872019-08-16 17:48:44 -07001711 return;
1712 }
1713
Steven Luongd810a6e2022-10-25 13:09:11 -07001714 session_set_state (s, SESSION_STATE_APP_CLOSED);
Florin Corasdfb3b872019-08-16 17:48:44 -07001715 transport_reset (session_get_transport_proto (s), s->connection_index,
1716 s->thread_index);
1717}
1718
1719/**
Dave Barach68b0fb02017-02-28 15:15:56 -05001720 * Cleanup transport and session state.
Florin Corasd79b41e2017-03-04 05:37:52 -08001721 *
Florin Coras25579b42018-06-06 17:55:02 -07001722 * Notify transport of the cleanup and free the session. This should
1723 * be called only if transport reported some error and is already
1724 * closed.
Dave Barach68b0fb02017-02-28 15:15:56 -05001725 */
1726void
Florin Coras288eaab2019-02-03 15:26:14 -08001727session_transport_cleanup (session_t * s)
Dave Barach68b0fb02017-02-28 15:15:56 -05001728{
Florin Coras25579b42018-06-06 17:55:02 -07001729 /* Delete from main lookup table before we axe the the transport */
1730 session_lookup_del_session (s);
Florin Coras5afea122019-10-28 08:46:37 -07001731 if (s->session_state != SESSION_STATE_TRANSPORT_DELETED)
1732 transport_cleanup (session_get_transport_proto (s), s->connection_index,
1733 s->thread_index);
Florin Coras25579b42018-06-06 17:55:02 -07001734 /* Since we called cleanup, no delete notification will come. So, make
1735 * sure the session is properly freed. */
Florin Corasd3955fb2019-11-29 09:31:47 -08001736 segment_manager_dealloc_fifos (s->rx_fifo, s->tx_fifo);
1737 session_free (s);
Dave Barach68b0fb02017-02-28 15:15:56 -05001738}
1739
Florin Corasa5464812017-04-19 13:00:05 -07001740/**
Florin Coras8afe1b82021-11-17 23:38:54 -08001741 * Allocate worker mqs in share-able segment
Florin Corasb384b542018-01-15 01:08:33 -08001742 *
Florin Coras8afe1b82021-11-17 23:38:54 -08001743 * That can only be a newly created memfd segment, that must be mapped
1744 * by all apps/stack users unless private rx mqs are enabled.
Florin Corasa5464812017-04-19 13:00:05 -07001745 */
1746void
Florin Coras8afe1b82021-11-17 23:38:54 -08001747session_vpp_wrk_mqs_alloc (session_main_t *smm)
Florin Corasa5464812017-04-19 13:00:05 -07001748{
Florin Coras8afe1b82021-11-17 23:38:54 -08001749 u32 mq_q_length = 2048, evt_size = sizeof (session_event_t);
1750 fifo_segment_t *mqs_seg = &smm->wrk_mqs_segment;
1751 svm_msg_q_cfg_t _cfg, *cfg = &_cfg;
1752 uword mqs_seg_size;
Florin Corasb384b542018-01-15 01:08:33 -08001753 int i;
Florin Corasa5464812017-04-19 13:00:05 -07001754
Florin Coras8afe1b82021-11-17 23:38:54 -08001755 mq_q_length = clib_max (mq_q_length, smm->configured_wrk_mq_length);
Florin Corasb384b542018-01-15 01:08:33 -08001756
Florin Coras8afe1b82021-11-17 23:38:54 -08001757 svm_msg_q_ring_cfg_t rc[SESSION_MQ_N_RINGS] = {
1758 { mq_q_length, evt_size, 0 }, { mq_q_length >> 1, 256, 0 }
1759 };
1760 cfg->consumer_pid = 0;
1761 cfg->n_rings = 2;
1762 cfg->q_nitems = mq_q_length;
1763 cfg->ring_cfgs = rc;
Florin Coras6c10ab22020-11-08 16:50:39 -08001764
Florin Coras8afe1b82021-11-17 23:38:54 -08001765 /*
1766 * Compute mqs segment size based on rings config and leave space
1767 * for passing extended configuration messages, i.e., data allocated
1768 * outside of the rings. If provided with a config value, accept it
1769 * if larger than minimum size.
1770 */
1771 mqs_seg_size = svm_msg_q_size_to_alloc (cfg) * vec_len (smm->wrk);
Florin Corascf5c7742022-06-28 14:34:45 -07001772 mqs_seg_size = mqs_seg_size + (1 << 20);
Florin Coras8afe1b82021-11-17 23:38:54 -08001773 mqs_seg_size = clib_max (mqs_seg_size, smm->wrk_mqs_segment_size);
1774
1775 mqs_seg->ssvm.ssvm_size = mqs_seg_size;
1776 mqs_seg->ssvm.my_pid = getpid ();
1777 mqs_seg->ssvm.name = format (0, "%s%c", "session: wrk-mqs-segment", 0);
Florin Coras6c10ab22020-11-08 16:50:39 -08001778
Florin Coras8afe1b82021-11-17 23:38:54 -08001779 if (ssvm_server_init (&mqs_seg->ssvm, SSVM_SEGMENT_MEMFD))
Florin Corasa5464812017-04-19 13:00:05 -07001780 {
Florin Coras6c10ab22020-11-08 16:50:39 -08001781 clib_warning ("failed to initialize queue segment");
1782 return;
Florin Corasa5464812017-04-19 13:00:05 -07001783 }
Florin Corasb384b542018-01-15 01:08:33 -08001784
Florin Coras8afe1b82021-11-17 23:38:54 -08001785 fifo_segment_init (mqs_seg);
Florin Corasb384b542018-01-15 01:08:33 -08001786
Florin Corasb4624182020-12-11 13:58:12 -08001787 /* Special fifo segment that's filled only with mqs */
Florin Coras8afe1b82021-11-17 23:38:54 -08001788 mqs_seg->h->n_mqs = vec_len (smm->wrk);
Florin Corasb4624182020-12-11 13:58:12 -08001789
Florin Coras5a7ca7b2018-10-30 12:01:48 -07001790 for (i = 0; i < vec_len (smm->wrk); i++)
Florin Coras8afe1b82021-11-17 23:38:54 -08001791 smm->wrk[i].vpp_event_queue = fifo_segment_msg_q_alloc (mqs_seg, i, cfg);
Florin Corasb384b542018-01-15 01:08:33 -08001792}
1793
Florin Coras04943b42020-12-25 11:45:40 -08001794fifo_segment_t *
Florin Coras8afe1b82021-11-17 23:38:54 -08001795session_main_get_wrk_mqs_segment (void)
Florin Corasb384b542018-01-15 01:08:33 -08001796{
Florin Coras8afe1b82021-11-17 23:38:54 -08001797 return &session_main.wrk_mqs_segment;
Florin Corasa5464812017-04-19 13:00:05 -07001798}
1799
Florin Coras31c99552019-03-01 13:00:58 -08001800u64
1801session_segment_handle (session_t * s)
1802{
1803 svm_fifo_t *f;
1804
Aloys Augustincdb71702019-04-08 17:54:39 +02001805 if (!s->rx_fifo)
Florin Coras31c99552019-03-01 13:00:58 -08001806 return SESSION_INVALID_HANDLE;
1807
1808 f = s->rx_fifo;
1809 return segment_manager_make_segment_handle (f->segment_manager,
1810 f->segment_index);
1811}
1812
qinyangaf9b7152023-06-27 01:11:53 -07001813void
1814session_get_original_dst (transport_endpoint_t *i2o_src,
1815 transport_endpoint_t *i2o_dst,
1816 transport_proto_t transport_proto, u32 *original_dst,
1817 u16 *original_dst_port)
1818{
1819 session_main_t *smm = vnet_get_session_main ();
1820 ip_protocol_t proto =
1821 (transport_proto == TRANSPORT_PROTO_TCP ? IPPROTO_TCP : IPPROTO_UDP);
1822 if (!smm->original_dst_lookup || !i2o_dst->is_ip4)
1823 return;
1824 smm->original_dst_lookup (&i2o_src->ip.ip4, i2o_src->port, &i2o_dst->ip.ip4,
1825 i2o_dst->port, proto, original_dst,
1826 original_dst_port);
1827}
1828
Florin Coras371ca502018-02-21 12:07:41 -08001829static session_fifo_rx_fn *session_tx_fns[TRANSPORT_TX_N_FNS] = {
1830 session_tx_fifo_peek_and_snd,
1831 session_tx_fifo_dequeue_and_snd,
Florin Coras7fb0fe12018-04-09 09:24:52 -07001832 session_tx_fifo_dequeue_internal,
1833 session_tx_fifo_dequeue_and_snd
Florin Coras371ca502018-02-21 12:07:41 -08001834};
Florin Coras371ca502018-02-21 12:07:41 -08001835
Florin Coras561af9b2017-12-09 10:19:43 -08001836void
1837session_register_transport (transport_proto_t transport_proto,
1838 const transport_proto_vft_t * vft, u8 is_ip4,
1839 u32 output_node)
Dave Barach2c25a622017-06-26 11:35:07 -04001840{
Florin Coras31c99552019-03-01 13:00:58 -08001841 session_main_t *smm = &session_main;
Florin Coras561af9b2017-12-09 10:19:43 -08001842 session_type_t session_type;
1843 u32 next_index = ~0;
Dave Barach2c25a622017-06-26 11:35:07 -04001844
Florin Coras561af9b2017-12-09 10:19:43 -08001845 session_type = session_type_from_proto_and_ip (transport_proto, is_ip4);
1846
1847 vec_validate (smm->session_type_to_next, session_type);
Florin Coras561af9b2017-12-09 10:19:43 -08001848 vec_validate (smm->session_tx_fns, session_type);
1849
Florin Coras371ca502018-02-21 12:07:41 -08001850 if (output_node != ~0)
Florin Coraseb839cc2021-04-14 11:23:55 -07001851 next_index = vlib_node_add_next (vlib_get_main (),
1852 session_queue_node.index, output_node);
Florin Coras561af9b2017-12-09 10:19:43 -08001853
1854 smm->session_type_to_next[session_type] = next_index;
Nathan Skrzypczake971bc92019-06-19 13:42:37 +02001855 smm->session_tx_fns[session_type] =
1856 session_tx_fns[vft->transport_options.tx_type];
Dave Barach2c25a622017-06-26 11:35:07 -04001857}
1858
Florin Coras5384cca2022-01-20 18:10:26 -08001859void
1860session_register_update_time_fn (session_update_time_fn fn, u8 is_add)
1861{
1862 session_main_t *smm = &session_main;
1863 session_update_time_fn *fi;
1864 u32 fi_pos = ~0;
1865 u8 found = 0;
1866
1867 vec_foreach (fi, smm->update_time_fns)
1868 {
1869 if (*fi == fn)
1870 {
1871 fi_pos = fi - smm->update_time_fns;
1872 found = 1;
1873 break;
1874 }
1875 }
1876
1877 if (is_add)
1878 {
1879 if (found)
1880 {
1881 clib_warning ("update time fn %p already registered", fn);
1882 return;
1883 }
1884 vec_add1 (smm->update_time_fns, fn);
1885 }
1886 else
1887 {
Steven Luongb8a22732024-06-28 12:27:50 -07001888 if (found)
1889 vec_del1 (smm->update_time_fns, fi_pos);
Florin Coras5384cca2022-01-20 18:10:26 -08001890 }
1891}
1892
Florin Coras07063b82020-03-13 04:44:51 +00001893transport_proto_t
1894session_add_transport_proto (void)
1895{
1896 session_main_t *smm = &session_main;
1897 session_worker_t *wrk;
1898 u32 thread;
1899
1900 smm->last_transport_proto_type += 1;
1901
1902 for (thread = 0; thread < vec_len (smm->wrk); thread++)
1903 {
1904 wrk = session_main_get_worker (thread);
1905 vec_validate (wrk->session_to_enqueue, smm->last_transport_proto_type);
1906 }
1907
1908 return smm->last_transport_proto_type;
1909}
1910
Florin Coras3cbc04b2017-10-02 00:18:51 -07001911transport_connection_t *
Florin Coras288eaab2019-02-03 15:26:14 -08001912session_get_transport (session_t * s)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001913{
Florin Corasade70e42017-10-14 18:56:41 -07001914 if (s->session_state != SESSION_STATE_LISTENING)
Florin Coras4edc37e2019-02-04 23:01:34 -08001915 return transport_get_connection (session_get_transport_proto (s),
1916 s->connection_index, s->thread_index);
1917 else
1918 return transport_get_listener (session_get_transport_proto (s),
1919 s->connection_index);
Florin Coras3cbc04b2017-10-02 00:18:51 -07001920}
1921
Aloys Augustincdb71702019-04-08 17:54:39 +02001922void
Florin Coras09d18c22019-04-24 11:10:02 -07001923session_get_endpoint (session_t * s, transport_endpoint_t * tep, u8 is_lcl)
Aloys Augustincdb71702019-04-08 17:54:39 +02001924{
1925 if (s->session_state != SESSION_STATE_LISTENING)
1926 return transport_get_endpoint (session_get_transport_proto (s),
Florin Coras09d18c22019-04-24 11:10:02 -07001927 s->connection_index, s->thread_index, tep,
1928 is_lcl);
Aloys Augustincdb71702019-04-08 17:54:39 +02001929 else
1930 return transport_get_listener_endpoint (session_get_transport_proto (s),
Florin Coras09d18c22019-04-24 11:10:02 -07001931 s->connection_index, tep, is_lcl);
Aloys Augustincdb71702019-04-08 17:54:39 +02001932}
1933
Florin Coras04ae8272021-04-12 19:55:37 -07001934int
1935session_transport_attribute (session_t *s, u8 is_get,
1936 transport_endpt_attr_t *attr)
1937{
1938 if (s->session_state < SESSION_STATE_READY)
1939 return -1;
1940
1941 return transport_connection_attribute (session_get_transport_proto (s),
1942 s->connection_index, s->thread_index,
1943 is_get, attr);
1944}
1945
Florin Coras3cbc04b2017-10-02 00:18:51 -07001946transport_connection_t *
Florin Coras288eaab2019-02-03 15:26:14 -08001947listen_session_get_transport (session_t * s)
Florin Coras3cbc04b2017-10-02 00:18:51 -07001948{
Florin Coras4edc37e2019-02-04 23:01:34 -08001949 return transport_get_listener (session_get_transport_proto (s),
1950 s->connection_index);
Florin Coras3cbc04b2017-10-02 00:18:51 -07001951}
1952
Florin Corasfd542f12018-05-16 19:28:24 -07001953void
Florin Coras5484daa2020-03-27 23:55:06 +00001954session_queue_run_on_main_thread (vlib_main_t * vm)
Florin Corasfd542f12018-05-16 19:28:24 -07001955{
1956 ASSERT (vlib_get_thread_index () == 0);
Florin Coras1d2e38b2021-03-17 21:52:49 -07001957 vlib_node_set_interrupt_pending (vm, session_queue_node.index);
Florin Corasfd542f12018-05-16 19:28:24 -07001958}
1959
Florin Corasd82f4712022-04-25 16:15:02 -07001960static void
1961session_stats_collector_fn (vlib_stats_collector_data_t *d)
1962{
1963 u32 i, n_workers, n_wrk_sessions, n_sessions = 0;
1964 session_main_t *smm = &session_main;
1965 session_worker_t *wrk;
1966 counter_t **counters;
1967 counter_t *cb;
1968
1969 n_workers = vec_len (smm->wrk);
1970 vlib_stats_validate (d->entry_index, 0, n_workers - 1);
1971 counters = d->entry->data;
1972 cb = counters[0];
1973
1974 for (i = 0; i < vec_len (smm->wrk); i++)
1975 {
1976 wrk = session_main_get_worker (i);
1977 n_wrk_sessions = pool_elts (wrk->sessions);
1978 cb[i] = n_wrk_sessions;
1979 n_sessions += n_wrk_sessions;
1980 }
1981
1982 vlib_stats_set_gauge (d->private_data, n_sessions);
1983}
1984
1985static void
1986session_stats_collector_init (void)
1987{
Florin Coras975e0df2022-04-26 19:32:11 -07001988 vlib_stats_collector_reg_t reg = {};
Florin Corasd82f4712022-04-25 16:15:02 -07001989
1990 reg.entry_index =
1991 vlib_stats_add_counter_vector ("/sys/session/sessions_per_worker");
1992 reg.private_data = vlib_stats_add_gauge ("/sys/session/sessions_total");
1993 reg.collect_fn = session_stats_collector_fn;
1994 vlib_stats_register_collector_fn (&reg);
1995 vlib_stats_validate (reg.entry_index, 0, vlib_get_n_threads ());
1996}
1997
Dave Barach68b0fb02017-02-28 15:15:56 -05001998static clib_error_t *
Florin Corase04c2992017-03-01 08:17:34 -08001999session_manager_main_enable (vlib_main_t * vm)
Dave Barach68b0fb02017-02-28 15:15:56 -05002000{
Florin Coras31c99552019-03-01 13:00:58 -08002001 session_main_t *smm = &session_main;
Florin Corase04c2992017-03-01 08:17:34 -08002002 vlib_thread_main_t *vtm = vlib_get_thread_main ();
Florin Coras371ca502018-02-21 12:07:41 -08002003 u32 num_threads, preallocated_sessions_per_worker;
Florin Coras31c99552019-03-01 13:00:58 -08002004 session_worker_t *wrk;
Florin Corasd5c604d2019-03-18 09:06:35 -07002005 int i;
Dave Barach68b0fb02017-02-28 15:15:56 -05002006
Florin Corase10da622020-10-25 14:00:29 -07002007 /* We only initialize once and do not de-initialized on disable */
2008 if (smm->is_initialized)
2009 goto done;
2010
Dave Barach68b0fb02017-02-28 15:15:56 -05002011 num_threads = 1 /* main thread */ + vtm->n_threads;
2012
2013 if (num_threads < 1)
2014 return clib_error_return (0, "n_thread_stacks not set");
2015
Florin Coras5f56d732018-10-30 10:21:59 -07002016 /* Allocate cache line aligned worker contexts */
Florin Coras5a7ca7b2018-10-30 12:01:48 -07002017 vec_validate_aligned (smm->wrk, num_threads - 1, CLIB_CACHE_LINE_BYTES);
Florin Coras53d8d4f2022-03-09 13:55:38 -08002018 clib_spinlock_init (&session_main.pool_realloc_lock);
Florin Coras3cbc04b2017-10-02 00:18:51 -07002019
Dave Barachacd2a6a2017-05-16 17:41:34 -04002020 for (i = 0; i < num_threads; i++)
2021 {
Florin Coras5a7ca7b2018-10-30 12:01:48 -07002022 wrk = &smm->wrk[i];
Florin Corasb0ffbee2019-07-21 19:23:46 -07002023 wrk->ctrl_head = clib_llist_make_head (wrk->event_elts, evt_list);
Florin Coras2062ec02019-07-15 13:15:18 -07002024 wrk->new_head = clib_llist_make_head (wrk->event_elts, evt_list);
Florin Coras60183db2019-07-20 15:53:16 -07002025 wrk->old_head = clib_llist_make_head (wrk->event_elts, evt_list);
Florin Corasaf972212021-05-05 09:54:00 -07002026 wrk->pending_connects = clib_llist_make_head (wrk->event_elts, evt_list);
Florin Corase09bd482022-03-21 10:38:01 -07002027 wrk->evts_pending_main =
2028 clib_llist_make_head (wrk->event_elts, evt_list);
Damjan Marion6ffb7c62021-03-26 13:06:13 +01002029 wrk->vm = vlib_get_main_by_index (i);
Dave Barach77d98382020-04-28 18:00:21 -04002030 wrk->last_vlib_time = vlib_time_now (vm);
Florin Corasa8e71c82019-10-22 19:01:39 -07002031 wrk->last_vlib_us_time = wrk->last_vlib_time * CLIB_US_TIME_FREQ;
Florin Corasa48dffe2021-05-16 10:58:53 -07002032 wrk->timerfd = -1;
Florin Coras07063b82020-03-13 04:44:51 +00002033 vec_validate (wrk->session_to_enqueue, smm->last_transport_proto_type);
Florin Corasd67f1122018-05-21 17:47:40 -07002034
Florin Coras7da88292021-03-18 15:04:34 -07002035 if (!smm->no_adaptive && smm->use_private_rx_mqs)
2036 session_wrk_enable_adaptive_mode (wrk);
Dave Barachacd2a6a2017-05-16 17:41:34 -04002037 }
2038
Florin Corasb384b542018-01-15 01:08:33 -08002039 /* Allocate vpp event queues segment and queue */
Florin Coras8afe1b82021-11-17 23:38:54 -08002040 session_vpp_wrk_mqs_alloc (smm);
Florin Corasb384b542018-01-15 01:08:33 -08002041
Florin Coras9a45bd82020-12-28 16:28:07 -08002042 /* Initialize segment manager properties */
2043 segment_manager_main_init ();
Florin Coras6cf30ad2017-04-04 23:08:23 -07002044
Florin Coras66b11312017-07-31 17:18:03 -07002045 /* Preallocate sessions */
Dave Barachb7f1faa2017-08-29 11:43:37 -04002046 if (smm->preallocated_sessions)
Dave Barach68b0fb02017-02-28 15:15:56 -05002047 {
Dave Barachb7f1faa2017-08-29 11:43:37 -04002048 if (num_threads == 1)
Florin Coras66b11312017-07-31 17:18:03 -07002049 {
Florin Coras5a7ca7b2018-10-30 12:01:48 -07002050 pool_init_fixed (smm->wrk[0].sessions, smm->preallocated_sessions);
Florin Coras66b11312017-07-31 17:18:03 -07002051 }
Dave Barachb7f1faa2017-08-29 11:43:37 -04002052 else
Florin Coras66b11312017-07-31 17:18:03 -07002053 {
Dave Barachb7f1faa2017-08-29 11:43:37 -04002054 int j;
2055 preallocated_sessions_per_worker =
2056 (1.1 * (f64) smm->preallocated_sessions /
2057 (f64) (num_threads - 1));
2058
2059 for (j = 1; j < num_threads; j++)
Florin Coras66b11312017-07-31 17:18:03 -07002060 {
Florin Coras5a7ca7b2018-10-30 12:01:48 -07002061 pool_init_fixed (smm->wrk[j].sessions,
Dave Barachb7f1faa2017-08-29 11:43:37 -04002062 preallocated_sessions_per_worker);
Florin Coras66b11312017-07-31 17:18:03 -07002063 }
Florin Coras66b11312017-07-31 17:18:03 -07002064 }
2065 }
Dave Barach68b0fb02017-02-28 15:15:56 -05002066
Florin Coras04e53442017-07-16 17:12:15 -07002067 session_lookup_init ();
Florin Corascea194d2017-10-02 00:18:51 -07002068 app_namespaces_init ();
Florin Coras3cbc04b2017-10-02 00:18:51 -07002069 transport_init ();
Florin Corasd82f4712022-04-25 16:15:02 -07002070 session_stats_collector_init ();
Florin Corase10da622020-10-25 14:00:29 -07002071 smm->is_initialized = 1;
2072
2073done:
Dave Barach68b0fb02017-02-28 15:15:56 -05002074
Florin Corase04c2992017-03-01 08:17:34 -08002075 smm->is_enabled = 1;
2076
Florin Coras561af9b2017-12-09 10:19:43 -08002077 /* Enable transports */
2078 transport_enable_disable (vm, 1);
Florin Coras11166672020-04-13 01:20:25 +00002079 session_debug_init ();
Srikanth Akula73570432020-04-06 19:19:49 -07002080
Dave Barach68b0fb02017-02-28 15:15:56 -05002081 return 0;
2082}
2083
Florin Corase10da622020-10-25 14:00:29 -07002084static void
2085session_manager_main_disable (vlib_main_t * vm)
2086{
2087 transport_enable_disable (vm, 0 /* is_en */ );
2088}
2089
Marvin Liu06542422022-08-16 06:49:09 +00002090/* in this new callback, cookie hint the index */
2091void
2092session_dma_completion_cb (vlib_main_t *vm, struct vlib_dma_batch *batch)
2093{
2094 session_worker_t *wrk;
2095 wrk = session_main_get_worker (vm->thread_index);
2096 session_dma_transfer *dma_transfer;
2097
2098 dma_transfer = &wrk->dma_trans[wrk->trans_head];
2099 vec_add (wrk->pending_tx_buffers, dma_transfer->pending_tx_buffers,
2100 vec_len (dma_transfer->pending_tx_buffers));
2101 vec_add (wrk->pending_tx_nexts, dma_transfer->pending_tx_nexts,
2102 vec_len (dma_transfer->pending_tx_nexts));
2103 vec_reset_length (dma_transfer->pending_tx_buffers);
2104 vec_reset_length (dma_transfer->pending_tx_nexts);
2105 wrk->trans_head++;
2106 if (wrk->trans_head == wrk->trans_size)
2107 wrk->trans_head = 0;
2108 return;
2109}
2110
2111static void
2112session_prepare_dma_args (vlib_dma_config_t *args)
2113{
Marvin Liu48d2e152023-03-14 23:56:31 +08002114 args->max_batches = 16;
Marvin Liu06542422022-08-16 06:49:09 +00002115 args->max_transfers = DMA_TRANS_SIZE;
2116 args->max_transfer_size = 65536;
2117 args->features = 0;
2118 args->sw_fallback = 1;
2119 args->barrier_before_last = 1;
2120 args->callback_fn = session_dma_completion_cb;
2121}
2122
2123static void
2124session_node_enable_dma (u8 is_en, int n_vlibs)
2125{
2126 vlib_dma_config_t args;
2127 session_prepare_dma_args (&args);
2128 session_worker_t *wrk;
2129 vlib_main_t *vm;
2130
2131 int config_index = -1;
2132
2133 if (is_en)
2134 {
2135 vm = vlib_get_main_by_index (0);
2136 config_index = vlib_dma_config_add (vm, &args);
2137 }
2138 else
2139 {
2140 vm = vlib_get_main_by_index (0);
2141 wrk = session_main_get_worker (0);
2142 if (wrk->config_index >= 0)
2143 vlib_dma_config_del (vm, wrk->config_index);
2144 }
2145 int i;
2146 for (i = 0; i < n_vlibs; i++)
2147 {
2148 vm = vlib_get_main_by_index (i);
2149 wrk = session_main_get_worker (vm->thread_index);
2150 wrk->config_index = config_index;
2151 if (is_en)
2152 {
2153 if (config_index >= 0)
2154 wrk->dma_enabled = true;
2155 wrk->dma_trans = (session_dma_transfer *) clib_mem_alloc (
2156 sizeof (session_dma_transfer) * DMA_TRANS_SIZE);
2157 bzero (wrk->dma_trans,
2158 sizeof (session_dma_transfer) * DMA_TRANS_SIZE);
2159 }
2160 else
2161 {
2162 if (wrk->dma_trans)
2163 clib_mem_free (wrk->dma_trans);
2164 }
2165 wrk->trans_head = 0;
2166 wrk->trans_tail = 0;
2167 wrk->trans_size = DMA_TRANS_SIZE;
2168 }
2169}
2170
Florin Coras75e8e1e2024-07-02 04:34:54 -07002171static void
2172session_main_start_q_process (vlib_main_t *vm, vlib_node_state_t state)
2173{
2174 vlib_node_t *n;
2175
2176 vlib_node_set_state (vm, session_queue_process_node.index, state);
2177 n = vlib_get_node (vm, session_queue_process_node.index);
2178 vlib_start_process (vm, n->runtime_index);
2179}
2180
Florin Corasa5464812017-04-19 13:00:05 -07002181void
2182session_node_enable_disable (u8 is_en)
2183{
Florin Coras1d2e38b2021-03-17 21:52:49 -07002184 u8 mstate = is_en ? VLIB_NODE_STATE_INTERRUPT : VLIB_NODE_STATE_DISABLED;
Florin Corasa5464812017-04-19 13:00:05 -07002185 u8 state = is_en ? VLIB_NODE_STATE_POLLING : VLIB_NODE_STATE_DISABLED;
Florin Coras1d2e38b2021-03-17 21:52:49 -07002186 session_main_t *sm = &session_main;
2187 vlib_main_t *vm;
Florin Coras1d2e38b2021-03-17 21:52:49 -07002188 int n_vlibs, i;
Florin Corasfd542f12018-05-16 19:28:24 -07002189
Florin Coras1d2e38b2021-03-17 21:52:49 -07002190 n_vlibs = vlib_get_n_threads ();
2191 for (i = 0; i < n_vlibs; i++)
Damjan Marion92ccf9b2021-03-26 11:38:01 +01002192 {
Florin Coras1d2e38b2021-03-17 21:52:49 -07002193 vm = vlib_get_main_by_index (i);
2194 /* main thread with workers and not polling */
2195 if (i == 0 && n_vlibs > 1)
Damjan Marion92ccf9b2021-03-26 11:38:01 +01002196 {
Florin Coras1d2e38b2021-03-17 21:52:49 -07002197 vlib_node_set_state (vm, session_queue_node.index, mstate);
Damjan Marion92ccf9b2021-03-26 11:38:01 +01002198 if (is_en)
2199 {
Florin Corasb32af352021-05-19 07:58:49 -07002200 session_main_get_worker (0)->state = SESSION_WRK_INTERRUPT;
Florin Coras75e8e1e2024-07-02 04:34:54 -07002201 session_main_start_q_process (vm, state);
Damjan Marion92ccf9b2021-03-26 11:38:01 +01002202 }
2203 else
2204 {
Florin Coras1d2e38b2021-03-17 21:52:49 -07002205 vlib_process_signal_event_mt (vm,
Damjan Marion92ccf9b2021-03-26 11:38:01 +01002206 session_queue_process_node.index,
2207 SESSION_Q_PROCESS_STOP, 0);
2208 }
Florin Coras1d2e38b2021-03-17 21:52:49 -07002209 if (!sm->poll_main)
Damjan Marion92ccf9b2021-03-26 11:38:01 +01002210 continue;
2211 }
Florin Coras0242d302022-12-22 15:03:44 -08002212 vlib_node_set_state (vm, session_input_node.index, mstate);
Florin Coras1d2e38b2021-03-17 21:52:49 -07002213 vlib_node_set_state (vm, session_queue_node.index, state);
Damjan Marion92ccf9b2021-03-26 11:38:01 +01002214 }
Florin Coras41d5f542021-01-15 13:49:33 -08002215
Florin Coras1d2e38b2021-03-17 21:52:49 -07002216 if (sm->use_private_rx_mqs)
Florin Coras41d5f542021-01-15 13:49:33 -08002217 application_enable_rx_mqs_nodes (is_en);
Marvin Liu06542422022-08-16 06:49:09 +00002218
2219 if (sm->dma_enabled)
2220 session_node_enable_dma (is_en, n_vlibs);
Florin Corasa5464812017-04-19 13:00:05 -07002221}
2222
Florin Corase04c2992017-03-01 08:17:34 -08002223clib_error_t *
2224vnet_session_enable_disable (vlib_main_t * vm, u8 is_en)
2225{
Florin Corascea194d2017-10-02 00:18:51 -07002226 clib_error_t *error = 0;
Florin Corase04c2992017-03-01 08:17:34 -08002227 if (is_en)
2228 {
Florin Coras31c99552019-03-01 13:00:58 -08002229 if (session_main.is_enabled)
Florin Corase04c2992017-03-01 08:17:34 -08002230 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05002231
Florin Corascea194d2017-10-02 00:18:51 -07002232 error = session_manager_main_enable (vm);
Vladimir Kropyleva2e44512019-07-16 21:32:41 +03002233 session_node_enable_disable (is_en);
Florin Corase04c2992017-03-01 08:17:34 -08002234 }
2235 else
2236 {
Florin Coras31c99552019-03-01 13:00:58 -08002237 session_main.is_enabled = 0;
Florin Corase10da622020-10-25 14:00:29 -07002238 session_manager_main_disable (vm);
Florin Corasa5464812017-04-19 13:00:05 -07002239 session_node_enable_disable (is_en);
Florin Corase04c2992017-03-01 08:17:34 -08002240 }
2241
Florin Corascea194d2017-10-02 00:18:51 -07002242 return error;
Florin Corase04c2992017-03-01 08:17:34 -08002243}
2244
Florin Corase04c2992017-03-01 08:17:34 -08002245clib_error_t *
Florin Corase33c0022020-04-03 17:23:42 +00002246session_main_init (vlib_main_t * vm)
Florin Corase04c2992017-03-01 08:17:34 -08002247{
Florin Coras31c99552019-03-01 13:00:58 -08002248 session_main_t *smm = &session_main;
Florin Corase33c0022020-04-03 17:23:42 +00002249
2250 smm->is_enabled = 0;
2251 smm->session_enable_asap = 0;
Florin Corase92c9462020-11-25 08:44:16 -08002252 smm->poll_main = 0;
Florin Coras41d5f542021-01-15 13:49:33 -08002253 smm->use_private_rx_mqs = 0;
Florin Coras7da88292021-03-18 15:04:34 -07002254 smm->no_adaptive = 0;
Florin Coras0b656212022-01-13 11:59:44 -08002255 smm->last_transport_proto_type = TRANSPORT_PROTO_HTTP;
Nathan Skrzypczake111bbd2023-10-03 13:54:15 +02002256 smm->port_allocator_min_src_port = 1024;
2257 smm->port_allocator_max_src_port = 65535;
Florin Corase33c0022020-04-03 17:23:42 +00002258
Nathan Skrzypczak31bd0352019-11-07 17:55:01 +01002259 return 0;
2260}
2261
2262static clib_error_t *
Florin Corase33c0022020-04-03 17:23:42 +00002263session_main_loop_init (vlib_main_t * vm)
Nathan Skrzypczak31bd0352019-11-07 17:55:01 +01002264{
2265 session_main_t *smm = &session_main;
2266 if (smm->session_enable_asap)
2267 {
2268 vlib_worker_thread_barrier_sync (vm);
2269 vnet_session_enable_disable (vm, 1 /* is_en */ );
2270 vlib_worker_thread_barrier_release (vm);
2271 }
Florin Corase04c2992017-03-01 08:17:34 -08002272 return 0;
2273}
2274
Florin Corase33c0022020-04-03 17:23:42 +00002275VLIB_INIT_FUNCTION (session_main_init);
2276VLIB_MAIN_LOOP_ENTER_FUNCTION (session_main_loop_init);
Dave Barach2c25a622017-06-26 11:35:07 -04002277
2278static clib_error_t *
2279session_config_fn (vlib_main_t * vm, unformat_input_t * input)
Dave Barach10d8cc62017-05-30 09:30:07 -04002280{
Florin Coras31c99552019-03-01 13:00:58 -08002281 session_main_t *smm = &session_main;
Dave Barach10d8cc62017-05-30 09:30:07 -04002282 u32 nitems;
Florin Coras66b11312017-07-31 17:18:03 -07002283 uword tmp;
Dave Barach10d8cc62017-05-30 09:30:07 -04002284
2285 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2286 {
Florin Coras8afe1b82021-11-17 23:38:54 -08002287 if (unformat (input, "wrk-mq-length %d", &nitems))
Dave Barach10d8cc62017-05-30 09:30:07 -04002288 {
2289 if (nitems >= 2048)
Florin Coras8afe1b82021-11-17 23:38:54 -08002290 smm->configured_wrk_mq_length = nitems;
Dave Barach10d8cc62017-05-30 09:30:07 -04002291 else
2292 clib_warning ("event queue length %d too small, ignored", nitems);
2293 }
Florin Corascf5c7742022-06-28 14:34:45 -07002294 else if (unformat (input, "wrk-mqs-segment-size %U",
2295 unformat_memory_size, &smm->wrk_mqs_segment_size))
2296 ;
Florin Coras66b11312017-07-31 17:18:03 -07002297 else if (unformat (input, "preallocated-sessions %d",
2298 &smm->preallocated_sessions))
Dave Barach2c25a622017-06-26 11:35:07 -04002299 ;
Florin Coras66b11312017-07-31 17:18:03 -07002300 else if (unformat (input, "v4-session-table-buckets %d",
2301 &smm->configured_v4_session_table_buckets))
2302 ;
2303 else if (unformat (input, "v4-halfopen-table-buckets %d",
2304 &smm->configured_v4_halfopen_table_buckets))
2305 ;
2306 else if (unformat (input, "v6-session-table-buckets %d",
2307 &smm->configured_v6_session_table_buckets))
2308 ;
2309 else if (unformat (input, "v6-halfopen-table-buckets %d",
2310 &smm->configured_v6_halfopen_table_buckets))
2311 ;
2312 else if (unformat (input, "v4-session-table-memory %U",
2313 unformat_memory_size, &tmp))
2314 {
2315 if (tmp >= 0x100000000)
2316 return clib_error_return (0, "memory size %llx (%lld) too large",
2317 tmp, tmp);
2318 smm->configured_v4_session_table_memory = tmp;
2319 }
2320 else if (unformat (input, "v4-halfopen-table-memory %U",
2321 unformat_memory_size, &tmp))
2322 {
2323 if (tmp >= 0x100000000)
2324 return clib_error_return (0, "memory size %llx (%lld) too large",
2325 tmp, tmp);
2326 smm->configured_v4_halfopen_table_memory = tmp;
2327 }
2328 else if (unformat (input, "v6-session-table-memory %U",
2329 unformat_memory_size, &tmp))
2330 {
2331 if (tmp >= 0x100000000)
2332 return clib_error_return (0, "memory size %llx (%lld) too large",
2333 tmp, tmp);
2334 smm->configured_v6_session_table_memory = tmp;
2335 }
2336 else if (unformat (input, "v6-halfopen-table-memory %U",
2337 unformat_memory_size, &tmp))
2338 {
2339 if (tmp >= 0x100000000)
2340 return clib_error_return (0, "memory size %llx (%lld) too large",
2341 tmp, tmp);
2342 smm->configured_v6_halfopen_table_memory = tmp;
2343 }
Florin Coras93e65802017-11-29 00:07:11 -05002344 else if (unformat (input, "local-endpoints-table-memory %U",
2345 unformat_memory_size, &tmp))
2346 {
2347 if (tmp >= 0x100000000)
2348 return clib_error_return (0, "memory size %llx (%lld) too large",
2349 tmp, tmp);
2350 smm->local_endpoints_table_memory = tmp;
2351 }
2352 else if (unformat (input, "local-endpoints-table-buckets %d",
2353 &smm->local_endpoints_table_buckets))
2354 ;
Nathan Skrzypczake111bbd2023-10-03 13:54:15 +02002355 else if (unformat (input, "min-src-port %d", &tmp))
2356 smm->port_allocator_min_src_port = tmp;
2357 else if (unformat (input, "max-src-port %d", &tmp))
2358 smm->port_allocator_max_src_port = tmp;
Nathan Skrzypczak1292d192019-09-13 15:44:54 +02002359 else if (unformat (input, "enable"))
Nathan Skrzypczak31bd0352019-11-07 17:55:01 +01002360 smm->session_enable_asap = 1;
Florin Coras61ae0562020-09-02 19:10:28 -07002361 else if (unformat (input, "use-app-socket-api"))
Nathan Skrzypczak7b3a3df2021-07-28 14:09:50 +02002362 (void) appns_sapi_enable_disable (1 /* is_enable */);
Florin Corase92c9462020-11-25 08:44:16 -08002363 else if (unformat (input, "poll-main"))
2364 smm->poll_main = 1;
Florin Coras41d5f542021-01-15 13:49:33 -08002365 else if (unformat (input, "use-private-rx-mqs"))
2366 smm->use_private_rx_mqs = 1;
Florin Coras7da88292021-03-18 15:04:34 -07002367 else if (unformat (input, "no-adaptive"))
2368 smm->no_adaptive = 1;
Marvin Liu06542422022-08-16 06:49:09 +00002369 else if (unformat (input, "use-dma"))
2370 smm->dma_enabled = 1;
qinyangaf9b7152023-06-27 01:11:53 -07002371 else if (unformat (input, "nat44-original-dst-enable"))
2372 {
2373 smm->original_dst_lookup = vlib_get_plugin_symbol (
2374 "nat_plugin.so", "nat44_original_dst_lookup");
2375 }
Florin Coras8afe1b82021-11-17 23:38:54 -08002376 /*
2377 * Deprecated but maintained for compatibility
2378 */
2379 else if (unformat (input, "evt_qs_memfd_seg"))
2380 ;
Florin Corasef048032021-11-17 23:57:30 -08002381 else if (unformat (input, "segment-baseva 0x%lx", &tmp))
2382 ;
Florin Coras8afe1b82021-11-17 23:38:54 -08002383 else if (unformat (input, "evt_qs_seg_size %U", unformat_memory_size,
Florin Corascf5c7742022-06-28 14:34:45 -07002384 &smm->wrk_mqs_segment_size))
Florin Coras8afe1b82021-11-17 23:38:54 -08002385 ;
2386 else if (unformat (input, "event-queue-length %d", &nitems))
2387 {
2388 if (nitems >= 2048)
2389 smm->configured_wrk_mq_length = nitems;
2390 else
2391 clib_warning ("event queue length %d too small, ignored", nitems);
2392 }
Dave Barach10d8cc62017-05-30 09:30:07 -04002393 else
2394 return clib_error_return (0, "unknown input `%U'",
2395 format_unformat_error, input);
2396 }
2397 return 0;
2398}
2399
2400VLIB_CONFIG_FUNCTION (session_config_fn, "session");
2401
Dave Barach68b0fb02017-02-28 15:15:56 -05002402/*
2403 * fd.io coding-style-patch-verification: ON
2404 *
2405 * Local Variables:
2406 * eval: (c-set-style "gnu")
2407 * End:
2408 */