blob: 69a5ba356c0d103935bd25e55a22b08f06cb2c9c [file] [log] [blame]
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -08001/*
2 * Copyright (c) 2018 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#ifndef VPP_VCL_EVENT_H
17#define VPP_VCL_EVENT_H
18
Dave Wallace7e607a72018-06-18 18:41:32 -040019#include <vppinfra/cache.h>
20#include <vppinfra/mem.h>
21
22#define VCE_EVENTS_LOCK() clib_spinlock_lock (&(evt->events_lockp))
23#define VCE_EVENTS_UNLOCK() clib_spinlock_unlock (&(evt->events_lockp))
24#define VCE_HANDLERS_LOCK() clib_spinlock_lock (&(evt->handlers_lockp))
25#define VCE_HANDLERS_UNLOCK() clib_spinlock_unlock (&(evt->handlers_lockp))
26#define VCE_IO_SESSIONS_LOCK() clib_spinlock_lock (&(evt->io_sessions_lockp))
27#define VCE_IO_SESSIONS_UNLOCK() \
28 clib_spinlock_unlock (&(evt->io_sessions_lockp))
29
30typedef struct vppcom_ioevent_
31{
32 uint32_t session_index;
33 size_t bytes;
34} vppcom_ioevent_t;
35
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -080036/**
37 * @file
38 * @brief VPP Communications Library (VCL) event handler.
39 *
40 * Declarations for generic event handling in VCL.
41 */
42
43#include <vppinfra/types.h>
44#include <vppinfra/lock.h>
45#include <pthread.h>
46
Dave Wallace7e607a72018-06-18 18:41:32 -040047/**
48 * User registered callback for when connection arrives on listener created
49 * with vppcom_session_register_listener()
50 * @param uint32_t - newly accepted session_index
51 * @param vppcom_endpt_t* - ip/port information of remote
52 * @param void* - user passed arg to pass back
53 */
54typedef void (*vppcom_session_listener_cb) (uint32_t, vppcom_endpt_t *,
55 void *);
56
57/**
58 * User registered callback for IO events (rx/tx)
59 * @param vppcom_ioevent_t* -
60 * @param void* - user passed arg to pass back
61 */
62typedef void (*vppcom_session_ioevent_cb) (vppcom_ioevent_t *, void *);
63
64/**
65 * User registered ERROR callback for any errors associated with
66 * handling vppcom_session_register_listener() and connections
67 * @param void* - user passed arg to pass back
68 */
69typedef void (*vppcom_session_listener_errcb) (void *);
70
71
72typedef enum vcl_event_id_
73{
74 VCL_EVENT_INVALID_EVENT,
75 VCL_EVENT_CONNECT_REQ_ACCEPTED,
76 VCL_EVENT_IOEVENT_RX_FIFO,
77 VCL_EVENT_IOEVENT_TX_FIFO,
78 VCL_EVENT_N_EVENTS
79} vcl_event_id_t;
80
81/* VPPCOM Event typedefs */
82typedef struct vppcom_session_listener
83{
84 vppcom_session_listener_cb user_cb;
85 vppcom_session_listener_errcb user_errcb;
86 void *user_cb_data;
87} vppcom_session_listener_t;
88
89typedef struct vppcom_session_ioevent_
90{
91 vppcom_session_ioevent_cb user_cb;
92 void *user_cb_data;
93} vppcom_session_ioevent_t;
94
95typedef struct vppcom_session_io_thread_
96{
97 pthread_t thread;
98 pthread_mutex_t vce_io_lock;
99 pthread_cond_t vce_io_cond;
100 u32 *active_session_indexes; //pool
101 vppcom_session_ioevent_t *ioevents; //pool
102 clib_spinlock_t io_sessions_lockp;
103} vppcom_session_io_thread_t;
104
105typedef struct vce_event_connect_request_
106{
107 u32 accepted_session_index;
108} vce_event_connect_request_t;
109
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800110typedef union vce_event_key_
111{
112 struct {
113 u32 eid;
114 u32 session_index;
115 };
116 u64 as_u64;
117} vce_event_key_t;
118
119typedef struct vce_event_
120{
121 vce_event_key_t evk;
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -0700122 u32 recycle;
123 u64 data[2]; // Hard code size to avoid allocator thrashing.
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800124} vce_event_t;
125
126typedef void (*vce_event_callback_t) (void *reg /*vce_event_handler_reg_t* */);
127
128typedef struct vce_event_handler_reg_
129{
130 vce_event_callback_t handler_fn;
131 pthread_mutex_t handler_lock;
132 pthread_cond_t handler_cond;
133 u32 ev_idx;
Keith Burns (alagalah)00f44cc2018-03-07 09:26:38 -0800134 u64 evk; //Event key
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800135 u32 replaced_handler_idx;
Keith Burns (alagalah)0d2b0d52018-03-06 15:55:22 -0800136 void *handler_fn_args;
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800137} vce_event_handler_reg_t;
138
139typedef struct vce_event_thread_
140{
141 pthread_t thread;
142 pthread_mutex_t generator_lock;
143 pthread_cond_t generator_cond;
144 u32 *event_index_fifo;
145 u8 recycle_event;
146 clib_spinlock_t events_lockp;
147 vce_event_t *vce_events; //pool
148 clib_spinlock_t handlers_lockp;
149 vce_event_handler_reg_t *vce_event_handlers; //pool
150 uword *handlers_index_by_event_key; //hash
151} vce_event_thread_t;
152
Dave Wallace7e607a72018-06-18 18:41:32 -0400153
154/**
155 * @brief vppcom_session_register_listener accepts a bound session_index, and
156 * listens for connections.
157 *
158 * On successful connection, calls registered callback (cb) with new
159 * session_index.
160 *
161 * On error, calls registered error callback (errcb).
162 *
163 * @param session_index - bound session_index to create listener on
164 * @param cb - on new accepted session callback
165 * @param errcb - on failure callback
166 * @param flags - placeholder for future use. Must be ZERO
167 * @param q_len - max listener connection backlog
168 * @param ptr - user data
169 * @return
170 */
171extern int vppcom_session_register_ioevent_cb (uint32_t session_index,
172 vppcom_session_ioevent_cb cb,
173 uint8_t rx, void *ptr);
174
175/**
176 * @brief vppcom_session_register_listener accepts a bound session_index, and
177 * listens for connections.
178 *
179 * On successful connection, calls registered callback (cb) with new
180 * session_index.
181 *
182 * On error, calls registered error callback (errcb).
183 *
184 * @param session_index - bound session_index to create listener on
185 * @param cb - on new accepted session callback
186 * @param errcb - on failure callback
187 * @param flags - placeholder for future use. Must be ZERO
188 * @param q_len - max listener connection backlog
189 * @param ptr - user data
190 * @return
191 */
192extern int vppcom_session_register_listener (uint32_t session_index,
193 vppcom_session_listener_cb cb,
194 vppcom_session_listener_errcb
195 errcb, uint8_t flags, int q_len,
196 void *ptr);
197
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800198/**
199 * @brief vce_generate_event
200 * - used to trigger an event in the event thread so that registered
201 * handlers are notified
202 *
203 * @param evt - vce_event_thread_t - event system state
204 * @param ev_idx - index to vce_event_thread_t vce_event pool
205 *
206 * @return success/failure rv
207 */
208int vce_generate_event (vce_event_thread_t *evt, u32 ev_idx);
209
210/**
211 * @brief vce_clear_event()
212 * - removes event from event_pool
213 *
214 * @param evt - vce_event_thread_t - event system state
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -0700215 * @param ev_idx - u32 - index of event to remove
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800216 */
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -0700217void vce_clear_event (vce_event_thread_t *evt, u32 ev_idx);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800218
219/**
220 * @brief vce_get_event_from_index()
221 *
222 * @param evt - vce_event_thread_t - event system state
223 * @param ev_idx - index to vce_event_thread_t vce_event pool
224 *
225 * @return vce_event_t *
226 */
227vce_event_t * vce_get_event_from_index(vce_event_thread_t *evt, u32 ev_idx);
228
229/**
Keith Burns (alagalah)410bcca2018-03-23 13:42:49 -0700230 * @brief vce_get_event_data()
231 *
232 * @param ev - vce_event_t * - event
233 * @param data_size - u32 - required size of data
234 *
235 * @return vce_event_t *
236 */
237always_inline void * vce_get_event_data(vce_event_t *ev, u32 data_size)
238{
239 ASSERT(sizeof(ev->data) >= data_size);
240 return (&ev->data);
241}
242
243/**
Keith Burns (alagalah)7cf80e02018-03-08 16:46:25 -0800244 * @brief vce_get_event_handler()
245 * - returns handler if exists or 0
246 * @param evt - vce_event_thread_t - event system state
247 * @param evk - event key
248 * @return vce_event_handler_reg_t *
249 */
250vce_event_handler_reg_t * vce_get_event_handler (vce_event_thread_t *evt,
251 vce_event_key_t *evk);
252
253/**
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800254 * @brief vce_register_handler
255 * - used by functions who need to be notified that an event has occurred
256 * on a vce_event_key_t (i.e. event type (enum) and sessionID)
257 * - if a handler already exists, the index to the old handler is stored
258 * inside the new handler for re-instatement on vce_unregister_handler()
259
260 * @param evt - vce_event_thread_t - event system state
261 * @param evk - vce_event_key_t current an eventID from enum in consumer and
262 * sessionID
263 * @param cb - vce_event_callback_t function to handle event
Keith Burns (alagalah)0d2b0d52018-03-06 15:55:22 -0800264 * @param cb_args - args that the callback needs passed back to it.
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800265 * @return vce_handler_reg_t - the function that needs event notification
266 * needs to block on a condvar mutex to reduce spin. That is in here.
267 */
268vce_event_handler_reg_t * vce_register_handler (vce_event_thread_t *evt,
269 vce_event_key_t *evk,
Keith Burns (alagalah)0d2b0d52018-03-06 15:55:22 -0800270 vce_event_callback_t cb,
271 void *cb_args);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800272
273/**
274 * @brief vce_unregister_handler
275 * - used by functions to remove need to be notified that an event has occurred
276 * on a vce_event_key_t (i.e. event type (enum) and sessionID)
277 * - if this handler replaced an existing one, re-instate it.
278 *
279 * @param evt - vce_event_thread_t - event system state
Keith Burns (alagalah)00f44cc2018-03-07 09:26:38 -0800280 * @param handler - handler to be unregistered
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800281 * @return success/failure rv
282 */
Keith Burns (alagalah)00f44cc2018-03-07 09:26:38 -0800283int vce_unregister_handler (vce_event_thread_t *evt,
284 vce_event_handler_reg_t *handler);
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800285
286/**
287 * @brief vce_event_thread_fn
288 * - main event thread that waits on a generic condvar/mutex that a signal
289 * has been generated.
290 * - loops through all registered handlers for that vce_event_key_t
291 * (event enum + sessionID)
292 *
293 * @param arg - cast to type of event defined in consuming program.
294 * @return
295 */
296extern void * vce_event_thread_fn (void *arg);
297
298/**
299 * @brief vce_start_event_thread
300 * - as name suggests. What is important is that vce_event_thread_t is allocated
301 * on the same heap as "everything else". ie use clib_mem_alloc.
302 * @param evt - vce_event_thread_t - event system state
303 * @param max_events - depth of event FIFO for max number of outstanding events.
304 * @return succes/failure
305 */
306int vce_start_event_thread (vce_event_thread_t *evt, u8 max_events);
307
Dave Wallace7e607a72018-06-18 18:41:32 -0400308/**
309 * * @brief vce_connect_request_handler_fn
310 * - used for listener sessions
311 * - when a vl_api_accept_session_t_handler() generates an event
312 * this callback is alerted and sets fields that consumers such as
313 * vppcom_session_accept() expect to see, ie. accepted_client_index
314 *
315 * @param arg - void* to be cast to vce_event_handler_reg_t*
316 */
317always_inline void
318vce_connect_request_handler_fn (void *arg)
319{
320 vce_event_handler_reg_t *reg = (vce_event_handler_reg_t *) arg;
321
322 pthread_mutex_lock (&reg->handler_lock);
323 pthread_cond_signal (&reg->handler_cond);
324 pthread_mutex_unlock (&reg->handler_lock);
325}
326
Keith Burns (alagalah)3cf2d642018-02-23 10:17:01 -0800327#endif //VPP_VCL_EVENT_H