blob: 6254bad09b610e7796745d90010223d0b9320091 [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
19typedef struct vcl_locked_session_
20{
21 u32 session_index;
22 u32 worker_index;
23 u32 vls_index;
24 u32 flags;
25 clib_spinlock_t lock;
26} vcl_locked_session_t;
27
28typedef struct vcl_main_
29{
30 vcl_locked_session_t *vls_pool;
31 clib_rwlock_t vls_table_lock;
32 uword *session_index_to_vlsh_table;
33} vls_main_t;
34
35vls_main_t vls_main;
36vls_main_t *vlsm = &vls_main;
37
38static inline void
39vls_table_rlock (void)
40{
41 clib_rwlock_reader_lock (&vlsm->vls_table_lock);
42}
43
44static inline void
45vls_table_runlock (void)
46{
47 clib_rwlock_reader_unlock (&vlsm->vls_table_lock);
48}
49
50static inline void
51vls_table_wlock (void)
52{
53 clib_rwlock_writer_lock (&vlsm->vls_table_lock);
54}
55
56static inline void
57vls_table_wunlock (void)
58{
59 clib_rwlock_writer_unlock (&vlsm->vls_table_lock);
60}
61
62static inline vcl_session_handle_t
63vls_to_sh (vcl_locked_session_t * vls)
64{
65 return vppcom_session_handle (vls->session_index);
66}
67
68static inline vcl_session_handle_t
69vls_to_sh_tu (vcl_locked_session_t * vls)
70{
71 vcl_session_handle_t sh;
72 sh = vls_to_sh (vls);
73 vls_table_runlock ();
74 return sh;
75}
76
77static vls_handle_t
78vls_alloc (vcl_session_handle_t sh)
79{
80 vcl_locked_session_t *vls;
81
82 vls_table_wlock ();
83 pool_get (vlsm->vls_pool, vls);
84 vls->session_index = vppcom_session_index (sh);
85 vls->worker_index = vppcom_session_worker (sh);
86 vls->vls_index = vls - vlsm->vls_pool;
87 hash_set (vlsm->session_index_to_vlsh_table, vls->session_index,
88 vls->vls_index);
89 clib_spinlock_init (&vls->lock);
90 vls_table_wunlock ();
91 return vls->vls_index;
92}
93
94static vcl_locked_session_t *
95vls_get (vls_handle_t vlsh)
96{
97 if (pool_is_free_index (vlsm->vls_pool, vlsh))
98 return 0;
99 return pool_elt_at_index (vlsm->vls_pool, vlsh);
100}
101
102static void
103vls_free (vcl_locked_session_t * fde)
104{
105 ASSERT (fde != 0);
106 hash_unset (vlsm->session_index_to_vlsh_table, fde->session_index);
107 clib_spinlock_free (&fde->lock);
108 pool_put (vlsm->vls_pool, fde);
109}
110
111static vcl_locked_session_t *
112vls_get_and_lock (vls_handle_t vlsh)
113{
114 vcl_locked_session_t *vls;
115 if (pool_is_free_index (vlsm->vls_pool, vlsh))
116 return 0;
117 vls = pool_elt_at_index (vlsm->vls_pool, vlsh);
118 clib_spinlock_lock (&vls->lock);
119 return vls;
120}
121
122static vcl_locked_session_t *
123vls_get_w_dlock (vls_handle_t vlsh)
124{
125 vcl_locked_session_t *vls;
126 vls_table_rlock ();
127 vls = vls_get_and_lock (vlsh);
128 if (!vls)
129 vls_table_runlock ();
130 return vls;
131}
132
133static inline void
134vls_unlock (vcl_locked_session_t * vls)
135{
136 clib_spinlock_unlock (&vls->lock);
137}
138
139static inline void
140vls_get_and_unlock (vls_handle_t vlsh)
141{
142 vcl_locked_session_t *vls;
143 vls_table_rlock ();
144 vls = vls_get (vlsh);
145 vls_unlock (vls);
146 vls_table_runlock ();
147}
148
149static inline void
150vls_dunlock (vcl_locked_session_t * vls)
151{
152 vls_unlock (vls);
153 vls_table_runlock ();
154}
155
156static void
157vls_get_and_free (vls_handle_t vlsh)
158{
159 vcl_locked_session_t *vls;
160
161 vls_table_wlock ();
162 vls = vls_get (vlsh);
163 vls_free (vls);
164 vls_table_wunlock ();
165}
166
167int
168vls_write (vls_handle_t vlsh, void *buf, size_t nbytes)
169{
170 vcl_locked_session_t *vls;
171 int rv;
172
173 if (!(vls = vls_get_w_dlock (vlsh)))
174 return VPPCOM_EBADFD;
175 rv = vppcom_session_write (vls_to_sh_tu (vls), buf, nbytes);
176 vls_get_and_unlock (vlsh);
177 return rv;
178}
179
180int
181vls_write_msg (vls_handle_t vlsh, void *buf, size_t nbytes)
182{
183 vcl_locked_session_t *vls;
184 int rv;
185
186 if (!(vls = vls_get_w_dlock (vlsh)))
187 return VPPCOM_EBADFD;
188 rv = vppcom_session_write_msg (vls_to_sh_tu (vls), buf, nbytes);
189 vls_get_and_unlock (vlsh);
190 return rv;
191}
192
193int
194vls_sendto (vls_handle_t vlsh, void *buf, int buflen, int flags,
195 vppcom_endpt_t * ep)
196{
197 vcl_locked_session_t *vls;
198 int rv;
199
200 if (!(vls = vls_get_w_dlock (vlsh)))
201 return VPPCOM_EBADFD;
202 rv = vppcom_session_sendto (vls_to_sh_tu (vls), buf, buflen, flags, ep);
203 vls_get_and_unlock (vlsh);
204 return rv;
205}
206
207ssize_t
208vls_read (vls_handle_t vlsh, void *buf, size_t nbytes)
209{
210 vcl_locked_session_t *vls;
211 int rv;
212
213 if (!(vls = vls_get_w_dlock (vlsh)))
214 return VPPCOM_EBADFD;
215 rv = vppcom_session_read (vls_to_sh_tu (vls), buf, nbytes);
216 vls_get_and_unlock (vlsh);
217 return rv;
218}
219
220ssize_t
221vls_recvfrom (vls_handle_t vlsh, void *buffer, uint32_t buflen, int flags,
222 vppcom_endpt_t * ep)
223{
224 vcl_locked_session_t *vls;
225 int rv;
226
227 if (!(vls = vls_get_w_dlock (vlsh)))
228 return VPPCOM_EBADFD;
229 rv = vppcom_session_recvfrom (vls_to_sh_tu (vls), buffer, buflen, flags,
230 ep);
231 vls_get_and_unlock (vlsh);
232 return rv;
233}
234
235int
236vls_attr (vls_handle_t vlsh, uint32_t op, void *buffer, uint32_t * buflen)
237{
238 vcl_locked_session_t *vls;
239 int rv;
240
241 if (!(vls = vls_get_w_dlock (vlsh)))
242 return VPPCOM_EBADFD;
243 rv = vppcom_session_attr (vls_to_sh_tu (vls), op, buffer, buflen);
244 vls_get_and_unlock (vlsh);
245 return rv;
246}
247
248int
249vls_bind (vls_handle_t vlsh, vppcom_endpt_t * ep)
250{
251 vcl_locked_session_t *vls;
252 int rv;
253
254 if (!(vls = vls_get_w_dlock (vlsh)))
255 return VPPCOM_EBADFD;
256 rv = vppcom_session_bind (vls_to_sh_tu (vls), ep);
257 vls_get_and_unlock (vlsh);
258 return rv;
259}
260
261int
262vls_listen (vls_handle_t vlsh, int q_len)
263{
264 vcl_locked_session_t *vls;
265 int rv;
266
267 if (!(vls = vls_get_w_dlock (vlsh)))
268 return VPPCOM_EBADFD;
269 rv = vppcom_session_listen (vls_to_sh_tu (vls), q_len);
270 vls_get_and_unlock (vlsh);
271 return rv;
272}
273
274int
275vls_connect (vls_handle_t vlsh, vppcom_endpt_t * server_ep)
276{
277 vcl_locked_session_t *vls;
278 int rv;
279
280 if (!(vls = vls_get_w_dlock (vlsh)))
281 return VPPCOM_EBADFD;
282 rv = vppcom_session_connect (vls_to_sh_tu (vls), server_ep);
283 vls_get_and_unlock (vlsh);
284 return rv;
285}
286
287vls_handle_t
288vls_accept (vls_handle_t listener_vlsh, vppcom_endpt_t * ep, int flags)
289{
290 vls_handle_t accepted_vlsh;
291 vcl_locked_session_t *vls;
292 int sh;
293
294 if (!(vls = vls_get_w_dlock (listener_vlsh)))
295 return VPPCOM_EBADFD;
296 sh = vppcom_session_accept (vls_to_sh_tu (vls), ep, flags);
297 vls_get_and_unlock (listener_vlsh);
298 if (sh < 0)
299 return sh;
300 accepted_vlsh = vls_alloc (sh);
301 if (PREDICT_FALSE (accepted_vlsh == VLS_INVALID_HANDLE))
302 vppcom_session_close (sh);
303 return accepted_vlsh;
304}
305
306vls_handle_t
307vls_create (uint8_t proto, uint8_t is_nonblocking)
308{
309 vcl_session_handle_t sh;
310 vls_handle_t vlsh;
311
312 sh = vppcom_session_create (proto, is_nonblocking);
313 if (sh == INVALID_SESSION_ID)
314 return VLS_INVALID_HANDLE;
315
316 vlsh = vls_alloc (sh);
317 if (PREDICT_FALSE (vlsh == VLS_INVALID_HANDLE))
318 vppcom_session_close (sh);
319
320 return vlsh;
321}
322
323int
324vls_close (vls_handle_t vlsh)
325{
326 vcl_locked_session_t *vls;
327 vcl_session_handle_t sh;
328 int rv, refcnt;
329
330 if (!(vls = vls_get_w_dlock (vlsh)))
331 return VPPCOM_EBADFD;
332
333 sh = vls_to_sh (vls);
334 refcnt = vppcom_session_attr (sh, VPPCOM_ATTR_GET_REFCNT, 0, 0);
335 if ((rv = vppcom_session_close (sh)))
336 {
337 vls_dunlock (vls);
338 return rv;
339 }
340
341 vls_dunlock (vls);
342 if (refcnt <= 1)
343 vls_get_and_free (vlsh);
344 return rv;
345}
346
347vls_handle_t
348vls_epoll_create (void)
349{
350 vcl_session_handle_t sh;
351 vls_handle_t vlsh;
352
353 sh = vppcom_epoll_create ();
354 if (sh == INVALID_SESSION_ID)
355 return VLS_INVALID_HANDLE;
356
357 vlsh = vls_alloc (sh);
358 if (vlsh == VLS_INVALID_HANDLE)
359 vppcom_session_close (sh);
360
361 return vlsh;
362}
363
364int
365vls_epoll_ctl (vls_handle_t ep_vlsh, int op, vls_handle_t vlsh,
366 struct epoll_event *event)
367{
368 vcl_locked_session_t *ep_vls, *vls;
369 vcl_session_handle_t ep_sh, sh;
370 int rv;
371
372 vls_table_rlock ();
373 ep_vls = vls_get_and_lock (ep_vlsh);
374 vls = vls_get_and_lock (vlsh);
375 ep_sh = vls_to_sh (ep_vls);
376 sh = vls_to_sh (vls);
377 vls_table_runlock ();
378
379 rv = vppcom_epoll_ctl (ep_sh, op, sh, event);
380
381 vls_table_rlock ();
382 ep_vls = vls_get (ep_vlsh);
383 vls = vls_get (vlsh);
384 vls_unlock (vls);
385 vls_unlock (ep_vls);
386 vls_table_runlock ();
387 return rv;
388}
389
390int
391vls_epoll_wait (vls_handle_t ep_vlsh, struct epoll_event *events,
392 int maxevents, double wait_for_time)
393{
394 vcl_locked_session_t *vls;
395 int rv;
396
397 if (!(vls = vls_get_w_dlock (ep_vlsh)))
398 return VPPCOM_EBADFD;
399 rv = vppcom_epoll_wait (vls_to_sh_tu (vls), events, maxevents,
400 wait_for_time);
401 vls_get_and_unlock (ep_vlsh);
402 return rv;
403}
404
405vcl_session_handle_t
406vlsh_to_sh (vls_handle_t vlsh)
407{
408 vcl_locked_session_t *vls;
409 int rv;
410
411 vls = vls_get_w_dlock (vlsh);
412 if (!vls)
413 return INVALID_SESSION_ID;
414 rv = vls_to_sh (vls);
415 vls_dunlock (vls);
416 return rv;
417}
418
419vcl_session_handle_t
420vlsh_to_session_index (vls_handle_t vlsh)
421{
422 vcl_session_handle_t sh;
423 sh = vlsh_to_sh (vlsh);
424 return vppcom_session_index (sh);
425}
426
427vls_handle_t
428vls_session_index_to_vlsh (uint32_t session_index)
429{
430 vls_handle_t vlsh;
431 uword *vlshp;
432
433 vls_table_rlock ();
434 vlshp = hash_get (vlsm->session_index_to_vlsh_table, session_index);
435 vlsh = vlshp ? *vlshp : VLS_INVALID_HANDLE;
436 vls_table_runlock ();
437
438 return vlsh;
439}
440
441int
442vls_app_create (char *app_name)
443{
444 int rv;
445 if ((rv = vppcom_app_create (app_name)))
446 return rv;
447 clib_rwlock_init (&vlsm->vls_table_lock);
448 return VPPCOM_OK;
449}
450
451/*
452 * fd.io coding-style-patch-verification: ON
453 *
454 * Local Variables:
455 * eval: (c-set-style "gnu")
456 * End:
457 */