blob: ea22bcd22f534baf3be8ae7c401443bcc6f8b283 [file] [log] [blame]
Florin Coras7baeb712019-01-04 17:05:43 -08001/*
2 * Copyright (c) 2019 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vcl/vcl_locked.h>
17#include <vcl/vcl_private.h>
18
Florin Coras243edd52020-03-04 22:20:12 +000019typedef struct vls_shared_data_
20{
21 clib_spinlock_t lock;
22 u32 owner_wrk_index;
23 u32 *workers_subscribed;
24 clib_bitmap_t *listeners;
25} vls_shared_data_t;
26
Florin Coras7baeb712019-01-04 17:05:43 -080027typedef struct vcl_locked_session_
28{
Florin Corasf9240dc2019-01-15 08:03:17 -080029 clib_spinlock_t lock;
Florin Coras7baeb712019-01-04 17:05:43 -080030 u32 session_index;
31 u32 worker_index;
32 u32 vls_index;
Florin Coras243edd52020-03-04 22:20:12 +000033 u32 shared_data_index;
hanlina3a48962020-07-13 11:09:15 +080034 /** VCL session owned by different workers because of migration */
35 u32 owner_vcl_wrk_index;
36 uword *vcl_wrk_index_to_session_index;
Florin Coras7baeb712019-01-04 17:05:43 -080037} vcl_locked_session_t;
38
Florin Coras243edd52020-03-04 22:20:12 +000039typedef struct vls_worker_
40{
wanghanline8f848a2021-01-08 14:57:11 +080041 clib_rwlock_t sh_to_vlsh_table_lock; /** valid for multithread workers */
Florin Coras243edd52020-03-04 22:20:12 +000042 vcl_locked_session_t *vls_pool;
hanlinf8e13632020-08-21 11:05:36 +080043 uword *session_handle_to_vlsh_table;
Florin Coras243edd52020-03-04 22:20:12 +000044 u32 wrk_index;
45} vls_worker_t;
46
Florin Coras2d675d72019-01-28 15:54:27 -080047typedef struct vls_local_
48{
49 int vls_wrk_index;
50 volatile int vls_mt_n_threads;
51 pthread_mutex_t vls_mt_mq_mlock;
52 pthread_mutex_t vls_mt_spool_mlock;
53 volatile u8 select_mp_check;
Florin Coras2d675d72019-01-28 15:54:27 -080054} vls_process_local_t;
55
56static vls_process_local_t vls_local;
57static vls_process_local_t *vlsl = &vls_local;
58
59typedef struct vls_main_
Florin Coras7baeb712019-01-04 17:05:43 -080060{
Florin Coras243edd52020-03-04 22:20:12 +000061 vls_worker_t *workers;
Florin Coras7baeb712019-01-04 17:05:43 -080062 clib_rwlock_t vls_table_lock;
Florin Coras243edd52020-03-04 22:20:12 +000063 /** Pool of data shared by sessions owned by different workers */
64 vls_shared_data_t *shared_data_pool;
65 clib_rwlock_t shared_data_lock;
wanghanlindcacdc42020-12-28 16:19:05 +080066 /** Lock to protect rpc among workers */
67 clib_spinlock_t worker_rpc_lock;
Florin Coras7baeb712019-01-04 17:05:43 -080068} vls_main_t;
69
Florin Coras2d675d72019-01-28 15:54:27 -080070vls_main_t *vlsm;
Florin Coras7baeb712019-01-04 17:05:43 -080071
wanghanlindcacdc42020-12-28 16:19:05 +080072typedef enum
73{
74 VLS_RPC_STATE_INIT,
75 VLS_RPC_STATE_SUCCESS,
76 VLS_RPC_STATE_SESSION_NOT_EXIST,
77} vls_rpc_state_e;
78
Florin Coras40c07ce2020-07-16 20:46:17 -070079typedef enum vls_rpc_msg_type_
80{
81 VLS_RPC_CLONE_AND_SHARE,
hanlina3a48962020-07-13 11:09:15 +080082 VLS_RPC_SESS_CLEANUP,
Florin Coras40c07ce2020-07-16 20:46:17 -070083} vls_rpc_msg_type_e;
84
85typedef struct vls_rpc_msg_
86{
87 u8 type;
88 u8 data[0];
89} vls_rpc_msg_t;
90
91typedef struct vls_clone_and_share_msg_
92{
93 u32 vls_index; /**< vls to be shared */
hanlina3a48962020-07-13 11:09:15 +080094 u32 session_index; /**< vcl session to be shared */
95 u32 origin_vls_wrk; /**< vls worker that initiated the rpc */
Florin Coras40c07ce2020-07-16 20:46:17 -070096 u32 origin_vls_index; /**< vls session of the originator */
hanlina3a48962020-07-13 11:09:15 +080097 u32 origin_vcl_wrk; /**< vcl worker that initiated the rpc */
98 u32 origin_session_index; /**< vcl session of the originator */
Florin Coras40c07ce2020-07-16 20:46:17 -070099} vls_clone_and_share_msg_t;
100
hanlina3a48962020-07-13 11:09:15 +0800101typedef struct vls_sess_cleanup_msg_
102{
103 u32 session_index; /**< vcl session to be cleaned */
104 u32 origin_vcl_wrk; /**< worker that initiated the rpc */
105} vls_sess_cleanup_msg_t;
106
107void vls_send_session_cleanup_rpc (vcl_worker_t * wrk,
108 u32 dst_wrk_index, u32 dst_session_index);
wanghanlindcacdc42020-12-28 16:19:05 +0800109void vls_send_clone_and_share_rpc (vcl_worker_t *wrk, u32 origin_vls_index,
hanlina3a48962020-07-13 11:09:15 +0800110 u32 session_index, u32 vls_wrk_index,
111 u32 dst_wrk_index, u32 dst_vls_index,
112 u32 dst_session_index);
113
Florin Coras243edd52020-03-04 22:20:12 +0000114static inline u32
115vls_get_worker_index (void)
116{
hanlina3a48962020-07-13 11:09:15 +0800117 if (vls_mt_wrk_supported ())
118 return vlsl->vls_wrk_index;
119 else
120 return vcl_get_worker_index ();
Florin Coras243edd52020-03-04 22:20:12 +0000121}
122
123static u32
124vls_shared_data_alloc (void)
125{
126 vls_shared_data_t *vls_shd;
127 u32 shd_index;
128
129 clib_rwlock_writer_lock (&vlsm->shared_data_lock);
130 pool_get_zero (vlsm->shared_data_pool, vls_shd);
131 clib_spinlock_init (&vls_shd->lock);
132 shd_index = vls_shd - vlsm->shared_data_pool;
133 clib_rwlock_writer_unlock (&vlsm->shared_data_lock);
134
135 return shd_index;
136}
137
138static u32
139vls_shared_data_index (vls_shared_data_t * vls_shd)
140{
141 return vls_shd - vlsm->shared_data_pool;
142}
143
144vls_shared_data_t *
145vls_shared_data_get (u32 shd_index)
146{
147 if (pool_is_free_index (vlsm->shared_data_pool, shd_index))
148 return 0;
149 return pool_elt_at_index (vlsm->shared_data_pool, shd_index);
150}
151
152static void
153vls_shared_data_free (u32 shd_index)
154{
155 vls_shared_data_t *vls_shd;
156
157 clib_rwlock_writer_lock (&vlsm->shared_data_lock);
158 vls_shd = vls_shared_data_get (shd_index);
159 clib_spinlock_free (&vls_shd->lock);
160 clib_bitmap_free (vls_shd->listeners);
161 vec_free (vls_shd->workers_subscribed);
162 pool_put (vlsm->shared_data_pool, vls_shd);
163 clib_rwlock_writer_unlock (&vlsm->shared_data_lock);
164}
165
166static inline void
167vls_shared_data_pool_rlock (void)
168{
169 clib_rwlock_reader_lock (&vlsm->shared_data_lock);
170}
171
172static inline void
173vls_shared_data_pool_runlock (void)
174{
175 clib_rwlock_reader_unlock (&vlsm->shared_data_lock);
176}
177
Florin Coras7baeb712019-01-04 17:05:43 -0800178static inline void
Florin Corasff40d8f2020-08-11 22:05:28 -0700179vls_mt_table_rlock (void)
Florin Coras7baeb712019-01-04 17:05:43 -0800180{
Florin Coras243edd52020-03-04 22:20:12 +0000181 if (vlsl->vls_mt_n_threads > 1)
182 clib_rwlock_reader_lock (&vlsm->vls_table_lock);
Florin Coras7baeb712019-01-04 17:05:43 -0800183}
184
185static inline void
Florin Corasff40d8f2020-08-11 22:05:28 -0700186vls_mt_table_runlock (void)
Florin Coras7baeb712019-01-04 17:05:43 -0800187{
Florin Coras243edd52020-03-04 22:20:12 +0000188 if (vlsl->vls_mt_n_threads > 1)
189 clib_rwlock_reader_unlock (&vlsm->vls_table_lock);
Florin Coras7baeb712019-01-04 17:05:43 -0800190}
191
192static inline void
Florin Corasff40d8f2020-08-11 22:05:28 -0700193vls_mt_table_wlock (void)
Florin Coras7baeb712019-01-04 17:05:43 -0800194{
Florin Coras243edd52020-03-04 22:20:12 +0000195 if (vlsl->vls_mt_n_threads > 1)
196 clib_rwlock_writer_lock (&vlsm->vls_table_lock);
Florin Coras7baeb712019-01-04 17:05:43 -0800197}
198
199static inline void
Florin Corasff40d8f2020-08-11 22:05:28 -0700200vls_mt_table_wunlock (void)
Florin Coras7baeb712019-01-04 17:05:43 -0800201{
Florin Coras243edd52020-03-04 22:20:12 +0000202 if (vlsl->vls_mt_n_threads > 1)
203 clib_rwlock_writer_unlock (&vlsm->vls_table_lock);
Florin Coras7baeb712019-01-04 17:05:43 -0800204}
205
Florin Coras0ef8ef22019-01-18 08:37:13 -0800206typedef enum
207{
208 VLS_MT_OP_READ,
209 VLS_MT_OP_WRITE,
210 VLS_MT_OP_SPOOL,
211 VLS_MT_OP_XPOLL,
212} vls_mt_ops_t;
213
214typedef enum
215{
216 VLS_MT_LOCK_MQ = 1 << 0,
217 VLS_MT_LOCK_SPOOL = 1 << 1
218} vls_mt_lock_type_t;
219
Florin Coras0ef8ef22019-01-18 08:37:13 -0800220static void
221vls_mt_add (void)
222{
Florin Coras2d675d72019-01-28 15:54:27 -0800223 vlsl->vls_mt_n_threads += 1;
Florin Corasff40d8f2020-08-11 22:05:28 -0700224
225 /* If multi-thread workers are supported, for each new thread register a new
226 * vcl worker with vpp. Otherwise, all threads use the same vcl worker, so
227 * update the vcl worker's thread local worker index variable */
hanlina3a48962020-07-13 11:09:15 +0800228 if (vls_mt_wrk_supported ())
wanghanlin492350e2020-09-11 17:19:32 +0800229 {
230 if (vppcom_worker_register () != VPPCOM_OK)
231 VERR ("failed to register worker");
232 }
hanlina3a48962020-07-13 11:09:15 +0800233 else
234 vcl_set_worker_index (vlsl->vls_wrk_index);
Florin Coras0ef8ef22019-01-18 08:37:13 -0800235}
236
237static inline void
238vls_mt_mq_lock (void)
239{
Florin Coras2d675d72019-01-28 15:54:27 -0800240 pthread_mutex_lock (&vlsl->vls_mt_mq_mlock);
Florin Coras0ef8ef22019-01-18 08:37:13 -0800241}
242
243static inline void
244vls_mt_mq_unlock (void)
245{
Florin Coras2d675d72019-01-28 15:54:27 -0800246 pthread_mutex_unlock (&vlsl->vls_mt_mq_mlock);
Florin Coras0ef8ef22019-01-18 08:37:13 -0800247}
248
249static inline void
250vls_mt_spool_lock (void)
251{
Florin Coras2d675d72019-01-28 15:54:27 -0800252 pthread_mutex_lock (&vlsl->vls_mt_spool_mlock);
Florin Coras0ef8ef22019-01-18 08:37:13 -0800253}
254
255static inline void
256vls_mt_create_unlock (void)
257{
Florin Coras2d675d72019-01-28 15:54:27 -0800258 pthread_mutex_unlock (&vlsl->vls_mt_spool_mlock);
259}
260
261static void
262vls_mt_locks_init (void)
263{
264 pthread_mutex_init (&vlsl->vls_mt_mq_mlock, NULL);
265 pthread_mutex_init (&vlsl->vls_mt_spool_mlock, NULL);
Florin Coras0ef8ef22019-01-18 08:37:13 -0800266}
267
Florin Coras243edd52020-03-04 22:20:12 +0000268u8
269vls_is_shared (vcl_locked_session_t * vls)
270{
271 return (vls->shared_data_index != ~0);
272}
273
274static inline void
275vls_lock (vcl_locked_session_t * vls)
276{
277 if ((vlsl->vls_mt_n_threads > 1) || vls_is_shared (vls))
278 clib_spinlock_lock (&vls->lock);
279}
280
281static inline void
282vls_unlock (vcl_locked_session_t * vls)
283{
284 if ((vlsl->vls_mt_n_threads > 1) || vls_is_shared (vls))
285 clib_spinlock_unlock (&vls->lock);
286}
287
Florin Coras7baeb712019-01-04 17:05:43 -0800288static inline vcl_session_handle_t
289vls_to_sh (vcl_locked_session_t * vls)
290{
Florin Corasf9240dc2019-01-15 08:03:17 -0800291 return vcl_session_handle_from_index (vls->session_index);
Florin Coras7baeb712019-01-04 17:05:43 -0800292}
293
294static inline vcl_session_handle_t
295vls_to_sh_tu (vcl_locked_session_t * vls)
296{
297 vcl_session_handle_t sh;
298 sh = vls_to_sh (vls);
Florin Corasff40d8f2020-08-11 22:05:28 -0700299 vls_mt_table_runlock ();
Florin Coras7baeb712019-01-04 17:05:43 -0800300 return sh;
301}
302
Florin Coras243edd52020-03-04 22:20:12 +0000303static vls_worker_t *
304vls_worker_get_current (void)
305{
306 return pool_elt_at_index (vlsm->workers, vls_get_worker_index ());
307}
308
309static void
310vls_worker_alloc (void)
311{
312 vls_worker_t *wrk;
313
314 pool_get_zero (vlsm->workers, wrk);
wanghanline8f848a2021-01-08 14:57:11 +0800315 if (vls_mt_wrk_supported ())
316 clib_rwlock_init (&wrk->sh_to_vlsh_table_lock);
Florin Coras243edd52020-03-04 22:20:12 +0000317 wrk->wrk_index = vcl_get_worker_index ();
318}
319
320static void
321vls_worker_free (vls_worker_t * wrk)
322{
hanlinf8e13632020-08-21 11:05:36 +0800323 hash_free (wrk->session_handle_to_vlsh_table);
wanghanline8f848a2021-01-08 14:57:11 +0800324 if (vls_mt_wrk_supported ())
325 clib_rwlock_free (&wrk->sh_to_vlsh_table_lock);
Florin Coras243edd52020-03-04 22:20:12 +0000326 pool_free (wrk->vls_pool);
327 pool_put (vlsm->workers, wrk);
328}
329
330static vls_worker_t *
331vls_worker_get (u32 wrk_index)
332{
333 if (pool_is_free_index (vlsm->workers, wrk_index))
334 return 0;
335 return pool_elt_at_index (vlsm->workers, wrk_index);
336}
337
wanghanline8f848a2021-01-08 14:57:11 +0800338static void
339vls_sh_to_vlsh_table_add (vls_worker_t *wrk, vcl_session_handle_t sh, u32 vlsh)
340{
341 if (vls_mt_wrk_supported ())
342 clib_rwlock_writer_lock (&wrk->sh_to_vlsh_table_lock);
343 hash_set (wrk->session_handle_to_vlsh_table, sh, vlsh);
344 if (vls_mt_wrk_supported ())
345 clib_rwlock_writer_unlock (&wrk->sh_to_vlsh_table_lock);
346}
347
348static void
349vls_sh_to_vlsh_table_del (vls_worker_t *wrk, vcl_session_handle_t sh)
350{
351 if (vls_mt_wrk_supported ())
352 clib_rwlock_writer_lock (&wrk->sh_to_vlsh_table_lock);
353 hash_unset (wrk->session_handle_to_vlsh_table, sh);
354 if (vls_mt_wrk_supported ())
355 clib_rwlock_writer_unlock (&wrk->sh_to_vlsh_table_lock);
356}
357
358static uword *
359vls_sh_to_vlsh_table_get (vls_worker_t *wrk, vcl_session_handle_t sh)
360{
361 if (vls_mt_wrk_supported ())
362 clib_rwlock_reader_lock (&wrk->sh_to_vlsh_table_lock);
363 uword *vlshp = hash_get (wrk->session_handle_to_vlsh_table, sh);
364 if (vls_mt_wrk_supported ())
365 clib_rwlock_reader_unlock (&wrk->sh_to_vlsh_table_lock);
366 return vlshp;
367}
368
Florin Coras7baeb712019-01-04 17:05:43 -0800369static vls_handle_t
370vls_alloc (vcl_session_handle_t sh)
371{
Florin Coras243edd52020-03-04 22:20:12 +0000372 vls_worker_t *wrk = vls_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -0800373 vcl_locked_session_t *vls;
374
Florin Corasff40d8f2020-08-11 22:05:28 -0700375 vls_mt_table_wlock ();
Florin Coras243edd52020-03-04 22:20:12 +0000376
377 pool_get_zero (wrk->vls_pool, vls);
Florin Coras7baeb712019-01-04 17:05:43 -0800378 vls->session_index = vppcom_session_index (sh);
379 vls->worker_index = vppcom_session_worker (sh);
Florin Coras243edd52020-03-04 22:20:12 +0000380 vls->vls_index = vls - wrk->vls_pool;
381 vls->shared_data_index = ~0;
wanghanline8f848a2021-01-08 14:57:11 +0800382 vls_sh_to_vlsh_table_add (wrk, sh, vls->vls_index);
hanlina3a48962020-07-13 11:09:15 +0800383 if (vls_mt_wrk_supported ())
384 {
385 hash_set (vls->vcl_wrk_index_to_session_index, vls->worker_index,
386 vls->session_index);
387 vls->owner_vcl_wrk_index = vls->worker_index;
388 }
Florin Coras7baeb712019-01-04 17:05:43 -0800389 clib_spinlock_init (&vls->lock);
Florin Coras243edd52020-03-04 22:20:12 +0000390
Florin Corasff40d8f2020-08-11 22:05:28 -0700391 vls_mt_table_wunlock ();
Florin Coras7baeb712019-01-04 17:05:43 -0800392 return vls->vls_index;
393}
394
395static vcl_locked_session_t *
396vls_get (vls_handle_t vlsh)
397{
Florin Coras243edd52020-03-04 22:20:12 +0000398 vls_worker_t *wrk = vls_worker_get_current ();
399 if (pool_is_free_index (wrk->vls_pool, vlsh))
Florin Coras7baeb712019-01-04 17:05:43 -0800400 return 0;
Florin Coras243edd52020-03-04 22:20:12 +0000401 return pool_elt_at_index (wrk->vls_pool, vlsh);
Florin Coras7baeb712019-01-04 17:05:43 -0800402}
403
404static void
Florin Coras0ef8ef22019-01-18 08:37:13 -0800405vls_free (vcl_locked_session_t * vls)
Florin Coras7baeb712019-01-04 17:05:43 -0800406{
Florin Coras243edd52020-03-04 22:20:12 +0000407 vls_worker_t *wrk = vls_worker_get_current ();
408
Florin Coras0ef8ef22019-01-18 08:37:13 -0800409 ASSERT (vls != 0);
wanghanline8f848a2021-01-08 14:57:11 +0800410 vls_sh_to_vlsh_table_del (
411 wrk, vcl_session_handle_from_index (vls->session_index));
Florin Coras0ef8ef22019-01-18 08:37:13 -0800412 clib_spinlock_free (&vls->lock);
Florin Coras243edd52020-03-04 22:20:12 +0000413 pool_put (wrk->vls_pool, vls);
Florin Coras7baeb712019-01-04 17:05:43 -0800414}
415
416static vcl_locked_session_t *
417vls_get_and_lock (vls_handle_t vlsh)
418{
Florin Coras243edd52020-03-04 22:20:12 +0000419 vls_worker_t *wrk = vls_worker_get_current ();
Florin Coras7baeb712019-01-04 17:05:43 -0800420 vcl_locked_session_t *vls;
Florin Coras243edd52020-03-04 22:20:12 +0000421 if (pool_is_free_index (wrk->vls_pool, vlsh))
Florin Coras7baeb712019-01-04 17:05:43 -0800422 return 0;
Florin Coras243edd52020-03-04 22:20:12 +0000423 vls = pool_elt_at_index (wrk->vls_pool, vlsh);
424 vls_lock (vls);
Florin Coras7baeb712019-01-04 17:05:43 -0800425 return vls;
426}
427
428static vcl_locked_session_t *
429vls_get_w_dlock (vls_handle_t vlsh)
430{
431 vcl_locked_session_t *vls;
Florin Corasff40d8f2020-08-11 22:05:28 -0700432 vls_mt_table_rlock ();
Florin Coras7baeb712019-01-04 17:05:43 -0800433 vls = vls_get_and_lock (vlsh);
434 if (!vls)
Florin Corasff40d8f2020-08-11 22:05:28 -0700435 vls_mt_table_runlock ();
Florin Coras7baeb712019-01-04 17:05:43 -0800436 return vls;
437}
438
439static inline void
Florin Coras7baeb712019-01-04 17:05:43 -0800440vls_get_and_unlock (vls_handle_t vlsh)
441{
442 vcl_locked_session_t *vls;
Florin Corasff40d8f2020-08-11 22:05:28 -0700443 vls_mt_table_rlock ();
Florin Coras7baeb712019-01-04 17:05:43 -0800444 vls = vls_get (vlsh);
445 vls_unlock (vls);
Florin Corasff40d8f2020-08-11 22:05:28 -0700446 vls_mt_table_runlock ();
Florin Coras7baeb712019-01-04 17:05:43 -0800447}
448
449static inline void
450vls_dunlock (vcl_locked_session_t * vls)
451{
452 vls_unlock (vls);
Florin Corasff40d8f2020-08-11 22:05:28 -0700453 vls_mt_table_runlock ();
Florin Coras7baeb712019-01-04 17:05:43 -0800454}
455
Florin Coras243edd52020-03-04 22:20:12 +0000456static vcl_locked_session_t *
457vls_session_get (vls_worker_t * wrk, u32 vls_index)
458{
459 if (pool_is_free_index (wrk->vls_pool, vls_index))
460 return 0;
461 return pool_elt_at_index (wrk->vls_pool, vls_index);
462}
463
Florin Coras2d675d72019-01-28 15:54:27 -0800464vcl_session_handle_t
465vlsh_to_sh (vls_handle_t vlsh)
466{
467 vcl_locked_session_t *vls;
468 int rv;
469
470 vls = vls_get_w_dlock (vlsh);
471 if (!vls)
472 return INVALID_SESSION_ID;
473 rv = vls_to_sh (vls);
474 vls_dunlock (vls);
475 return rv;
476}
477
478vcl_session_handle_t
479vlsh_to_session_index (vls_handle_t vlsh)
480{
481 vcl_session_handle_t sh;
482 sh = vlsh_to_sh (vlsh);
483 return vppcom_session_index (sh);
484}
485
486vls_handle_t
hanlinf8e13632020-08-21 11:05:36 +0800487vls_si_wi_to_vlsh (u32 session_index, u32 vcl_wrk_index)
Florin Coras2d675d72019-01-28 15:54:27 -0800488{
Florin Coras243edd52020-03-04 22:20:12 +0000489 vls_worker_t *wrk = vls_worker_get_current ();
wanghanline8f848a2021-01-08 14:57:11 +0800490 uword *vlshp = vls_sh_to_vlsh_table_get (
491 wrk,
492 vcl_session_handle_from_wrk_session_index (session_index, vcl_wrk_index));
493
Florin Coras2d675d72019-01-28 15:54:27 -0800494 return vlshp ? *vlshp : VLS_INVALID_HANDLE;
495}
496
497vls_handle_t
498vls_session_index_to_vlsh (uint32_t session_index)
499{
500 vls_handle_t vlsh;
501
Florin Corasff40d8f2020-08-11 22:05:28 -0700502 vls_mt_table_rlock ();
hanlinf8e13632020-08-21 11:05:36 +0800503 vlsh = vls_si_wi_to_vlsh (session_index, vcl_get_worker_index ());
Florin Corasff40d8f2020-08-11 22:05:28 -0700504 vls_mt_table_runlock ();
Florin Coras2d675d72019-01-28 15:54:27 -0800505
506 return vlsh;
507}
508
Florin Corasf9240dc2019-01-15 08:03:17 -0800509u8
Florin Coras0ef8ef22019-01-18 08:37:13 -0800510vls_is_shared_by_wrk (vcl_locked_session_t * vls, u32 wrk_index)
Florin Corasf9240dc2019-01-15 08:03:17 -0800511{
Florin Coras243edd52020-03-04 22:20:12 +0000512 vls_shared_data_t *vls_shd;
Florin Coras0ef8ef22019-01-18 08:37:13 -0800513 int i;
Florin Coras243edd52020-03-04 22:20:12 +0000514
515 if (vls->shared_data_index == ~0)
516 return 0;
517
518 vls_shared_data_pool_rlock ();
519
520 vls_shd = vls_shared_data_get (vls->shared_data_index);
521 clib_spinlock_lock (&vls_shd->lock);
522
523 for (i = 0; i < vec_len (vls_shd->workers_subscribed); i++)
524 if (vls_shd->workers_subscribed[i] == wrk_index)
525 {
526 clib_spinlock_unlock (&vls_shd->lock);
527 vls_shared_data_pool_runlock ();
528 return 1;
529 }
530 clib_spinlock_unlock (&vls_shd->lock);
531
532 vls_shared_data_pool_runlock ();
Florin Coras0ef8ef22019-01-18 08:37:13 -0800533 return 0;
534}
535
Florin Coras2d675d72019-01-28 15:54:27 -0800536static void
537vls_listener_wrk_set (vcl_locked_session_t * vls, u32 wrk_index, u8 is_active)
538{
Florin Coras243edd52020-03-04 22:20:12 +0000539 vls_shared_data_t *vls_shd;
540
541 if (vls->shared_data_index == ~0)
542 {
543 clib_warning ("not a shared session");
544 return;
545 }
546
547 vls_shared_data_pool_rlock ();
548
549 vls_shd = vls_shared_data_get (vls->shared_data_index);
550
551 clib_spinlock_lock (&vls_shd->lock);
552 clib_bitmap_set (vls_shd->listeners, wrk_index, is_active);
553 clib_spinlock_unlock (&vls_shd->lock);
554
555 vls_shared_data_pool_runlock ();
556}
557
558static u32
559vls_shared_get_owner (vcl_locked_session_t * vls)
560{
561 vls_shared_data_t *vls_shd;
562 u32 owner_wrk;
563
564 vls_shared_data_pool_rlock ();
565
566 vls_shd = vls_shared_data_get (vls->shared_data_index);
567 owner_wrk = vls_shd->owner_wrk_index;
568
569 vls_shared_data_pool_runlock ();
570
571 return owner_wrk;
Florin Coras2d675d72019-01-28 15:54:27 -0800572}
573
574static u8
575vls_listener_wrk_is_active (vcl_locked_session_t * vls, u32 wrk_index)
576{
Florin Coras243edd52020-03-04 22:20:12 +0000577 vls_shared_data_t *vls_shd;
578 u8 is_set;
579
580 if (vls->shared_data_index == ~0)
581 {
582 clib_warning ("not a shared session");
583 return 0;
584 }
585
586 vls_shared_data_pool_rlock ();
587
588 vls_shd = vls_shared_data_get (vls->shared_data_index);
589
590 clib_spinlock_lock (&vls_shd->lock);
591 is_set = clib_bitmap_get (vls_shd->listeners, wrk_index);
592 clib_spinlock_unlock (&vls_shd->lock);
593
594 vls_shared_data_pool_runlock ();
595
596 return (is_set == 1);
Florin Coras2d675d72019-01-28 15:54:27 -0800597}
598
599static void
600vls_listener_wrk_start_listen (vcl_locked_session_t * vls, u32 wrk_index)
601{
602 vppcom_session_listen (vls_to_sh (vls), ~0);
603 vls_listener_wrk_set (vls, wrk_index, 1 /* is_active */ );
604}
605
606static void
607vls_listener_wrk_stop_listen (vcl_locked_session_t * vls, u32 wrk_index)
608{
609 vcl_worker_t *wrk;
610 vcl_session_t *s;
611
612 wrk = vcl_worker_get (wrk_index);
613 s = vcl_session_get (wrk, vls->session_index);
Florin Corasc127d5a2020-10-14 16:35:58 -0700614 if (s->session_state != VCL_STATE_LISTEN)
Florin Coras2d675d72019-01-28 15:54:27 -0800615 return;
Florin Coras458089b2019-08-21 16:20:44 -0700616 vcl_send_session_unlisten (wrk, s);
Florin Corasc127d5a2020-10-14 16:35:58 -0700617 s->session_state = VCL_STATE_LISTEN_NO_MQ;
Florin Coras2d675d72019-01-28 15:54:27 -0800618 vls_listener_wrk_set (vls, wrk_index, 0 /* is_active */ );
619}
620
Florin Coras243edd52020-03-04 22:20:12 +0000621static int
622vls_shared_data_subscriber_position (vls_shared_data_t * vls_shd,
623 u32 wrk_index)
624{
625 int i;
626
627 for (i = 0; i < vec_len (vls_shd->workers_subscribed); i++)
628 {
629 if (vls_shd->workers_subscribed[i] == wrk_index)
630 return i;
631 }
632 return -1;
633}
634
Florin Coras0ef8ef22019-01-18 08:37:13 -0800635int
636vls_unshare_session (vcl_locked_session_t * vls, vcl_worker_t * wrk)
637{
Florin Coras243edd52020-03-04 22:20:12 +0000638 vls_shared_data_t *vls_shd;
Florin Coras311817f2020-03-07 17:45:47 +0000639 int do_disconnect, pos;
640 u32 n_subscribers;
Florin Corasf9240dc2019-01-15 08:03:17 -0800641 vcl_session_t *s;
Florin Coras2d675d72019-01-28 15:54:27 -0800642
hanlina3a48962020-07-13 11:09:15 +0800643 if (vls->shared_data_index == ~0)
644 return 0;
Florin Coras243edd52020-03-04 22:20:12 +0000645
Florin Coras2d675d72019-01-28 15:54:27 -0800646 s = vcl_session_get (wrk, vls->session_index);
Florin Corasc127d5a2020-10-14 16:35:58 -0700647 if (s->session_state == VCL_STATE_LISTEN)
Florin Coras2d675d72019-01-28 15:54:27 -0800648 vls_listener_wrk_set (vls, wrk->wrk_index, 0 /* is_active */ );
Florin Corasf9240dc2019-01-15 08:03:17 -0800649
Florin Coras243edd52020-03-04 22:20:12 +0000650 vls_shared_data_pool_rlock ();
Florin Corasf9240dc2019-01-15 08:03:17 -0800651
Florin Coras243edd52020-03-04 22:20:12 +0000652 vls_shd = vls_shared_data_get (vls->shared_data_index);
653 clib_spinlock_lock (&vls_shd->lock);
654
655 pos = vls_shared_data_subscriber_position (vls_shd, wrk->wrk_index);
656 if (pos < 0)
657 {
658 clib_warning ("worker %u not subscribed for vls %u", wrk->wrk_index,
659 vls->worker_index);
660 goto done;
661 }
662
663 /*
664 * Unsubscribe from share data and fifos
665 */
666 if (s->rx_fifo)
667 {
668 svm_fifo_del_subscriber (s->rx_fifo, wrk->vpp_wrk_index);
669 svm_fifo_del_subscriber (s->tx_fifo, wrk->vpp_wrk_index);
670 }
671 vec_del1 (vls_shd->workers_subscribed, pos);
672
673 /*
674 * Cleanup vcl state
675 */
676 n_subscribers = vec_len (vls_shd->workers_subscribed);
Florin Corasc127d5a2020-10-14 16:35:58 -0700677 do_disconnect = s->session_state == VCL_STATE_LISTEN || !n_subscribers;
Florin Coras243edd52020-03-04 22:20:12 +0000678 vcl_session_cleanup (wrk, s, vcl_session_handle (s), do_disconnect);
679
680 /*
681 * No subscriber left, cleanup shared data
682 */
683 if (!n_subscribers)
684 {
685 u32 shd_index = vls_shared_data_index (vls_shd);
686
687 clib_spinlock_unlock (&vls_shd->lock);
688 vls_shared_data_pool_runlock ();
689
690 vls_shared_data_free (shd_index);
691
692 /* All locks have been dropped */
Florin Corasf9240dc2019-01-15 08:03:17 -0800693 return 0;
694 }
695
Florin Coras0ef8ef22019-01-18 08:37:13 -0800696 /* Return, if this is not the owning worker */
Florin Coras243edd52020-03-04 22:20:12 +0000697 if (vls_shd->owner_wrk_index != wrk->wrk_index)
698 goto done;
Florin Coras0ef8ef22019-01-18 08:37:13 -0800699
Florin Coras243edd52020-03-04 22:20:12 +0000700 ASSERT (vec_len (vls_shd->workers_subscribed));
701
702 /*
703 * Check if we can change owner or close
704 */
705 vls_shd->owner_wrk_index = vls_shd->workers_subscribed[0];
706 vcl_send_session_worker_update (wrk, s, vls_shd->owner_wrk_index);
707
708 /* XXX is this still needed? */
709 if (vec_len (vls_shd->workers_subscribed) > 1)
710 clib_warning ("more workers need to be updated");
711
712done:
713
714 clib_spinlock_unlock (&vls_shd->lock);
715 vls_shared_data_pool_runlock ();
Florin Corasf9240dc2019-01-15 08:03:17 -0800716
717 return 0;
718}
719
720void
Florin Coras40c07ce2020-07-16 20:46:17 -0700721vls_init_share_session (vls_worker_t * vls_wrk, vcl_locked_session_t * vls)
Florin Corasf9240dc2019-01-15 08:03:17 -0800722{
Florin Coras40c07ce2020-07-16 20:46:17 -0700723 vls_shared_data_t *vls_shd;
724
725 u32 vls_shd_index = vls_shared_data_alloc ();
726
727 vls_shared_data_pool_rlock ();
728
729 vls_shd = vls_shared_data_get (vls_shd_index);
730 vls_shd->owner_wrk_index = vls_wrk->wrk_index;
731 vls->shared_data_index = vls_shd_index;
732 vec_add1 (vls_shd->workers_subscribed, vls_wrk->wrk_index);
733
734 vls_shared_data_pool_runlock ();
735}
736
737void
738vls_share_session (vls_worker_t * vls_wrk, vcl_locked_session_t * vls)
739{
740 vcl_worker_t *vcl_wrk = vcl_worker_get (vls_wrk->wrk_index);
Florin Coras243edd52020-03-04 22:20:12 +0000741 vls_shared_data_t *vls_shd;
742 vcl_session_t *s;
Florin Corasf9240dc2019-01-15 08:03:17 -0800743
Florin Coras243edd52020-03-04 22:20:12 +0000744 s = vcl_session_get (vcl_wrk, vls->session_index);
745 if (!s)
746 {
Florin Coras40c07ce2020-07-16 20:46:17 -0700747 clib_warning ("wrk %u session %u vls %u NOT AVAILABLE",
748 vcl_wrk->wrk_index, vls->session_index, vls->vls_index);
Florin Coras243edd52020-03-04 22:20:12 +0000749 return;
750 }
751
Florin Coras40c07ce2020-07-16 20:46:17 -0700752 ASSERT (vls->shared_data_index != ~0);
753
Florin Coras243edd52020-03-04 22:20:12 +0000754 /* Reinit session lock */
755 clib_spinlock_init (&vls->lock);
756
Florin Coras40c07ce2020-07-16 20:46:17 -0700757 vls_shared_data_pool_rlock ();
Florin Coras243edd52020-03-04 22:20:12 +0000758
Florin Coras40c07ce2020-07-16 20:46:17 -0700759 vls_shd = vls_shared_data_get (vls->shared_data_index);
Florin Coras243edd52020-03-04 22:20:12 +0000760
761 clib_spinlock_lock (&vls_shd->lock);
Florin Coras243edd52020-03-04 22:20:12 +0000762 vec_add1 (vls_shd->workers_subscribed, vls_wrk->wrk_index);
Florin Coras243edd52020-03-04 22:20:12 +0000763 clib_spinlock_unlock (&vls_shd->lock);
Florin Coras40c07ce2020-07-16 20:46:17 -0700764
Florin Coras243edd52020-03-04 22:20:12 +0000765 vls_shared_data_pool_runlock ();
766
Florin Corasf9240dc2019-01-15 08:03:17 -0800767 if (s->rx_fifo)
768 {
Florin Coras243edd52020-03-04 22:20:12 +0000769 svm_fifo_add_subscriber (s->rx_fifo, vcl_wrk->vpp_wrk_index);
770 svm_fifo_add_subscriber (s->tx_fifo, vcl_wrk->vpp_wrk_index);
Florin Corasf9240dc2019-01-15 08:03:17 -0800771 }
Florin Corasc127d5a2020-10-14 16:35:58 -0700772 else if (s->session_state == VCL_STATE_LISTEN)
Florin Coras2d675d72019-01-28 15:54:27 -0800773 {
Florin Corasc127d5a2020-10-14 16:35:58 -0700774 s->session_state = VCL_STATE_LISTEN_NO_MQ;
Florin Coras2d675d72019-01-28 15:54:27 -0800775 }
Florin Coras243edd52020-03-04 22:20:12 +0000776}
Florin Coras2d675d72019-01-28 15:54:27 -0800777
Florin Coras243edd52020-03-04 22:20:12 +0000778static void
779vls_share_sessions (vls_worker_t * vls_parent_wrk, vls_worker_t * vls_wrk)
780{
Florin Coras40c07ce2020-07-16 20:46:17 -0700781 vcl_locked_session_t *vls, *parent_vls;
Florin Coras243edd52020-03-04 22:20:12 +0000782
783 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +0100784 pool_foreach (vls, vls_wrk->vls_pool) {
Florin Coras40c07ce2020-07-16 20:46:17 -0700785 /* Initialize sharing on parent session */
786 if (vls->shared_data_index == ~0)
787 {
788 parent_vls = vls_session_get (vls_parent_wrk, vls->vls_index);
789 vls_init_share_session (vls_parent_wrk, parent_vls);
790 vls->shared_data_index = parent_vls->shared_data_index;
791 }
792 vls_share_session (vls_wrk, vls);
Damjan Marionb2c31b62020-12-13 21:47:40 +0100793 }
Florin Coras243edd52020-03-04 22:20:12 +0000794 /* *INDENT-ON* */
Florin Corasf9240dc2019-01-15 08:03:17 -0800795}
796
797void
798vls_worker_copy_on_fork (vcl_worker_t * parent_wrk)
799{
Florin Coras243edd52020-03-04 22:20:12 +0000800 vls_worker_t *vls_wrk = vls_worker_get_current (), *vls_parent_wrk;
Florin Corasf9240dc2019-01-15 08:03:17 -0800801 vcl_worker_t *wrk = vcl_worker_get_current ();
hanlinf8e13632020-08-21 11:05:36 +0800802 u32 vls_index, session_index, wrk_index;
803 vcl_session_handle_t sh;
Florin Corasf9240dc2019-01-15 08:03:17 -0800804
Florin Coras243edd52020-03-04 22:20:12 +0000805 /*
806 * init vcl worker
807 */
Florin Corasf9240dc2019-01-15 08:03:17 -0800808 wrk->sessions = pool_dup (parent_wrk->sessions);
809 wrk->session_index_by_vpp_handles =
810 hash_dup (parent_wrk->session_index_by_vpp_handles);
811
Florin Coras243edd52020-03-04 22:20:12 +0000812 /*
813 * init vls worker
814 */
815 vls_parent_wrk = vls_worker_get (parent_wrk->wrk_index);
hanlinf8e13632020-08-21 11:05:36 +0800816 /* *INDENT-OFF* */
817 hash_foreach (sh, vls_index, vls_parent_wrk->session_handle_to_vlsh_table,
818 ({
819 vcl_session_handle_parse (sh, &wrk_index, &session_index);
820 hash_set (vls_wrk->session_handle_to_vlsh_table,
821 vcl_session_handle_from_index (session_index), vls_index);
822 }));
823 /* *INDENT-ON* */
Florin Coras243edd52020-03-04 22:20:12 +0000824 vls_wrk->vls_pool = pool_dup (vls_parent_wrk->vls_pool);
Florin Coras2d675d72019-01-28 15:54:27 -0800825
Florin Coras243edd52020-03-04 22:20:12 +0000826 vls_share_sessions (vls_parent_wrk, vls_wrk);
Florin Corasf9240dc2019-01-15 08:03:17 -0800827}
828
Florin Coras0ef8ef22019-01-18 08:37:13 -0800829static void
830vls_mt_acq_locks (vcl_locked_session_t * vls, vls_mt_ops_t op, int *locks_acq)
831{
832 vcl_worker_t *wrk = vcl_worker_get_current ();
833 vcl_session_t *s = 0;
834 int is_nonblk = 0;
835
836 if (vls)
837 {
838 s = vcl_session_get (wrk, vls->session_index);
839 if (PREDICT_FALSE (!s))
840 return;
Florin Corasac422d62020-10-19 20:51:36 -0700841 is_nonblk = vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK);
Florin Coras0ef8ef22019-01-18 08:37:13 -0800842 }
843
844 switch (op)
845 {
846 case VLS_MT_OP_READ:
847 if (!is_nonblk)
848 is_nonblk = vcl_session_read_ready (s) != 0;
849 if (!is_nonblk)
850 {
851 vls_mt_mq_lock ();
852 *locks_acq |= VLS_MT_LOCK_MQ;
853 }
854 break;
855 case VLS_MT_OP_WRITE:
Florin Coras78b5fa62019-02-21 20:04:15 -0800856 ASSERT (s);
Florin Coras0ef8ef22019-01-18 08:37:13 -0800857 if (!is_nonblk)
858 is_nonblk = vcl_session_write_ready (s) != 0;
859 if (!is_nonblk)
860 {
861 vls_mt_mq_lock ();
862 *locks_acq |= VLS_MT_LOCK_MQ;
863 }
864 break;
865 case VLS_MT_OP_XPOLL:
866 vls_mt_mq_lock ();
867 *locks_acq |= VLS_MT_LOCK_MQ;
868 break;
869 case VLS_MT_OP_SPOOL:
870 vls_mt_spool_lock ();
871 *locks_acq |= VLS_MT_LOCK_SPOOL;
872 break;
873 default:
874 break;
875 }
876}
877
878static void
879vls_mt_rel_locks (int locks_acq)
880{
881 if (locks_acq & VLS_MT_LOCK_MQ)
882 vls_mt_mq_unlock ();
883 if (locks_acq & VLS_MT_LOCK_SPOOL)
884 vls_mt_create_unlock ();
885}
886
Florin Corasff40d8f2020-08-11 22:05:28 -0700887static inline u8
888vls_mt_session_should_migrate (vcl_locked_session_t * vls)
889{
890 return (vls_mt_wrk_supported ()
891 && vls->worker_index != vcl_get_worker_index ());
892}
893
wanghanlindcacdc42020-12-28 16:19:05 +0800894static vcl_locked_session_t *
895vls_mt_session_migrate (vcl_locked_session_t *vls)
hanlina3a48962020-07-13 11:09:15 +0800896{
897 u32 wrk_index = vcl_get_worker_index ();
898 vcl_worker_t *wrk;
wanghanline8f848a2021-01-08 14:57:11 +0800899 vls_worker_t *vls_wrk = vls_worker_get_current ();
wanghanlindcacdc42020-12-28 16:19:05 +0800900 u32 src_sid, sid, vls_index, own_vcl_wrk_index;
hanlina3a48962020-07-13 11:09:15 +0800901 vcl_session_t *session;
902 uword *p;
903
Florin Corasff40d8f2020-08-11 22:05:28 -0700904 ASSERT (vls_mt_wrk_supported () && vls->worker_index != wrk_index);
hanlina3a48962020-07-13 11:09:15 +0800905
Florin Corasff40d8f2020-08-11 22:05:28 -0700906 /*
907 * VCL session on current vcl worker already allocated. Update current
908 * owner worker and index and return
909 */
hanlina3a48962020-07-13 11:09:15 +0800910 if ((p = hash_get (vls->vcl_wrk_index_to_session_index, wrk_index)))
911 {
912 vls->worker_index = wrk_index;
913 vls->session_index = (u32) p[0];
wanghanlindcacdc42020-12-28 16:19:05 +0800914 return vls;
hanlina3a48962020-07-13 11:09:15 +0800915 }
916
Florin Corasff40d8f2020-08-11 22:05:28 -0700917 /*
918 * Ask vcl worker that owns the original vcl session to clone it into
919 * current vcl worker session pool
920 */
921
hanlina3a48962020-07-13 11:09:15 +0800922 if (!(p = hash_get (vls->vcl_wrk_index_to_session_index,
923 vls->owner_vcl_wrk_index)))
924 {
925 VERR ("session in owner worker(%u) is free", vls->owner_vcl_wrk_index);
926 ASSERT (0);
wanghanlindcacdc42020-12-28 16:19:05 +0800927 vls_unlock (vls);
928 vls_mt_table_runlock ();
929 return 0;
hanlina3a48962020-07-13 11:09:15 +0800930 }
931
932 src_sid = (u32) p[0];
933 wrk = vcl_worker_get_current ();
934 session = vcl_session_alloc (wrk);
935 sid = session->session_index;
hanlina3a48962020-07-13 11:09:15 +0800936 VDBG (1, "migrate session of worker (session): %u (%u) -> %u (%u)",
937 vls->owner_vcl_wrk_index, src_sid, wrk_index, sid);
938
wanghanlindcacdc42020-12-28 16:19:05 +0800939 /* Drop lock to prevent dead lock when dst wrk trying to get lock. */
940 vls_index = vls->vls_index;
941 own_vcl_wrk_index = vls->owner_vcl_wrk_index;
942 vls_unlock (vls);
943 vls_mt_table_runlock ();
944 vls_send_clone_and_share_rpc (wrk, vls_index, sid, vls_get_worker_index (),
945 own_vcl_wrk_index, vls_index, src_sid);
946
947 if (PREDICT_FALSE (wrk->rpc_done == VLS_RPC_STATE_SESSION_NOT_EXIST))
hanlina3a48962020-07-13 11:09:15 +0800948 {
wanghanlindcacdc42020-12-28 16:19:05 +0800949 VWRN ("session %u not exist", src_sid);
950 goto err;
951 }
952 else if (PREDICT_FALSE (wrk->rpc_done == VLS_RPC_STATE_INIT))
953 {
954 VWRN ("failed to wait rpc response");
955 goto err;
956 }
957 else if (PREDICT_FALSE ((session->flags & VCL_SESSION_F_IS_VEP) &&
958 session->vep.next_sh != ~0))
959 {
hanlina3a48962020-07-13 11:09:15 +0800960 VERR ("can't migrate nonempty epoll session");
961 ASSERT (0);
wanghanlindcacdc42020-12-28 16:19:05 +0800962 goto err;
hanlina3a48962020-07-13 11:09:15 +0800963 }
Florin Coras6c3b2182020-10-19 18:36:48 -0700964 else if (PREDICT_FALSE (!(session->flags & VCL_SESSION_F_IS_VEP) &&
Florin Corasc127d5a2020-10-14 16:35:58 -0700965 session->session_state != VCL_STATE_CLOSED))
hanlina3a48962020-07-13 11:09:15 +0800966 {
hanlina3a48962020-07-13 11:09:15 +0800967 VERR ("migrate NOT supported, session_status (%u)",
968 session->session_state);
969 ASSERT (0);
wanghanlindcacdc42020-12-28 16:19:05 +0800970 goto err;
hanlina3a48962020-07-13 11:09:15 +0800971 }
wanghanlindcacdc42020-12-28 16:19:05 +0800972
973 vls = vls_get_w_dlock (vls_index);
974 if (PREDICT_FALSE (!vls))
975 {
976 VWRN ("failed to get vls %u", vls_index);
977 goto err;
978 }
979
980 session->session_index = sid;
981 vls->worker_index = wrk_index;
982 vls->session_index = sid;
983 hash_set (vls->vcl_wrk_index_to_session_index, wrk_index, sid);
wanghanline8f848a2021-01-08 14:57:11 +0800984 vls_sh_to_vlsh_table_add (vls_wrk, vcl_session_handle (session),
985 vls->vls_index);
wanghanlindcacdc42020-12-28 16:19:05 +0800986 return vls;
987
988err:
989 vcl_session_free (wrk, session);
990 return 0;
hanlina3a48962020-07-13 11:09:15 +0800991}
992
Florin Corasff40d8f2020-08-11 22:05:28 -0700993static inline void
994vls_mt_detect (void)
995{
996 if (PREDICT_FALSE (vcl_get_worker_index () == ~0))
997 vls_mt_add ();
998}
Florin Coras0ef8ef22019-01-18 08:37:13 -0800999
wanghanlindcacdc42020-12-28 16:19:05 +08001000#define vls_mt_guard(_vls, _op) \
1001 int _locks_acq = 0; \
1002 if (vls_mt_wrk_supported ()) \
1003 { \
1004 if (PREDICT_FALSE (_vls && \
1005 ((vcl_locked_session_t *) _vls)->worker_index != \
1006 vcl_get_worker_index ())) \
1007 { \
1008 _vls = vls_mt_session_migrate (_vls); \
1009 if (PREDICT_FALSE (!_vls)) \
1010 return VPPCOM_EBADFD; \
1011 } \
1012 } \
1013 else \
1014 { \
1015 if (PREDICT_FALSE (vlsl->vls_mt_n_threads > 1)) \
1016 vls_mt_acq_locks (_vls, _op, &_locks_acq); \
1017 }
Florin Corasff40d8f2020-08-11 22:05:28 -07001018
1019#define vls_mt_unguard() \
1020 if (PREDICT_FALSE (_locks_acq)) \
Florin Coras0ef8ef22019-01-18 08:37:13 -08001021 vls_mt_rel_locks (_locks_acq)
1022
Florin Coras7baeb712019-01-04 17:05:43 -08001023int
1024vls_write (vls_handle_t vlsh, void *buf, size_t nbytes)
1025{
1026 vcl_locked_session_t *vls;
1027 int rv;
1028
Florin Corasff40d8f2020-08-11 22:05:28 -07001029 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001030 if (!(vls = vls_get_w_dlock (vlsh)))
1031 return VPPCOM_EBADFD;
Florin Coras0ef8ef22019-01-18 08:37:13 -08001032
1033 vls_mt_guard (vls, VLS_MT_OP_WRITE);
Florin Coras7baeb712019-01-04 17:05:43 -08001034 rv = vppcom_session_write (vls_to_sh_tu (vls), buf, nbytes);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001035 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001036 vls_get_and_unlock (vlsh);
1037 return rv;
1038}
1039
1040int
1041vls_write_msg (vls_handle_t vlsh, void *buf, size_t nbytes)
1042{
1043 vcl_locked_session_t *vls;
1044 int rv;
1045
Florin Corasff40d8f2020-08-11 22:05:28 -07001046 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001047 if (!(vls = vls_get_w_dlock (vlsh)))
1048 return VPPCOM_EBADFD;
Florin Coras0ef8ef22019-01-18 08:37:13 -08001049 vls_mt_guard (vls, VLS_MT_OP_WRITE);
Florin Coras7baeb712019-01-04 17:05:43 -08001050 rv = vppcom_session_write_msg (vls_to_sh_tu (vls), buf, nbytes);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001051 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001052 vls_get_and_unlock (vlsh);
1053 return rv;
1054}
1055
1056int
1057vls_sendto (vls_handle_t vlsh, void *buf, int buflen, int flags,
1058 vppcom_endpt_t * ep)
1059{
1060 vcl_locked_session_t *vls;
1061 int rv;
1062
Florin Corasff40d8f2020-08-11 22:05:28 -07001063 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001064 if (!(vls = vls_get_w_dlock (vlsh)))
1065 return VPPCOM_EBADFD;
Florin Coras0ef8ef22019-01-18 08:37:13 -08001066 vls_mt_guard (vls, VLS_MT_OP_WRITE);
Florin Coras7baeb712019-01-04 17:05:43 -08001067 rv = vppcom_session_sendto (vls_to_sh_tu (vls), buf, buflen, flags, ep);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001068 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001069 vls_get_and_unlock (vlsh);
1070 return rv;
1071}
1072
1073ssize_t
1074vls_read (vls_handle_t vlsh, void *buf, size_t nbytes)
1075{
1076 vcl_locked_session_t *vls;
1077 int rv;
1078
Florin Corasff40d8f2020-08-11 22:05:28 -07001079 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001080 if (!(vls = vls_get_w_dlock (vlsh)))
1081 return VPPCOM_EBADFD;
Florin Coras0ef8ef22019-01-18 08:37:13 -08001082 vls_mt_guard (vls, VLS_MT_OP_READ);
Florin Coras7baeb712019-01-04 17:05:43 -08001083 rv = vppcom_session_read (vls_to_sh_tu (vls), buf, nbytes);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001084 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001085 vls_get_and_unlock (vlsh);
1086 return rv;
1087}
1088
1089ssize_t
1090vls_recvfrom (vls_handle_t vlsh, void *buffer, uint32_t buflen, int flags,
1091 vppcom_endpt_t * ep)
1092{
1093 vcl_locked_session_t *vls;
1094 int rv;
1095
Florin Corasff40d8f2020-08-11 22:05:28 -07001096 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001097 if (!(vls = vls_get_w_dlock (vlsh)))
1098 return VPPCOM_EBADFD;
Florin Coras0ef8ef22019-01-18 08:37:13 -08001099 vls_mt_guard (vls, VLS_MT_OP_READ);
Florin Coras7baeb712019-01-04 17:05:43 -08001100 rv = vppcom_session_recvfrom (vls_to_sh_tu (vls), buffer, buflen, flags,
1101 ep);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001102 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001103 vls_get_and_unlock (vlsh);
1104 return rv;
1105}
1106
1107int
1108vls_attr (vls_handle_t vlsh, uint32_t op, void *buffer, uint32_t * buflen)
1109{
1110 vcl_locked_session_t *vls;
1111 int rv;
1112
Florin Corasff40d8f2020-08-11 22:05:28 -07001113 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001114 if (!(vls = vls_get_w_dlock (vlsh)))
1115 return VPPCOM_EBADFD;
Florin Corasff40d8f2020-08-11 22:05:28 -07001116 if (vls_mt_session_should_migrate (vls))
wanghanlindcacdc42020-12-28 16:19:05 +08001117 {
1118 vls = vls_mt_session_migrate (vls);
1119 if (PREDICT_FALSE (!vls))
1120 return VPPCOM_EBADFD;
1121 }
Florin Coras7baeb712019-01-04 17:05:43 -08001122 rv = vppcom_session_attr (vls_to_sh_tu (vls), op, buffer, buflen);
1123 vls_get_and_unlock (vlsh);
1124 return rv;
1125}
1126
1127int
1128vls_bind (vls_handle_t vlsh, vppcom_endpt_t * ep)
1129{
1130 vcl_locked_session_t *vls;
1131 int rv;
1132
Florin Corasff40d8f2020-08-11 22:05:28 -07001133 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001134 if (!(vls = vls_get_w_dlock (vlsh)))
1135 return VPPCOM_EBADFD;
1136 rv = vppcom_session_bind (vls_to_sh_tu (vls), ep);
1137 vls_get_and_unlock (vlsh);
1138 return rv;
1139}
1140
1141int
1142vls_listen (vls_handle_t vlsh, int q_len)
1143{
1144 vcl_locked_session_t *vls;
1145 int rv;
1146
Florin Corasff40d8f2020-08-11 22:05:28 -07001147 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001148 if (!(vls = vls_get_w_dlock (vlsh)))
1149 return VPPCOM_EBADFD;
Florin Coras0ef8ef22019-01-18 08:37:13 -08001150 vls_mt_guard (vls, VLS_MT_OP_XPOLL);
Florin Coras7baeb712019-01-04 17:05:43 -08001151 rv = vppcom_session_listen (vls_to_sh_tu (vls), q_len);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001152 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001153 vls_get_and_unlock (vlsh);
1154 return rv;
1155}
1156
1157int
1158vls_connect (vls_handle_t vlsh, vppcom_endpt_t * server_ep)
1159{
1160 vcl_locked_session_t *vls;
1161 int rv;
1162
Florin Corasff40d8f2020-08-11 22:05:28 -07001163 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001164 if (!(vls = vls_get_w_dlock (vlsh)))
1165 return VPPCOM_EBADFD;
Florin Coras0ef8ef22019-01-18 08:37:13 -08001166 vls_mt_guard (vls, VLS_MT_OP_XPOLL);
Florin Coras7baeb712019-01-04 17:05:43 -08001167 rv = vppcom_session_connect (vls_to_sh_tu (vls), server_ep);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001168 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001169 vls_get_and_unlock (vlsh);
1170 return rv;
1171}
1172
Florin Coras2d675d72019-01-28 15:54:27 -08001173static inline void
1174vls_mp_checks (vcl_locked_session_t * vls, int is_add)
1175{
1176 vcl_worker_t *wrk = vcl_worker_get_current ();
1177 vcl_session_t *s;
Florin Coras243edd52020-03-04 22:20:12 +00001178 u32 owner_wrk;
Florin Coras2d675d72019-01-28 15:54:27 -08001179
hanlina3a48962020-07-13 11:09:15 +08001180 if (vls_mt_wrk_supported ())
1181 return;
1182
Florin Coras2d675d72019-01-28 15:54:27 -08001183 s = vcl_session_get (wrk, vls->session_index);
1184 switch (s->session_state)
1185 {
Florin Corasc127d5a2020-10-14 16:35:58 -07001186 case VCL_STATE_LISTEN:
Florin Coras2d675d72019-01-28 15:54:27 -08001187 if (is_add)
1188 {
Florin Coras243edd52020-03-04 22:20:12 +00001189 vls_listener_wrk_set (vls, vls->worker_index, 1 /* is_active */ );
Florin Coras2d675d72019-01-28 15:54:27 -08001190 break;
1191 }
1192 vls_listener_wrk_stop_listen (vls, vls->worker_index);
1193 break;
Florin Corasc127d5a2020-10-14 16:35:58 -07001194 case VCL_STATE_LISTEN_NO_MQ:
Florin Coras2d675d72019-01-28 15:54:27 -08001195 if (!is_add)
1196 break;
1197
1198 /* Register worker as listener */
1199 vls_listener_wrk_start_listen (vls, wrk->wrk_index);
1200
1201 /* If owner worker did not attempt to accept/xpoll on the session,
1202 * force a listen stop for it, since it may not be interested in
1203 * accepting new sessions.
1204 * This is pretty much a hack done to give app workers the illusion
1205 * that it is fine to listen and not accept new sessions for a
1206 * given listener. Without it, we would accumulate unhandled
1207 * accepts on the passive worker message queue. */
Florin Coras243edd52020-03-04 22:20:12 +00001208 owner_wrk = vls_shared_get_owner (vls);
1209 if (!vls_listener_wrk_is_active (vls, owner_wrk))
1210 vls_listener_wrk_stop_listen (vls, owner_wrk);
Florin Coras2d675d72019-01-28 15:54:27 -08001211 break;
1212 default:
1213 break;
1214 }
1215}
1216
Florin Coras7baeb712019-01-04 17:05:43 -08001217vls_handle_t
1218vls_accept (vls_handle_t listener_vlsh, vppcom_endpt_t * ep, int flags)
1219{
1220 vls_handle_t accepted_vlsh;
1221 vcl_locked_session_t *vls;
1222 int sh;
1223
Florin Corasff40d8f2020-08-11 22:05:28 -07001224 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001225 if (!(vls = vls_get_w_dlock (listener_vlsh)))
1226 return VPPCOM_EBADFD;
Florin Coras2d675d72019-01-28 15:54:27 -08001227 if (vcl_n_workers () > 1)
1228 vls_mp_checks (vls, 1 /* is_add */ );
Florin Coras0ef8ef22019-01-18 08:37:13 -08001229 vls_mt_guard (vls, VLS_MT_OP_SPOOL);
Florin Coras7baeb712019-01-04 17:05:43 -08001230 sh = vppcom_session_accept (vls_to_sh_tu (vls), ep, flags);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001231 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001232 vls_get_and_unlock (listener_vlsh);
1233 if (sh < 0)
1234 return sh;
1235 accepted_vlsh = vls_alloc (sh);
1236 if (PREDICT_FALSE (accepted_vlsh == VLS_INVALID_HANDLE))
1237 vppcom_session_close (sh);
1238 return accepted_vlsh;
1239}
1240
1241vls_handle_t
1242vls_create (uint8_t proto, uint8_t is_nonblocking)
1243{
1244 vcl_session_handle_t sh;
1245 vls_handle_t vlsh;
wanghanlindcacdc42020-12-28 16:19:05 +08001246 vcl_locked_session_t *vls = NULL;
Florin Coras7baeb712019-01-04 17:05:43 -08001247
Florin Corasff40d8f2020-08-11 22:05:28 -07001248 vls_mt_detect ();
wanghanlindcacdc42020-12-28 16:19:05 +08001249 vls_mt_guard (vls, VLS_MT_OP_SPOOL);
Florin Coras7baeb712019-01-04 17:05:43 -08001250 sh = vppcom_session_create (proto, is_nonblocking);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001251 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001252 if (sh == INVALID_SESSION_ID)
1253 return VLS_INVALID_HANDLE;
1254
1255 vlsh = vls_alloc (sh);
1256 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
1257 vppcom_session_close (sh);
1258
1259 return vlsh;
1260}
1261
hanlina3a48962020-07-13 11:09:15 +08001262static void
Florin Corasff40d8f2020-08-11 22:05:28 -07001263vls_mt_session_cleanup (vcl_locked_session_t * vls)
hanlina3a48962020-07-13 11:09:15 +08001264{
Florin Corasff40d8f2020-08-11 22:05:28 -07001265 u32 session_index, wrk_index, current_vcl_wrk;
hanlina3a48962020-07-13 11:09:15 +08001266 vcl_worker_t *wrk = vcl_worker_get_current ();
1267
Florin Corasff40d8f2020-08-11 22:05:28 -07001268 ASSERT (vls_mt_wrk_supported ());
1269
1270 current_vcl_wrk = vcl_get_worker_index ();
hanlina3a48962020-07-13 11:09:15 +08001271
1272 /* *INDENT-OFF* */
1273 hash_foreach (wrk_index, session_index, vls->vcl_wrk_index_to_session_index,
1274 ({
Florin Corasff40d8f2020-08-11 22:05:28 -07001275 if (current_vcl_wrk != wrk_index)
1276 vls_send_session_cleanup_rpc (wrk, wrk_index, session_index);
hanlina3a48962020-07-13 11:09:15 +08001277 }));
1278 /* *INDENT-ON* */
1279 hash_free (vls->vcl_wrk_index_to_session_index);
1280}
1281
Florin Coras7baeb712019-01-04 17:05:43 -08001282int
1283vls_close (vls_handle_t vlsh)
1284{
1285 vcl_locked_session_t *vls;
Florin Corasf9240dc2019-01-15 08:03:17 -08001286 int rv;
Florin Coras7baeb712019-01-04 17:05:43 -08001287
Florin Corasff40d8f2020-08-11 22:05:28 -07001288 vls_mt_detect ();
1289 vls_mt_table_wlock ();
Florin Coras7baeb712019-01-04 17:05:43 -08001290
Florin Coras0ef8ef22019-01-18 08:37:13 -08001291 vls = vls_get_and_lock (vlsh);
1292 if (!vls)
1293 {
Florin Corasff40d8f2020-08-11 22:05:28 -07001294 vls_mt_table_wunlock ();
Florin Coras0ef8ef22019-01-18 08:37:13 -08001295 return VPPCOM_EBADFD;
1296 }
1297
hanlina3a48962020-07-13 11:09:15 +08001298 vls_mt_guard (vls, VLS_MT_OP_SPOOL);
Florin Corasf9240dc2019-01-15 08:03:17 -08001299
Florin Coras243edd52020-03-04 22:20:12 +00001300 if (vls_is_shared (vls))
1301 rv = vls_unshare_session (vls, vcl_worker_get_current ());
1302 else
1303 rv = vppcom_session_close (vls_to_sh (vls));
1304
Florin Corasff40d8f2020-08-11 22:05:28 -07001305 if (vls_mt_wrk_supported ())
1306 vls_mt_session_cleanup (vls);
hanlina3a48962020-07-13 11:09:15 +08001307
Florin Coras0ef8ef22019-01-18 08:37:13 -08001308 vls_free (vls);
1309 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001310
Florin Corasff40d8f2020-08-11 22:05:28 -07001311 vls_mt_table_wunlock ();
Florin Coras0ef8ef22019-01-18 08:37:13 -08001312
Florin Coras7baeb712019-01-04 17:05:43 -08001313 return rv;
1314}
1315
liuyacan534468e2021-05-09 03:50:40 +00001316int
liuyacan55c952e2021-06-13 14:54:55 +08001317vls_shutdown (vls_handle_t vlsh, int how)
liuyacan534468e2021-05-09 03:50:40 +00001318{
1319 vcl_locked_session_t *vls;
1320 int rv;
1321
1322 vls_mt_detect ();
1323 if (!(vls = vls_get_w_dlock (vlsh)))
1324 return VPPCOM_EBADFD;
1325
1326 vls_mt_guard (vls, VLS_MT_OP_SPOOL);
liuyacan55c952e2021-06-13 14:54:55 +08001327 rv = vppcom_session_shutdown (vls_to_sh (vls), how);
liuyacan534468e2021-05-09 03:50:40 +00001328 vls_mt_unguard ();
1329 vls_get_and_unlock (vlsh);
1330
1331 return rv;
1332}
1333
Florin Coras7baeb712019-01-04 17:05:43 -08001334vls_handle_t
1335vls_epoll_create (void)
1336{
1337 vcl_session_handle_t sh;
1338 vls_handle_t vlsh;
1339
Florin Corasff40d8f2020-08-11 22:05:28 -07001340 vls_mt_detect ();
Florin Coras63d3ac62019-03-29 08:29:25 -07001341
Florin Coras7baeb712019-01-04 17:05:43 -08001342 sh = vppcom_epoll_create ();
1343 if (sh == INVALID_SESSION_ID)
1344 return VLS_INVALID_HANDLE;
1345
1346 vlsh = vls_alloc (sh);
1347 if (vlsh == VLS_INVALID_HANDLE)
1348 vppcom_session_close (sh);
1349
1350 return vlsh;
1351}
1352
Florin Coras2d675d72019-01-28 15:54:27 -08001353static void
1354vls_epoll_ctl_mp_checks (vcl_locked_session_t * vls, int op)
1355{
nandfandc2632e2021-03-26 16:46:58 +08001356 if (vcl_n_workers () <= 1 || op == EPOLL_CTL_MOD)
Florin Coras2d675d72019-01-28 15:54:27 -08001357 return;
1358
Florin Coras2d675d72019-01-28 15:54:27 -08001359 vls_mp_checks (vls, op == EPOLL_CTL_ADD);
1360}
1361
Florin Coras7baeb712019-01-04 17:05:43 -08001362int
1363vls_epoll_ctl (vls_handle_t ep_vlsh, int op, vls_handle_t vlsh,
1364 struct epoll_event *event)
1365{
1366 vcl_locked_session_t *ep_vls, *vls;
1367 vcl_session_handle_t ep_sh, sh;
1368 int rv;
1369
Florin Corasff40d8f2020-08-11 22:05:28 -07001370 vls_mt_detect ();
1371 vls_mt_table_rlock ();
Florin Coras7baeb712019-01-04 17:05:43 -08001372 ep_vls = vls_get_and_lock (ep_vlsh);
Florin Corasff40d8f2020-08-11 22:05:28 -07001373
1374 if (vls_mt_session_should_migrate (ep_vls))
wanghanlindcacdc42020-12-28 16:19:05 +08001375 {
1376 ep_vls = vls_mt_session_migrate (ep_vls);
1377 if (PREDICT_FALSE (!ep_vls))
1378 return VPPCOM_EBADFD;
1379 }
Florin Corasff40d8f2020-08-11 22:05:28 -07001380
Florin Coras7baeb712019-01-04 17:05:43 -08001381 ep_sh = vls_to_sh (ep_vls);
wanghanlindcacdc42020-12-28 16:19:05 +08001382 vls = vls_get_and_lock (vlsh);
Florin Coras7baeb712019-01-04 17:05:43 -08001383 sh = vls_to_sh (vls);
Florin Coras2d675d72019-01-28 15:54:27 -08001384
nandfandc2632e2021-03-26 16:46:58 +08001385 vls_epoll_ctl_mp_checks (vls, op);
Florin Corasff40d8f2020-08-11 22:05:28 -07001386 vls_mt_table_runlock ();
Florin Coras7baeb712019-01-04 17:05:43 -08001387 rv = vppcom_epoll_ctl (ep_sh, op, sh, event);
1388
Florin Corasff40d8f2020-08-11 22:05:28 -07001389 vls_mt_table_rlock ();
Florin Coras7baeb712019-01-04 17:05:43 -08001390 ep_vls = vls_get (ep_vlsh);
1391 vls = vls_get (vlsh);
1392 vls_unlock (vls);
1393 vls_unlock (ep_vls);
Florin Corasff40d8f2020-08-11 22:05:28 -07001394 vls_mt_table_runlock ();
Florin Coras7baeb712019-01-04 17:05:43 -08001395 return rv;
1396}
1397
1398int
1399vls_epoll_wait (vls_handle_t ep_vlsh, struct epoll_event *events,
1400 int maxevents, double wait_for_time)
1401{
wanghanlindcacdc42020-12-28 16:19:05 +08001402 vcl_locked_session_t *vls, *vls_tmp = NULL;
Florin Coras7baeb712019-01-04 17:05:43 -08001403 int rv;
1404
Florin Corasff40d8f2020-08-11 22:05:28 -07001405 vls_mt_detect ();
Florin Coras7baeb712019-01-04 17:05:43 -08001406 if (!(vls = vls_get_w_dlock (ep_vlsh)))
1407 return VPPCOM_EBADFD;
wanghanlindcacdc42020-12-28 16:19:05 +08001408 vls_mt_guard (vls_tmp, VLS_MT_OP_XPOLL);
Florin Coras7baeb712019-01-04 17:05:43 -08001409 rv = vppcom_epoll_wait (vls_to_sh_tu (vls), events, maxevents,
1410 wait_for_time);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001411 vls_mt_unguard ();
Florin Coras7baeb712019-01-04 17:05:43 -08001412 vls_get_and_unlock (ep_vlsh);
1413 return rv;
1414}
1415
Florin Coras2d675d72019-01-28 15:54:27 -08001416static void
1417vls_select_mp_checks (vcl_si_set * read_map)
1418{
1419 vcl_locked_session_t *vls;
1420 vcl_worker_t *wrk;
1421 vcl_session_t *s;
1422 u32 si;
1423
1424 if (vcl_n_workers () <= 1)
1425 {
1426 vlsl->select_mp_check = 1;
1427 return;
1428 }
1429
1430 if (!read_map)
1431 return;
1432
1433 vlsl->select_mp_check = 1;
1434 wrk = vcl_worker_get_current ();
1435
1436 /* *INDENT-OFF* */
Damjan Marionf0ca1e82020-12-13 23:26:56 +01001437 clib_bitmap_foreach (si, read_map) {
Florin Coras2d675d72019-01-28 15:54:27 -08001438 s = vcl_session_get (wrk, si);
Florin Corasc127d5a2020-10-14 16:35:58 -07001439 if (s->session_state == VCL_STATE_LISTEN)
Florin Coras2d675d72019-01-28 15:54:27 -08001440 {
1441 vls = vls_get (vls_session_index_to_vlsh (si));
1442 vls_mp_checks (vls, 1 /* is_add */);
1443 }
Damjan Marionf0ca1e82020-12-13 23:26:56 +01001444 }
Florin Coras2d675d72019-01-28 15:54:27 -08001445 /* *INDENT-ON* */
1446}
1447
Florin Coras0ef8ef22019-01-18 08:37:13 -08001448int
1449vls_select (int n_bits, vcl_si_set * read_map, vcl_si_set * write_map,
1450 vcl_si_set * except_map, double wait_for_time)
1451{
1452 int rv;
wanghanlindcacdc42020-12-28 16:19:05 +08001453 vcl_locked_session_t *vls = NULL;
Florin Coras2d675d72019-01-28 15:54:27 -08001454
Florin Corasff40d8f2020-08-11 22:05:28 -07001455 vls_mt_detect ();
wanghanlindcacdc42020-12-28 16:19:05 +08001456 vls_mt_guard (vls, VLS_MT_OP_XPOLL);
Florin Coras2d675d72019-01-28 15:54:27 -08001457 if (PREDICT_FALSE (!vlsl->select_mp_check))
1458 vls_select_mp_checks (read_map);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001459 rv = vppcom_select (n_bits, read_map, write_map, except_map, wait_for_time);
1460 vls_mt_unguard ();
1461 return rv;
1462}
1463
Florin Corasf9240dc2019-01-15 08:03:17 -08001464static void
Florin Coras0ef8ef22019-01-18 08:37:13 -08001465vls_unshare_vcl_worker_sessions (vcl_worker_t * wrk)
1466{
1467 u32 current_wrk, is_current;
1468 vcl_locked_session_t *vls;
1469 vcl_session_t *s;
1470
Florin Coras14ed6df2019-03-06 21:13:42 -08001471 if (pool_elts (vcm->workers) <= 1)
1472 return;
1473
Florin Coras0ef8ef22019-01-18 08:37:13 -08001474 current_wrk = vcl_get_worker_index ();
1475 is_current = current_wrk == wrk->wrk_index;
Florin Coras0ef8ef22019-01-18 08:37:13 -08001476
1477 /* *INDENT-OFF* */
Damjan Marionb2c31b62020-12-13 21:47:40 +01001478 pool_foreach (s, wrk->sessions) {
hanlinf8e13632020-08-21 11:05:36 +08001479 vls = vls_get (vls_si_wi_to_vlsh (s->session_index, wrk->wrk_index));
Florin Coras0ef8ef22019-01-18 08:37:13 -08001480 if (vls && (is_current || vls_is_shared_by_wrk (vls, current_wrk)))
1481 vls_unshare_session (vls, wrk);
Damjan Marionb2c31b62020-12-13 21:47:40 +01001482 }
Florin Coras0ef8ef22019-01-18 08:37:13 -08001483 /* *INDENT-ON* */
Florin Coras0ef8ef22019-01-18 08:37:13 -08001484}
1485
1486static void
1487vls_cleanup_vcl_worker (vcl_worker_t * wrk)
1488{
Florin Coras243edd52020-03-04 22:20:12 +00001489 vls_worker_t *vls_wrk = vls_worker_get (wrk->wrk_index);
1490
Florin Coras0ef8ef22019-01-18 08:37:13 -08001491 /* Unshare sessions and also cleanup worker since child may have
1492 * called _exit () and therefore vcl may not catch the event */
1493 vls_unshare_vcl_worker_sessions (wrk);
1494 vcl_worker_cleanup (wrk, 1 /* notify vpp */ );
Florin Coras243edd52020-03-04 22:20:12 +00001495
1496 vls_worker_free (vls_wrk);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001497}
1498
1499static void
Florin Corasf9240dc2019-01-15 08:03:17 -08001500vls_cleanup_forked_child (vcl_worker_t * wrk, vcl_worker_t * child_wrk)
1501{
1502 vcl_worker_t *sub_child;
1503 int tries = 0;
1504
1505 if (child_wrk->forked_child != ~0)
1506 {
1507 sub_child = vcl_worker_get_if_valid (child_wrk->forked_child);
1508 if (sub_child)
1509 {
1510 /* Wait a bit, maybe the process is going away */
1511 while (kill (sub_child->current_pid, 0) >= 0 && tries++ < 50)
1512 usleep (1e3);
1513 if (kill (sub_child->current_pid, 0) < 0)
1514 vls_cleanup_forked_child (child_wrk, sub_child);
1515 }
1516 }
Florin Coras0ef8ef22019-01-18 08:37:13 -08001517 vls_cleanup_vcl_worker (child_wrk);
1518 VDBG (0, "Cleaned up forked child wrk %u", child_wrk->wrk_index);
Florin Corasf9240dc2019-01-15 08:03:17 -08001519 wrk->forked_child = ~0;
1520}
1521
1522static struct sigaction old_sa;
1523
1524static void
1525vls_intercept_sigchld_handler (int signum, siginfo_t * si, void *uc)
1526{
1527 vcl_worker_t *wrk, *child_wrk;
1528
1529 if (vcl_get_worker_index () == ~0)
1530 return;
1531
1532 if (sigaction (SIGCHLD, &old_sa, 0))
1533 {
1534 VERR ("couldn't restore sigchld");
1535 exit (-1);
1536 }
1537
1538 wrk = vcl_worker_get_current ();
1539 if (wrk->forked_child == ~0)
1540 return;
1541
1542 child_wrk = vcl_worker_get_if_valid (wrk->forked_child);
1543 if (!child_wrk)
1544 goto done;
1545
1546 if (si && si->si_pid != child_wrk->current_pid)
1547 {
1548 VDBG (0, "unexpected child pid %u", si->si_pid);
1549 goto done;
1550 }
1551 vls_cleanup_forked_child (wrk, child_wrk);
1552
1553done:
1554 if (old_sa.sa_flags & SA_SIGINFO)
1555 {
1556 void (*fn) (int, siginfo_t *, void *) = old_sa.sa_sigaction;
1557 fn (signum, si, uc);
1558 }
1559 else
1560 {
1561 void (*fn) (int) = old_sa.sa_handler;
1562 if (fn)
1563 fn (signum);
1564 }
1565}
1566
1567static void
1568vls_incercept_sigchld ()
1569{
1570 struct sigaction sa;
nandfan5fdc47c2021-02-22 17:17:17 +08001571 if (old_sa.sa_sigaction)
1572 {
1573 VDBG (0, "have intercepted sigchld");
1574 return;
1575 }
Florin Corasf9240dc2019-01-15 08:03:17 -08001576 clib_memset (&sa, 0, sizeof (sa));
1577 sa.sa_sigaction = vls_intercept_sigchld_handler;
1578 sa.sa_flags = SA_SIGINFO;
1579 if (sigaction (SIGCHLD, &sa, &old_sa))
1580 {
1581 VERR ("couldn't intercept sigchld");
1582 exit (-1);
1583 }
1584}
1585
1586static void
1587vls_app_pre_fork (void)
1588{
1589 vls_incercept_sigchld ();
1590 vcl_flush_mq_events ();
1591}
1592
1593static void
1594vls_app_fork_child_handler (void)
1595{
1596 vcl_worker_t *parent_wrk;
Florin Corasb88de902020-09-08 16:47:57 -07001597 int parent_wrk_index;
Florin Corasf9240dc2019-01-15 08:03:17 -08001598
1599 parent_wrk_index = vcl_get_worker_index ();
1600 VDBG (0, "initializing forked child %u with parent wrk %u", getpid (),
1601 parent_wrk_index);
1602
1603 /*
Florin Corasb88de902020-09-08 16:47:57 -07001604 * Clear old state
Florin Corasf9240dc2019-01-15 08:03:17 -08001605 */
1606 vcl_set_worker_index (~0);
Florin Corasf9240dc2019-01-15 08:03:17 -08001607
1608 /*
Florin Corasb88de902020-09-08 16:47:57 -07001609 * Allocate and register vcl worker with vpp
Florin Corasf9240dc2019-01-15 08:03:17 -08001610 */
Florin Corasb88de902020-09-08 16:47:57 -07001611 if (vppcom_worker_register ())
Florin Corasf9240dc2019-01-15 08:03:17 -08001612 {
Florin Corasb88de902020-09-08 16:47:57 -07001613 VERR ("couldn't register new worker!");
Florin Corasf9240dc2019-01-15 08:03:17 -08001614 return;
1615 }
1616
1617 /*
Florin Corasb88de902020-09-08 16:47:57 -07001618 * Allocate/initialize vls worker and share sessions
Florin Coras243edd52020-03-04 22:20:12 +00001619 */
1620 vls_worker_alloc ();
Florin Corasf9240dc2019-01-15 08:03:17 -08001621 parent_wrk = vcl_worker_get (parent_wrk_index);
1622 vls_worker_copy_on_fork (parent_wrk);
1623 parent_wrk->forked_child = vcl_get_worker_index ();
1624
Florin Coras0ef8ef22019-01-18 08:37:13 -08001625 /* Reset number of threads and set wrk index */
Florin Coras2d675d72019-01-28 15:54:27 -08001626 vlsl->vls_mt_n_threads = 0;
1627 vlsl->vls_wrk_index = vcl_get_worker_index ();
1628 vlsl->select_mp_check = 0;
Florin Coras2d675d72019-01-28 15:54:27 -08001629 vls_mt_locks_init ();
Florin Coras0ef8ef22019-01-18 08:37:13 -08001630
Florin Corasf9240dc2019-01-15 08:03:17 -08001631 VDBG (0, "forked child main worker initialized");
1632 vcm->forking = 0;
1633}
1634
1635static void
1636vls_app_fork_parent_handler (void)
1637{
1638 vcm->forking = 1;
1639 while (vcm->forking)
1640 ;
1641}
1642
Florin Coras0ef8ef22019-01-18 08:37:13 -08001643void
1644vls_app_exit (void)
1645{
Florin Coras243edd52020-03-04 22:20:12 +00001646 vls_worker_t *wrk = vls_worker_get_current ();
1647
Florin Coras0ef8ef22019-01-18 08:37:13 -08001648 /* Unshare the sessions. VCL will clean up the worker */
1649 vls_unshare_vcl_worker_sessions (vcl_worker_get_current ());
Florin Coras243edd52020-03-04 22:20:12 +00001650 vls_worker_free (wrk);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001651}
1652
Florin Coras40c07ce2020-07-16 20:46:17 -07001653static void
1654vls_clone_and_share_rpc_handler (void *args)
1655{
1656 vls_clone_and_share_msg_t *msg = (vls_clone_and_share_msg_t *) args;
1657 vls_worker_t *wrk = vls_worker_get_current (), *dst_wrk;
1658 vcl_locked_session_t *vls, *dst_vls;
hanlina3a48962020-07-13 11:09:15 +08001659 vcl_worker_t *vcl_wrk = vcl_worker_get_current (), *dst_vcl_wrk;
Florin Coras40c07ce2020-07-16 20:46:17 -07001660 vcl_session_t *s, *dst_s;
1661
wanghanlindcacdc42020-12-28 16:19:05 +08001662 VDBG (1, "process session clone of worker (session): %u (%u) -> %u (%u)",
1663 vcl_wrk->wrk_index, msg->session_index, msg->origin_vcl_wrk,
1664 msg->origin_session_index);
1665
1666 /* VCL locked session can't been protected, so DONT touch it.
1667 * VCL session may been free, check it.
1668 */
1669 dst_vcl_wrk = vcl_worker_get (msg->origin_vcl_wrk);
1670 s = vcl_session_get (vcl_wrk, msg->session_index);
1671 if (PREDICT_FALSE (!s))
1672 {
1673 dst_vcl_wrk->rpc_done = VLS_RPC_STATE_SESSION_NOT_EXIST;
1674 return;
1675 }
Florin Coras40c07ce2020-07-16 20:46:17 -07001676
hanlina3a48962020-07-13 11:09:15 +08001677 if (!vls_mt_wrk_supported ())
wanghanlindcacdc42020-12-28 16:19:05 +08001678 {
1679 vls = vls_session_get (wrk, msg->vls_index);
1680 vls_init_share_session (wrk, vls);
1681 dst_wrk = vls_worker_get (msg->origin_vls_wrk);
1682 dst_vls = vls_session_get (dst_wrk, msg->origin_vls_index);
1683 dst_vls->shared_data_index = vls->shared_data_index;
1684 }
hanlina3a48962020-07-13 11:09:15 +08001685 dst_s = vcl_session_get (dst_vcl_wrk, msg->origin_session_index);
Florin Coras40c07ce2020-07-16 20:46:17 -07001686 clib_memcpy (dst_s, s, sizeof (*s));
1687
wanghanlindcacdc42020-12-28 16:19:05 +08001688 dst_vcl_wrk->rpc_done = VLS_RPC_STATE_SUCCESS;
hanlina3a48962020-07-13 11:09:15 +08001689}
1690
1691static void
1692vls_session_cleanup_rpc_handler (void *args)
1693{
1694 vls_sess_cleanup_msg_t *msg = (vls_sess_cleanup_msg_t *) args;
1695 vcl_worker_t *wrk = vcl_worker_get_current ();
wanghanline8f848a2021-01-08 14:57:11 +08001696 vls_worker_t *vls_wrk = vls_worker_get_current ();
wanghanlindcacdc42020-12-28 16:19:05 +08001697 vcl_session_handle_t sh = vcl_session_handle_from_index (msg->session_index);
hanlina3a48962020-07-13 11:09:15 +08001698
wanghanlindcacdc42020-12-28 16:19:05 +08001699 VDBG (1, "process session cleanup of worker (session): %u (%u) from %u ()",
1700 wrk->wrk_index, msg->session_index, msg->origin_vcl_wrk);
hanlina3a48962020-07-13 11:09:15 +08001701
wanghanlindcacdc42020-12-28 16:19:05 +08001702 vppcom_session_close (sh);
wanghanline8f848a2021-01-08 14:57:11 +08001703 vls_sh_to_vlsh_table_del (vls_wrk, sh);
Florin Coras40c07ce2020-07-16 20:46:17 -07001704}
1705
1706static void
1707vls_rpc_handler (void *args)
1708{
1709 vls_rpc_msg_t *msg = (vls_rpc_msg_t *) args;
1710 switch (msg->type)
1711 {
1712 case VLS_RPC_CLONE_AND_SHARE:
1713 vls_clone_and_share_rpc_handler (msg->data);
1714 break;
hanlina3a48962020-07-13 11:09:15 +08001715 case VLS_RPC_SESS_CLEANUP:
1716 vls_session_cleanup_rpc_handler (msg->data);
1717 break;
Florin Coras40c07ce2020-07-16 20:46:17 -07001718 default:
1719 break;
1720 }
1721}
1722
1723void
wanghanlindcacdc42020-12-28 16:19:05 +08001724vls_send_clone_and_share_rpc (vcl_worker_t *wrk, u32 origin_vls_index,
1725 u32 session_index, u32 vls_wrk_index,
1726 u32 dst_wrk_index, u32 dst_vls_index,
1727 u32 dst_session_index)
Florin Coras40c07ce2020-07-16 20:46:17 -07001728{
1729 u8 data[sizeof (u8) + sizeof (vls_clone_and_share_msg_t)];
1730 vls_clone_and_share_msg_t *msg;
1731 vls_rpc_msg_t *rpc;
hanlina3a48962020-07-13 11:09:15 +08001732 int ret;
wanghanlindcacdc42020-12-28 16:19:05 +08001733 f64 timeout = clib_time_now (&wrk->clib_time) + VLS_WORKER_RPC_TIMEOUT;
Florin Coras40c07ce2020-07-16 20:46:17 -07001734
1735 rpc = (vls_rpc_msg_t *) & data;
1736 rpc->type = VLS_RPC_CLONE_AND_SHARE;
1737 msg = (vls_clone_and_share_msg_t *) & rpc->data;
hanlina3a48962020-07-13 11:09:15 +08001738 msg->origin_vls_wrk = vls_wrk_index;
wanghanlindcacdc42020-12-28 16:19:05 +08001739 msg->origin_vls_index = origin_vls_index;
hanlina3a48962020-07-13 11:09:15 +08001740 msg->origin_vcl_wrk = wrk->wrk_index;
1741 msg->origin_session_index = session_index;
Florin Coras40c07ce2020-07-16 20:46:17 -07001742 msg->vls_index = dst_vls_index;
hanlina3a48962020-07-13 11:09:15 +08001743 msg->session_index = dst_session_index;
Florin Coras40c07ce2020-07-16 20:46:17 -07001744
wanghanlindcacdc42020-12-28 16:19:05 +08001745 /* Try lock and handle rpcs if two threads send each other
1746 * clone requests at the same time.
1747 */
1748 wrk->rpc_done = VLS_RPC_STATE_INIT;
1749 while (!clib_spinlock_trylock (&vlsm->worker_rpc_lock))
1750 vcl_flush_mq_events ();
hanlina3a48962020-07-13 11:09:15 +08001751 ret = vcl_send_worker_rpc (dst_wrk_index, rpc, sizeof (data));
1752
Florin Corasff40d8f2020-08-11 22:05:28 -07001753 VDBG (1, "send session clone to wrk (session): %u (%u) -> %u (%u), ret=%d",
hanlina3a48962020-07-13 11:09:15 +08001754 dst_wrk_index, msg->session_index, msg->origin_vcl_wrk,
1755 msg->origin_session_index, ret);
wanghanlindcacdc42020-12-28 16:19:05 +08001756 while (!ret && wrk->rpc_done == VLS_RPC_STATE_INIT &&
1757 clib_time_now (&wrk->clib_time) < timeout)
hanlina3a48962020-07-13 11:09:15 +08001758 ;
wanghanlindcacdc42020-12-28 16:19:05 +08001759 clib_spinlock_unlock (&vlsm->worker_rpc_lock);
hanlina3a48962020-07-13 11:09:15 +08001760}
1761
1762void
1763vls_send_session_cleanup_rpc (vcl_worker_t * wrk,
1764 u32 dst_wrk_index, u32 dst_session_index)
1765{
1766 u8 data[sizeof (u8) + sizeof (vls_sess_cleanup_msg_t)];
1767 vls_sess_cleanup_msg_t *msg;
1768 vls_rpc_msg_t *rpc;
1769 int ret;
1770
1771 rpc = (vls_rpc_msg_t *) & data;
1772 rpc->type = VLS_RPC_SESS_CLEANUP;
1773 msg = (vls_sess_cleanup_msg_t *) & rpc->data;
1774 msg->origin_vcl_wrk = wrk->wrk_index;
1775 msg->session_index = dst_session_index;
1776
hanlina3a48962020-07-13 11:09:15 +08001777 ret = vcl_send_worker_rpc (dst_wrk_index, rpc, sizeof (data));
1778
Florin Corasff40d8f2020-08-11 22:05:28 -07001779 VDBG (1, "send session cleanup to wrk (session): %u (%u) from %u, ret=%d",
hanlina3a48962020-07-13 11:09:15 +08001780 dst_wrk_index, msg->session_index, msg->origin_vcl_wrk, ret);
Florin Coras40c07ce2020-07-16 20:46:17 -07001781}
1782
Florin Coras7baeb712019-01-04 17:05:43 -08001783int
1784vls_app_create (char *app_name)
1785{
1786 int rv;
Florin Coras0ef8ef22019-01-18 08:37:13 -08001787
Florin Coras7baeb712019-01-04 17:05:43 -08001788 if ((rv = vppcom_app_create (app_name)))
1789 return rv;
Florin Coras243edd52020-03-04 22:20:12 +00001790
Florin Coras2d675d72019-01-28 15:54:27 -08001791 vlsm = clib_mem_alloc (sizeof (vls_main_t));
1792 clib_memset (vlsm, 0, sizeof (*vlsm));
Florin Coras7baeb712019-01-04 17:05:43 -08001793 clib_rwlock_init (&vlsm->vls_table_lock);
Florin Coras243edd52020-03-04 22:20:12 +00001794 clib_rwlock_init (&vlsm->shared_data_lock);
wanghanlindcacdc42020-12-28 16:19:05 +08001795 clib_spinlock_init (&vlsm->worker_rpc_lock);
Florin Coras243edd52020-03-04 22:20:12 +00001796 pool_alloc (vlsm->workers, vcm->cfg.max_workers);
1797
Florin Corasf9240dc2019-01-15 08:03:17 -08001798 pthread_atfork (vls_app_pre_fork, vls_app_fork_parent_handler,
1799 vls_app_fork_child_handler);
Florin Coras0ef8ef22019-01-18 08:37:13 -08001800 atexit (vls_app_exit);
Florin Coras243edd52020-03-04 22:20:12 +00001801 vls_worker_alloc ();
Florin Coras2d675d72019-01-28 15:54:27 -08001802 vlsl->vls_wrk_index = vcl_get_worker_index ();
1803 vls_mt_locks_init ();
Florin Coras40c07ce2020-07-16 20:46:17 -07001804 vcm->wrk_rpc_fn = vls_rpc_handler;
Florin Coras7baeb712019-01-04 17:05:43 -08001805 return VPPCOM_OK;
1806}
1807
hanlin4266d4d2020-05-19 17:34:17 +08001808unsigned char
1809vls_use_eventfd (void)
1810{
1811 return vcm->cfg.use_mq_eventfd;
1812}
1813
hanlina3a48962020-07-13 11:09:15 +08001814unsigned char
1815vls_mt_wrk_supported (void)
1816{
Florin Corasff40d8f2020-08-11 22:05:28 -07001817 return vcm->cfg.mt_wrk_supported;
hanlina3a48962020-07-13 11:09:15 +08001818}
1819
1820int
1821vls_use_real_epoll (void)
1822{
1823 if (vcl_get_worker_index () == ~0)
1824 return 0;
1825
1826 return vcl_worker_get_current ()->vcl_needs_real_epoll;
1827}
1828
1829void
1830vls_register_vcl_worker (void)
1831{
wanghanlin492350e2020-09-11 17:19:32 +08001832 vls_mt_add ();
hanlina3a48962020-07-13 11:09:15 +08001833}
1834
Florin Coras7baeb712019-01-04 17:05:43 -08001835/*
1836 * fd.io coding-style-patch-verification: ON
1837 *
1838 * Local Variables:
1839 * eval: (c-set-style "gnu")
1840 * End:
1841 */