blob: 7a04bb056f22da033bb4c82545193cbb511867b6 [file] [log] [blame]
Dave Barachaff70772016-10-31 11:59:07 -04001/*
2 *------------------------------------------------------------------
3 * api_helper_macros.h - message handler helper macros
4 *
5 * Copyright (c) 2016 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
Dave Barachaff70772016-10-31 11:59:07 -040020#ifndef __api_helper_macros_h__
21#define __api_helper_macros_h__
22
23#define f64_endian(a)
24#define f64_print(a,b)
25
Eyal Bari0856b972017-03-15 14:54:19 +020026#ifndef REPLY_MSG_ID_BASE
27#define REPLY_MSG_ID_BASE 0
28#endif
29
Dave Barach59b25652017-09-10 15:04:27 -040030#define REPLY_MACRO(t) \
31do { \
32 vl_api_registration_t *rp; \
Dave Barach59b25652017-09-10 15:04:27 -040033 rp = vl_api_client_index_to_registration (mp->client_index); \
34 if (rp == 0) \
35 return; \
36 \
37 rmp = vl_msg_api_alloc (sizeof (*rmp)); \
38 rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \
39 rmp->context = mp->context; \
40 rmp->retval = ntohl(rv); \
41 \
Florin Corase86a8ed2018-01-05 03:20:25 -080042 vl_api_send_msg (rp, (u8 *)rmp); \
Dave Barachaff70772016-10-31 11:59:07 -040043} while(0);
44
Ole Troanbad67922020-08-24 12:22:01 +020045#define REPLY_MACRO_END(t) \
46do { \
47 vl_api_registration_t *rp; \
Ole Troanbad67922020-08-24 12:22:01 +020048 rp = vl_api_client_index_to_registration (mp->client_index); \
49 if (rp == 0) \
50 return; \
51 \
52 rmp = vl_msg_api_alloc (sizeof (*rmp)); \
53 rmp->_vl_msg_id = t+(REPLY_MSG_ID_BASE); \
54 rmp->context = mp->context; \
55 rmp->retval = rv; \
56 api_main_t *am = vlibapi_get_main (); \
57 void (*endian_fp) (void *); \
58 endian_fp = am->msg_endian_handlers[t+(REPLY_MSG_ID_BASE)]; \
59 (*endian_fp) (rmp); \
60 vl_api_send_msg (rp, (u8 *)rmp); \
61} while(0);
62
Dave Barach59b25652017-09-10 15:04:27 -040063#define REPLY_MACRO2(t, body) \
64do { \
65 vl_api_registration_t *rp; \
Dave Barach59b25652017-09-10 15:04:27 -040066 rp = vl_api_client_index_to_registration (mp->client_index); \
67 if (rp == 0) \
68 return; \
69 \
70 rmp = vl_msg_api_alloc (sizeof (*rmp)); \
71 rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \
72 rmp->context = mp->context; \
73 rmp->retval = ntohl(rv); \
74 do {body;} while (0); \
Florin Corase86a8ed2018-01-05 03:20:25 -080075 vl_api_send_msg (rp, (u8 *)rmp); \
Dave Barachaff70772016-10-31 11:59:07 -040076} while(0);
77
Ole Troane796a182020-05-18 11:14:05 +020078#define REPLY_MACRO2_END(t, body) \
79do { \
80 vl_api_registration_t *rp; \
Ole Troane796a182020-05-18 11:14:05 +020081 rp = vl_api_client_index_to_registration (mp->client_index); \
82 if (rp == 0) \
83 return; \
84 \
85 rmp = vl_msg_api_alloc (sizeof (*rmp)); \
86 rmp->_vl_msg_id = t+(REPLY_MSG_ID_BASE); \
87 rmp->context = mp->context; \
88 rmp->retval = rv; \
89 do {body;} while (0); \
90 api_main_t *am = vlibapi_get_main (); \
91 void (*endian_fp) (void *); \
Ole Troanbad67922020-08-24 12:22:01 +020092 endian_fp = am->msg_endian_handlers[t+(REPLY_MSG_ID_BASE)]; \
Ole Troane796a182020-05-18 11:14:05 +020093 (*endian_fp) (rmp); \
94 vl_api_send_msg (rp, (u8 *)rmp); \
95} while(0);
96
Paul Vinciguerraf24de172020-01-27 18:42:25 -050097#define REPLY_MACRO2_ZERO(t, body) \
98do { \
99 vl_api_registration_t *rp; \
Paul Vinciguerraf24de172020-01-27 18:42:25 -0500100 rp = vl_api_client_index_to_registration (mp->client_index); \
101 if (rp == 0) \
102 return; \
103 \
104 rmp = vl_msg_api_alloc_zero (sizeof (*rmp)); \
105 rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \
106 rmp->context = mp->context; \
107 rmp->retval = ntohl(rv); \
108 do {body;} while (0); \
109 vl_api_send_msg (rp, (u8 *)rmp); \
110} while(0);
111
Ole Troan2a1ca782019-09-19 01:08:30 +0200112#define REPLY_MACRO_DETAILS2(t, body) \
113do { \
114 vl_api_registration_t *rp; \
Ole Troan2a1ca782019-09-19 01:08:30 +0200115 rp = vl_api_client_index_to_registration (mp->client_index); \
116 if (rp == 0) \
117 return; \
118 \
119 rmp = vl_msg_api_alloc (sizeof (*rmp)); \
120 rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \
121 rmp->context = mp->context; \
122 do {body;} while (0); \
123 vl_api_send_msg (rp, (u8 *)rmp); \
124} while(0);
125
Ole Troanf5db3712020-05-20 15:47:06 +0200126#define REPLY_MACRO_DETAILS4(t, rp, context, body) \
127do { \
128 rmp = vl_msg_api_alloc (sizeof (*rmp)); \
129 rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \
130 rmp->context = context; \
131 do {body;} while (0); \
132 vl_api_send_msg (rp, (u8 *)rmp); \
133} while(0);
134
Dave Barach59b25652017-09-10 15:04:27 -0400135#define REPLY_MACRO3(t, n, body) \
136do { \
137 vl_api_registration_t *rp; \
Dave Barach59b25652017-09-10 15:04:27 -0400138 rp = vl_api_client_index_to_registration (mp->client_index); \
139 if (rp == 0) \
140 return; \
141 \
142 rmp = vl_msg_api_alloc (sizeof (*rmp) + n); \
143 rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \
144 rmp->context = mp->context; \
145 rmp->retval = ntohl(rv); \
146 do {body;} while (0); \
Florin Corase86a8ed2018-01-05 03:20:25 -0800147 vl_api_send_msg (rp, (u8 *)rmp); \
Dave Barachaff70772016-10-31 11:59:07 -0400148} while(0);
149
Paul Vinciguerraf24de172020-01-27 18:42:25 -0500150#define REPLY_MACRO3_ZERO(t, n, body) \
151do { \
152 vl_api_registration_t *rp; \
Paul Vinciguerraf24de172020-01-27 18:42:25 -0500153 rp = vl_api_client_index_to_registration (mp->client_index); \
154 if (rp == 0) \
155 return; \
156 \
157 rmp = vl_msg_api_alloc_zero (sizeof (*rmp) + n); \
158 rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \
159 rmp->context = mp->context; \
160 rmp->retval = ntohl(rv); \
161 do {body;} while (0); \
162 vl_api_send_msg (rp, (u8 *)rmp); \
163} while(0);
164
Dave Barach59b25652017-09-10 15:04:27 -0400165#define REPLY_MACRO4(t, n, body) \
166do { \
167 vl_api_registration_t *rp; \
168 u8 is_error = 0; \
Dave Barach59b25652017-09-10 15:04:27 -0400169 \
170 rp = vl_api_client_index_to_registration (mp->client_index); \
171 if (rp == 0) \
172 return; \
173 \
174 rmp = vl_msg_api_alloc_or_null (sizeof (*rmp) + n); \
175 if (!rmp) \
176 { \
177 /* if there isn't enough memory, try to allocate */ \
178 /* some at least for returning an error */ \
179 rmp = vl_msg_api_alloc (sizeof (*rmp)); \
180 if (!rmp) \
181 return; \
182 \
Dave Barachb7b92992018-10-17 10:38:51 -0400183 clib_memset (rmp, 0, sizeof (*rmp)); \
Dave Barach59b25652017-09-10 15:04:27 -0400184 rv = VNET_API_ERROR_TABLE_TOO_BIG; \
185 is_error = 1; \
186 } \
187 rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \
188 rmp->context = mp->context; \
189 rmp->retval = ntohl(rv); \
190 if (!is_error) \
191 do {body;} while (0); \
Florin Corase86a8ed2018-01-05 03:20:25 -0800192 vl_api_send_msg (rp, (u8 *)rmp); \
Dave Barachaff70772016-10-31 11:59:07 -0400193} while(0);
194
Neale Ranns44db1ca2020-12-24 09:16:09 +0000195#define REPLY_AND_DETAILS_MACRO(t, p, body) \
196 do \
197 { \
198 if (pool_elts (p) == 0) \
199 { \
200 REPLY_MACRO (t); \
201 break; \
202 } \
203 vl_api_registration_t *rp; \
204 rp = vl_api_client_index_to_registration (mp->client_index); \
205 if (rp == 0) \
206 return; \
207 u32 cursor = clib_net_to_host_u32 (mp->cursor); \
208 vlib_main_t *vm = vlib_get_main (); \
209 f64 start = vlib_time_now (vm); \
210 if (pool_is_free_index (p, cursor)) \
211 { \
212 cursor = pool_next_index (p, cursor); \
213 if (cursor == ~0) \
214 rv = VNET_API_ERROR_INVALID_VALUE; \
215 } \
216 while (cursor != ~0) \
217 { \
218 do \
219 { \
220 body; \
221 } \
222 while (0); \
223 cursor = pool_next_index (p, cursor); \
224 if (vl_api_process_may_suspend (vm, rp, start)) \
225 { \
226 if (cursor != ~0) \
227 rv = VNET_API_ERROR_EAGAIN; \
228 break; \
229 } \
230 } \
231 REPLY_MACRO2 (t, ({ rmp->cursor = clib_host_to_net_u32 (cursor); })); \
232 } \
233 while (0);
Ole Troanf5db3712020-05-20 15:47:06 +0200234
Jon Loeligerc0b19542020-05-11 08:43:51 -0500235#define REPLY_AND_DETAILS_VEC_MACRO(t, v, mp, rmp, rv, body) \
236do { \
237 vl_api_registration_t *rp; \
238 rp = vl_api_client_index_to_registration (mp->client_index); \
239 if (rp == 0) \
240 return; \
241 u32 cursor = clib_net_to_host_u32 (mp->cursor); \
242 vlib_main_t *vm = vlib_get_main (); \
243 f64 start = vlib_time_now (vm); \
244 if (!v || vec_len (v) == 0) { \
245 cursor = ~0; \
246 rv = VNET_API_ERROR_INVALID_VALUE; \
247 } else if (cursor == ~0) \
248 cursor = 0; \
249 while (cursor != ~0 && cursor < vec_len (v)) { \
250 do {body;} while (0); \
251 ++cursor; \
252 if (vl_api_process_may_suspend (vm, rp, start)) { \
253 if (cursor < vec_len (v)) \
254 rv = VNET_API_ERROR_EAGAIN; \
255 break; \
256 } \
257 } \
258 REPLY_MACRO2 (t, ({ \
259 rmp->cursor = clib_host_to_net_u32 (cursor); \
260 })); \
261} while(0);
262
263
Dave Barachaff70772016-10-31 11:59:07 -0400264/* "trust, but verify" */
Florin Coras248210c2021-09-14 18:54:45 -0700265#define vnet_sw_if_index_is_api_valid(sw_if_index) \
266 vnet_sw_interface_is_api_valid (vnet_get_main (), sw_if_index)
Eyal Bari1c82cd42017-03-14 14:39:51 +0200267
Dave Barachaff70772016-10-31 11:59:07 -0400268#define VALIDATE_SW_IF_INDEX(mp) \
Neale Ranns947ea622018-06-07 23:48:20 -0700269 do { u32 __sw_if_index = ntohl((mp)->sw_if_index); \
Eyal Bari1c82cd42017-03-14 14:39:51 +0200270 if (!vnet_sw_if_index_is_api_valid(__sw_if_index)) { \
Dave Barachaff70772016-10-31 11:59:07 -0400271 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
272 goto bad_sw_if_index; \
273 } \
274} while(0);
275
276#define BAD_SW_IF_INDEX_LABEL \
277do { \
278bad_sw_if_index: \
279 ; \
280} while (0);
281
282#define VALIDATE_RX_SW_IF_INDEX(mp) \
Neale Ranns947ea622018-06-07 23:48:20 -0700283 do { u32 __rx_sw_if_index = ntohl((mp)->rx_sw_if_index); \
Eyal Bari1c82cd42017-03-14 14:39:51 +0200284 if (!vnet_sw_if_index_is_api_valid(__rx_sw_if_index)) { \
Dave Barachaff70772016-10-31 11:59:07 -0400285 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
286 goto bad_rx_sw_if_index; \
287 } \
288} while(0);
289
290#define BAD_RX_SW_IF_INDEX_LABEL \
291do { \
292bad_rx_sw_if_index: \
293 ; \
294} while (0);
295
296#define VALIDATE_TX_SW_IF_INDEX(mp) \
297 do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index); \
Eyal Bari1c82cd42017-03-14 14:39:51 +0200298 if (!vnet_sw_if_index_is_api_valid(__tx_sw_if_index)) { \
Dave Barachaff70772016-10-31 11:59:07 -0400299 rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
300 goto bad_tx_sw_if_index; \
301 } \
302} while(0);
303
304#define BAD_TX_SW_IF_INDEX_LABEL \
305do { \
306bad_tx_sw_if_index: \
307 ; \
308} while (0);
309
John Lo97934772017-05-18 22:26:47 -0400310#define VALIDATE_BD_ID(mp) \
311 do { u32 __rx_bd_id = ntohl(mp->bd_id); \
312 if (__rx_bd_id > L2_BD_ID_MAX) { \
313 rv = VNET_API_ERROR_BD_ID_EXCEED_MAX; \
314 goto bad_bd_id; \
315 } \
316} while(0);
317
318#define BAD_BD_ID_LABEL \
319do { \
320bad_bd_id: \
321 ; \
322} while (0);
323
Dave Barach6d963c22016-12-05 09:50:05 -0500324#define pub_sub_handler(lca,UCA) \
325static void vl_api_want_##lca##_t_handler ( \
326 vl_api_want_##lca##_t *mp) \
327{ \
328 vpe_api_main_t *vam = &vpe_api_main; \
329 vpe_client_registration_t *rp; \
330 vl_api_want_##lca##_reply_t *rmp; \
331 uword *p; \
332 i32 rv = 0; \
333 \
334 p = hash_get (vam->lca##_registration_hash, mp->client_index); \
335 if (p) { \
336 if (mp->enable_disable) { \
Ole Troan32ef1372019-01-07 22:17:31 +0100337 clib_warning ("pid %d: already enabled...", ntohl(mp->pid)); \
Dave Barach6d963c22016-12-05 09:50:05 -0500338 rv = VNET_API_ERROR_INVALID_REGISTRATION; \
339 goto reply; \
340 } else { \
341 rp = pool_elt_at_index (vam->lca##_registrations, p[0]); \
342 pool_put (vam->lca##_registrations, rp); \
343 hash_unset (vam->lca##_registration_hash, \
344 mp->client_index); \
345 goto reply; \
346 } \
347 } \
348 if (mp->enable_disable == 0) { \
349 clib_warning ("pid %d: already disabled...", mp->pid); \
350 rv = VNET_API_ERROR_INVALID_REGISTRATION; \
351 goto reply; \
352 } \
353 pool_get (vam->lca##_registrations, rp); \
354 rp->client_index = mp->client_index; \
355 rp->client_pid = mp->pid; \
356 hash_set (vam->lca##_registration_hash, rp->client_index, \
357 rp - vam->lca##_registrations); \
358 \
359reply: \
360 REPLY_MACRO (VL_API_WANT_##UCA##_REPLY); \
Neale Rannsf12dad62018-06-04 18:41:24 -0700361} \
362 \
363static clib_error_t * vl_api_want_##lca##_t_reaper (u32 client_index) \
364{ \
365 vpe_api_main_t *vam = &vpe_api_main; \
366 vpe_client_registration_t *rp; \
367 uword *p; \
368 \
Matthew Smithd4656312018-06-14 11:40:49 -0500369 p = hash_get (vam->lca##_registration_hash, client_index); \
Neale Rannsf12dad62018-06-04 18:41:24 -0700370 if (p) \
371 { \
372 rp = pool_elt_at_index (vam->lca##_registrations, p[0]); \
373 pool_put (vam->lca##_registrations, rp); \
374 hash_unset (vam->lca##_registration_hash, client_index); \
375 } \
376 return (NULL); \
377} \
378 \
379VL_MSG_API_REAPER_FUNCTION (vl_api_want_##lca##_t_reaper); \
Dave Barach6d963c22016-12-05 09:50:05 -0500380
381#define foreach_registration_hash \
382_(interface_events) \
383_(to_netconf_server) \
384_(from_netconf_server) \
385_(to_netconf_client) \
386_(from_netconf_client) \
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200387_(oam_events) \
Eyal Bari20197482017-09-13 12:29:08 +0300388_(bfd_events) \
Neale Rannscbe25aa2019-09-30 10:53:31 +0000389_(l2_arp_term_events) \
Juraj Sloboda81119e82018-05-25 14:02:20 +0200390_(ip6_ra_events) \
Juraj Slobodadd3b8f72018-05-04 14:20:06 +0200391_(dhcp6_pd_reply_events) \
Matthew Smith78f487e2020-10-08 11:11:27 -0500392_(dhcp6_reply_events) \
393_(vrrp_vr_events)
Dave Barach6d963c22016-12-05 09:50:05 -0500394
Dave Barach6d963c22016-12-05 09:50:05 -0500395typedef struct
396{
397 u32 client_index; /* in memclnt registration pool */
398 u32 client_pid;
399} vpe_client_registration_t;
400
Dave Barach6d963c22016-12-05 09:50:05 -0500401typedef struct
402{
Neale Rannscbe25aa2019-09-30 10:53:31 +0000403#define _(a) \
404 uword *a##_registration_hash; \
405 vpe_client_registration_t * a##_registrations;
Dave Barach6d963c22016-12-05 09:50:05 -0500406 foreach_registration_hash
407#undef _
408 /* notifications happen really early in the game */
409 u8 link_state_process_up;
410
Dave Barach6d963c22016-12-05 09:50:05 -0500411 /* convenience */
412 vlib_main_t *vlib_main;
Florin Coras248210c2021-09-14 18:54:45 -0700413 struct vnet_main_t *vnet_main;
Dave Barach6d963c22016-12-05 09:50:05 -0500414} vpe_api_main_t;
415
416extern vpe_api_main_t vpe_api_main;
417
Dave Barachaff70772016-10-31 11:59:07 -0400418#endif /* __api_helper_macros_h__ */
419
420/*
421 * fd.io coding-style-patch-verification: ON
422 *
423 * Local Variables:
424 * eval: (c-set-style "gnu")
425 * End:
426 */