5c4dd9a6fd5516bf9165321874d3c648df14b89b
[vpp.git] / src / vlibapi / api_helper_macros.h
1 /*
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
20 #ifndef __api_helper_macros_h__
21 #define __api_helper_macros_h__
22
23 #define f64_endian(a)
24 #define f64_print(a,b)
25
26 #ifndef REPLY_MSG_ID_BASE
27 #define REPLY_MSG_ID_BASE 0
28 #endif
29
30 #define _NATIVE_TO_NETWORK(t, rmp)                                            \
31   api_main_t *am = vlibapi_get_main ();                                       \
32   void (*endian_fp) (void *);                                                 \
33   endian_fp = am->msg_endian_handlers[t + (REPLY_MSG_ID_BASE)];               \
34   (*endian_fp) (rmp);
35
36 #define REPLY_MACRO(t)                                                  \
37 do {                                                                    \
38     vl_api_registration_t *rp;                                          \
39     rp = vl_api_client_index_to_registration (mp->client_index);        \
40     if (rp == 0)                                                        \
41       return;                                                           \
42                                                                         \
43     rmp = vl_msg_api_alloc (sizeof (*rmp));                             \
44     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
45     rmp->context = mp->context;                                         \
46     rmp->retval = ntohl(rv);                                            \
47                                                                         \
48     vl_api_send_msg (rp, (u8 *)rmp);                                    \
49 } while(0);
50
51 #define REPLY_MACRO_END(t)                                                    \
52   do                                                                          \
53     {                                                                         \
54       vl_api_registration_t *rp;                                              \
55       rp = vl_api_client_index_to_registration (mp->client_index);            \
56       if (rp == 0)                                                            \
57         return;                                                               \
58                                                                               \
59       rmp = vl_msg_api_alloc (sizeof (*rmp));                                 \
60       rmp->_vl_msg_id = t + (REPLY_MSG_ID_BASE);                              \
61       rmp->context = mp->context;                                             \
62       rmp->retval = rv;                                                       \
63       _NATIVE_TO_NETWORK (t, rmp);                                            \
64       vl_api_send_msg (rp, (u8 *) rmp);                                       \
65     }                                                                         \
66   while (0);
67
68 #define REPLY_MACRO2(t, body)                                           \
69 do {                                                                    \
70     vl_api_registration_t *rp;                                          \
71     rp = vl_api_client_index_to_registration (mp->client_index);        \
72     if (rp == 0)                                                        \
73       return;                                                           \
74                                                                         \
75     rmp = vl_msg_api_alloc (sizeof (*rmp));                             \
76     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
77     rmp->context = mp->context;                                         \
78     rmp->retval = ntohl(rv);                                            \
79     do {body;} while (0);                                               \
80     vl_api_send_msg (rp, (u8 *)rmp);                                    \
81 } while(0);
82
83 #define REPLY_MACRO2_END(t, body)                                             \
84   do                                                                          \
85     {                                                                         \
86       vl_api_registration_t *rp;                                              \
87       rp = vl_api_client_index_to_registration (mp->client_index);            \
88       if (rp == 0)                                                            \
89         return;                                                               \
90                                                                               \
91       rmp = vl_msg_api_alloc (sizeof (*rmp));                                 \
92       rmp->_vl_msg_id = t + (REPLY_MSG_ID_BASE);                              \
93       rmp->context = mp->context;                                             \
94       rmp->retval = rv;                                                       \
95       do                                                                      \
96         {                                                                     \
97           body;                                                               \
98         }                                                                     \
99       while (0);                                                              \
100       _NATIVE_TO_NETWORK (t, rmp);                                            \
101       vl_api_send_msg (rp, (u8 *) rmp);                                       \
102     }                                                                         \
103   while (0);
104
105 #define REPLY_MACRO2_ZERO(t, body)                                      \
106 do {                                                                    \
107     vl_api_registration_t *rp;                                          \
108     rp = vl_api_client_index_to_registration (mp->client_index);        \
109     if (rp == 0)                                                        \
110       return;                                                           \
111                                                                         \
112     rmp = vl_msg_api_alloc_zero (sizeof (*rmp));                        \
113     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
114     rmp->context = mp->context;                                         \
115     rmp->retval = ntohl(rv);                                            \
116     do {body;} while (0);                                               \
117     vl_api_send_msg (rp, (u8 *)rmp);                                    \
118 } while(0);
119
120 #define REPLY_MACRO2_ZERO_END(t, body)                                        \
121   do                                                                          \
122     {                                                                         \
123       vl_api_registration_t *rp;                                              \
124       rp = vl_api_client_index_to_registration (mp->client_index);            \
125       if (rp == 0)                                                            \
126         return;                                                               \
127                                                                               \
128       rmp = vl_msg_api_alloc_zero (sizeof (*rmp));                            \
129       rmp->_vl_msg_id = ((t) + (REPLY_MSG_ID_BASE));                          \
130       rmp->context = mp->context;                                             \
131       rmp->retval = rv;                                                       \
132       do                                                                      \
133         {                                                                     \
134           body;                                                               \
135         }                                                                     \
136       while (0);                                                              \
137       _NATIVE_TO_NETWORK (t, rmp);                                            \
138       vl_api_send_msg (rp, (u8 *) rmp);                                       \
139     }                                                                         \
140   while (0);
141
142 #define REPLY_MACRO_DETAILS2(t, body)                                   \
143 do {                                                                    \
144     vl_api_registration_t *rp;                                          \
145     rp = vl_api_client_index_to_registration (mp->client_index);        \
146     if (rp == 0)                                                        \
147       return;                                                           \
148                                                                         \
149     rmp = vl_msg_api_alloc (sizeof (*rmp));                             \
150     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
151     rmp->context = mp->context;                                         \
152     do {body;} while (0);                                               \
153     vl_api_send_msg (rp, (u8 *)rmp);                                    \
154 } while(0);
155
156 #define REPLY_MACRO_DETAILS2_END(t, body)                                     \
157   do                                                                          \
158     {                                                                         \
159       vl_api_registration_t *rp;                                              \
160       rp = vl_api_client_index_to_registration (mp->client_index);            \
161       if (rp == 0)                                                            \
162         return;                                                               \
163                                                                               \
164       rmp = vl_msg_api_alloc (sizeof (*rmp));                                 \
165       rmp->_vl_msg_id = ((t) + (REPLY_MSG_ID_BASE));                          \
166       rmp->context = mp->context;                                             \
167       do                                                                      \
168         {                                                                     \
169           body;                                                               \
170         }                                                                     \
171       while (0);                                                              \
172       _NATIVE_TO_NETWORK (t, rmp);                                            \
173       vl_api_send_msg (rp, (u8 *) rmp);                                       \
174     }                                                                         \
175   while (0);
176
177 #define REPLY_MACRO_DETAILS4(t, rp, context, body)                      \
178 do {                                                                    \
179     rmp = vl_msg_api_alloc (sizeof (*rmp));                             \
180     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
181     rmp->context = context;                                             \
182     do {body;} while (0);                                               \
183     vl_api_send_msg (rp, (u8 *)rmp);                                    \
184 } while(0);
185
186 #define REPLY_MACRO_DETAILS4_END(t, rp, context, body)                        \
187   do                                                                          \
188     {                                                                         \
189       rmp = vl_msg_api_alloc (sizeof (*rmp));                                 \
190       rmp->_vl_msg_id = ((t) + (REPLY_MSG_ID_BASE));                          \
191       rmp->context = context;                                                 \
192       do                                                                      \
193         {                                                                     \
194           body;                                                               \
195         }                                                                     \
196       while (0);                                                              \
197       _NATIVE_TO_NETWORK (t, rmp);                                            \
198       vl_api_send_msg (rp, (u8 *) rmp);                                       \
199     }                                                                         \
200   while (0);
201
202 #define REPLY_MACRO_DETAILS5(t, n, rp, context, body)                         \
203   do                                                                          \
204     {                                                                         \
205       rmp = vl_msg_api_alloc (sizeof (*rmp) + n);                             \
206       rmp->_vl_msg_id = htons ((t) + (REPLY_MSG_ID_BASE));                    \
207       rmp->context = context;                                                 \
208       do                                                                      \
209         {                                                                     \
210           body;                                                               \
211         }                                                                     \
212       while (0);                                                              \
213       vl_api_send_msg (rp, (u8 *) rmp);                                       \
214     }                                                                         \
215   while (0);
216
217 #define REPLY_MACRO_DETAILS5_END(t, n, rp, context, body)                     \
218   do                                                                          \
219     {                                                                         \
220       rmp = vl_msg_api_alloc (sizeof (*rmp) + n);                             \
221       rmp->_vl_msg_id = ((t) + (REPLY_MSG_ID_BASE));                          \
222       rmp->context = context;                                                 \
223       do                                                                      \
224         {                                                                     \
225           body;                                                               \
226         }                                                                     \
227       while (0);                                                              \
228       _NATIVE_TO_NETWORK (t, rmp);                                            \
229       vl_api_send_msg (rp, (u8 *) rmp);                                       \
230     }                                                                         \
231   while (0);
232
233 #define REPLY_MACRO3(t, n, body)                                        \
234 do {                                                                    \
235     vl_api_registration_t *rp;                                          \
236     rp = vl_api_client_index_to_registration (mp->client_index);        \
237     if (rp == 0)                                                        \
238       return;                                                           \
239                                                                         \
240     rmp = vl_msg_api_alloc (sizeof (*rmp) + n);                         \
241     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
242     rmp->context = mp->context;                                         \
243     rmp->retval = ntohl(rv);                                            \
244     do {body;} while (0);                                               \
245     vl_api_send_msg (rp, (u8 *)rmp);                                    \
246 } while(0);
247
248 #define REPLY_MACRO3_END(t, n, body)                                          \
249   do                                                                          \
250     {                                                                         \
251       vl_api_registration_t *rp;                                              \
252       rp = vl_api_client_index_to_registration (mp->client_index);            \
253       if (rp == 0)                                                            \
254         return;                                                               \
255                                                                               \
256       rmp = vl_msg_api_alloc (sizeof (*rmp) + n);                             \
257       rmp->_vl_msg_id = ((t) + (REPLY_MSG_ID_BASE));                          \
258       rmp->context = mp->context;                                             \
259       rmp->retval = rv;                                                       \
260       do                                                                      \
261         {                                                                     \
262           body;                                                               \
263         }                                                                     \
264       while (0);                                                              \
265       _NATIVE_TO_NETWORK (t, rmp);                                            \
266       vl_api_send_msg (rp, (u8 *) rmp);                                       \
267     }                                                                         \
268   while (0);
269
270 #define REPLY_MACRO3_ZERO(t, n, body)                                   \
271 do {                                                                    \
272     vl_api_registration_t *rp;                                          \
273     rp = vl_api_client_index_to_registration (mp->client_index);        \
274     if (rp == 0)                                                        \
275       return;                                                           \
276                                                                         \
277     rmp = vl_msg_api_alloc_zero (sizeof (*rmp) + n);                    \
278     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
279     rmp->context = mp->context;                                         \
280     rmp->retval = ntohl(rv);                                            \
281     do {body;} while (0);                                               \
282     vl_api_send_msg (rp, (u8 *)rmp);                                    \
283 } while(0);
284
285 #define REPLY_MACRO3_ZERO_END(t, n, body)                                     \
286   do                                                                          \
287     {                                                                         \
288       vl_api_registration_t *rp;                                              \
289       rp = vl_api_client_index_to_registration (mp->client_index);            \
290       if (rp == 0)                                                            \
291         return;                                                               \
292                                                                               \
293       rmp = vl_msg_api_alloc_zero (sizeof (*rmp) + n);                        \
294       rmp->_vl_msg_id = ((t) + (REPLY_MSG_ID_BASE));                          \
295       rmp->context = mp->context;                                             \
296       rmp->retval = rv;                                                       \
297       do                                                                      \
298         {                                                                     \
299           body;                                                               \
300         }                                                                     \
301       while (0);                                                              \
302       _NATIVE_TO_NETWORK (t, rmp);                                            \
303       vl_api_send_msg (rp, (u8 *) rmp);                                       \
304     }                                                                         \
305   while (0);
306
307 #define REPLY_MACRO4(t, n, body)                                        \
308 do {                                                                    \
309     vl_api_registration_t *rp;                                          \
310     u8 is_error = 0;                                                    \
311                                                                         \
312     rp = vl_api_client_index_to_registration (mp->client_index);        \
313     if (rp == 0)                                                        \
314       return;                                                           \
315                                                                         \
316     rmp = vl_msg_api_alloc_or_null (sizeof (*rmp) + n);                 \
317     if (!rmp)                                                           \
318       {                                                                 \
319         /* if there isn't enough memory, try to allocate */             \
320         /* some at least for returning an error */                      \
321         rmp = vl_msg_api_alloc (sizeof (*rmp));                         \
322         if (!rmp)                                                       \
323           return;                                                       \
324                                                                         \
325         clib_memset (rmp, 0, sizeof (*rmp));                                 \
326         rv = VNET_API_ERROR_TABLE_TOO_BIG;                              \
327         is_error = 1;                                                   \
328       }                                                                 \
329     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
330     rmp->context = mp->context;                                         \
331     rmp->retval = ntohl(rv);                                            \
332     if (!is_error)                                                      \
333       do {body;} while (0);                                             \
334     vl_api_send_msg (rp, (u8 *)rmp);                                    \
335 } while(0);
336
337 #define REPLY_MACRO4_END(t, n, body)                                          \
338   do                                                                          \
339     {                                                                         \
340       vl_api_registration_t *rp;                                              \
341       u8 is_error = 0;                                                        \
342                                                                               \
343       rp = vl_api_client_index_to_registration (mp->client_index);            \
344       if (rp == 0)                                                            \
345         return;                                                               \
346                                                                               \
347       rmp = vl_msg_api_alloc_or_null (sizeof (*rmp) + n);                     \
348       if (!rmp)                                                               \
349         {                                                                     \
350           /* if there isn't enough memory, try to allocate */                 \
351           /* some at least for returning an error */                          \
352           rmp = vl_msg_api_alloc (sizeof (*rmp));                             \
353           if (!rmp)                                                           \
354             return;                                                           \
355                                                                               \
356           clib_memset (rmp, 0, sizeof (*rmp));                                \
357           rv = VNET_API_ERROR_TABLE_TOO_BIG;                                  \
358           is_error = 1;                                                       \
359         }                                                                     \
360       rmp->_vl_msg_id = ((t) + (REPLY_MSG_ID_BASE));                          \
361       rmp->context = mp->context;                                             \
362       rmp->retval = rv;                                                       \
363       if (!is_error)                                                          \
364         do                                                                    \
365           {                                                                   \
366             body;                                                             \
367           }                                                                   \
368         while (0);                                                            \
369       _NATIVE_TO_NETWORK (t, rmp);                                            \
370       vl_api_send_msg (rp, (u8 *) rmp);                                       \
371     }                                                                         \
372   while (0);
373
374 #define REPLY_AND_DETAILS_MACRO(t, p, body)                                   \
375   do                                                                          \
376     {                                                                         \
377       if (pool_elts (p) == 0)                                                 \
378         {                                                                     \
379           REPLY_MACRO (t);                                                    \
380           break;                                                              \
381         }                                                                     \
382       vl_api_registration_t *rp;                                              \
383       rp = vl_api_client_index_to_registration (mp->client_index);            \
384       if (rp == 0)                                                            \
385         return;                                                               \
386       u32 cursor = clib_net_to_host_u32 (mp->cursor);                         \
387       vlib_main_t *vm = vlib_get_main ();                                     \
388       f64 start = vlib_time_now (vm);                                         \
389       if (pool_is_free_index (p, cursor))                                     \
390         {                                                                     \
391           cursor = pool_next_index (p, cursor);                               \
392           if (cursor == ~0)                                                   \
393             rv = VNET_API_ERROR_INVALID_VALUE;                                \
394         }                                                                     \
395       while (cursor != ~0)                                                    \
396         {                                                                     \
397           do                                                                  \
398             {                                                                 \
399               body;                                                           \
400             }                                                                 \
401           while (0);                                                          \
402           cursor = pool_next_index (p, cursor);                               \
403           if (vl_api_process_may_suspend (vm, rp, start))                     \
404             {                                                                 \
405               if (cursor != ~0)                                               \
406                 rv = VNET_API_ERROR_EAGAIN;                                   \
407               break;                                                          \
408             }                                                                 \
409         }                                                                     \
410       REPLY_MACRO2 (t, ({ rmp->cursor = clib_host_to_net_u32 (cursor); }));   \
411     }                                                                         \
412   while (0);
413
414 #define REPLY_AND_DETAILS_MACRO_END(t, p, body)                               \
415   do                                                                          \
416     {                                                                         \
417       if (pool_elts (p) == 0)                                                 \
418         {                                                                     \
419           REPLY_MACRO_END (t);                                                \
420           break;                                                              \
421         }                                                                     \
422       vl_api_registration_t *rp;                                              \
423       rp = vl_api_client_index_to_registration (mp->client_index);            \
424       if (rp == 0)                                                            \
425         return;                                                               \
426       u32 cursor = mp->cursor;                                                \
427       vlib_main_t *vm = vlib_get_main ();                                     \
428       f64 start = vlib_time_now (vm);                                         \
429       if (pool_is_free_index (p, cursor))                                     \
430         {                                                                     \
431           cursor = pool_next_index (p, cursor);                               \
432           if (cursor == ~0)                                                   \
433             rv = VNET_API_ERROR_INVALID_VALUE;                                \
434         }                                                                     \
435       while (cursor != ~0)                                                    \
436         {                                                                     \
437           do                                                                  \
438             {                                                                 \
439               body;                                                           \
440             }                                                                 \
441           while (0);                                                          \
442           cursor = pool_next_index (p, cursor);                               \
443           if (vl_api_process_may_suspend (vm, rp, start))                     \
444             {                                                                 \
445               if (cursor != ~0)                                               \
446                 rv = VNET_API_ERROR_EAGAIN;                                   \
447               break;                                                          \
448             }                                                                 \
449         }                                                                     \
450       REPLY_MACRO2_END (t, ({ rmp->cursor = cursor; }));                      \
451     }                                                                         \
452   while (0);
453
454 #define REPLY_AND_DETAILS_VEC_MACRO(t, v, mp, rmp, rv, body)    \
455 do {                                                            \
456   vl_api_registration_t *rp;                                    \
457   rp = vl_api_client_index_to_registration (mp->client_index);  \
458   if (rp == 0)                                                  \
459     return;                                                     \
460   u32 cursor = clib_net_to_host_u32 (mp->cursor);               \
461   vlib_main_t *vm = vlib_get_main ();                           \
462   f64 start = vlib_time_now (vm);                               \
463   if (!v || vec_len (v) == 0) {                                 \
464     cursor = ~0;                                                \
465     rv = VNET_API_ERROR_INVALID_VALUE;                          \
466   } else if (cursor == ~0)                                      \
467       cursor = 0;                                               \
468   while (cursor != ~0 && cursor < vec_len (v)) {                \
469     do {body;} while (0);                                       \
470     ++cursor;                                                   \
471     if (vl_api_process_may_suspend (vm, rp, start)) {           \
472       if (cursor < vec_len (v))                                 \
473         rv = VNET_API_ERROR_EAGAIN;                             \
474       break;                                                    \
475     }                                                           \
476   }                                                             \
477   REPLY_MACRO2 (t, ({                                           \
478     rmp->cursor = clib_host_to_net_u32 (cursor);                \
479   }));                                                          \
480 } while(0);
481
482 #define REPLY_AND_DETAILS_VEC_MACRO_END(t, v, mp, rmp, rv, body)              \
483   do                                                                          \
484     {                                                                         \
485       vl_api_registration_t *rp;                                              \
486       rp = vl_api_client_index_to_registration (mp->client_index);            \
487       if (rp == 0)                                                            \
488         return;                                                               \
489       u32 cursor = mp->cursor;                                                \
490       vlib_main_t *vm = vlib_get_main ();                                     \
491       f64 start = vlib_time_now (vm);                                         \
492       if (!v || vec_len (v) == 0)                                             \
493         {                                                                     \
494           cursor = ~0;                                                        \
495           rv = VNET_API_ERROR_INVALID_VALUE;                                  \
496         }                                                                     \
497       else if (cursor == ~0)                                                  \
498         cursor = 0;                                                           \
499       while (cursor != ~0 && cursor < vec_len (v))                            \
500         {                                                                     \
501           do                                                                  \
502             {                                                                 \
503               body;                                                           \
504             }                                                                 \
505           while (0);                                                          \
506           ++cursor;                                                           \
507           if (vl_api_process_may_suspend (vm, rp, start))                     \
508             {                                                                 \
509               if (cursor < vec_len (v))                                       \
510                 rv = VNET_API_ERROR_EAGAIN;                                   \
511               break;                                                          \
512             }                                                                 \
513         }                                                                     \
514       REPLY_MACRO2_END (t, ({ rmp->cursor = cursor; }));                      \
515     }                                                                         \
516   while (0);
517
518 /* "trust, but verify" */
519 #define vnet_sw_if_index_is_api_valid(sw_if_index)                            \
520   vnet_sw_interface_is_api_valid (vnet_get_main (), sw_if_index)
521
522 #define VALIDATE_SW_IF_INDEX(mp)                                \
523  do { u32 __sw_if_index = ntohl((mp)->sw_if_index);             \
524     if (!vnet_sw_if_index_is_api_valid(__sw_if_index)) {        \
525         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
526         goto bad_sw_if_index;                                   \
527     }                                                           \
528 } while(0);
529
530 #define VALIDATE_SW_IF_INDEX_END(mp)                                          \
531   do                                                                          \
532     {                                                                         \
533       if (!vnet_sw_if_index_is_api_valid ((mp)->sw_if_index))                 \
534         {                                                                     \
535           rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                            \
536           goto bad_sw_if_index;                                               \
537         }                                                                     \
538     }                                                                         \
539   while (0);
540
541 #define BAD_SW_IF_INDEX_LABEL                   \
542 do {                                            \
543 bad_sw_if_index:                                \
544     ;                                           \
545 } while (0);
546
547 #define VALIDATE_RX_SW_IF_INDEX(mp)                             \
548  do { u32 __rx_sw_if_index = ntohl((mp)->rx_sw_if_index);       \
549     if (!vnet_sw_if_index_is_api_valid(__rx_sw_if_index)) {     \
550         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
551         goto bad_rx_sw_if_index;                                \
552     }                                                           \
553 } while(0);
554
555 #define VALIDATE_RX_SW_IF_INDEX_END(mp)                                       \
556   do                                                                          \
557     {                                                                         \
558       if (!vnet_sw_if_index_is_api_valid ((mp)->rx_sw_if_index))              \
559         {                                                                     \
560           rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                            \
561           goto bad_rx_sw_if_index;                                            \
562         }                                                                     \
563     }                                                                         \
564   while (0);
565
566 #define BAD_RX_SW_IF_INDEX_LABEL                \
567 do {                                            \
568 bad_rx_sw_if_index:                             \
569     ;                                           \
570 } while (0);
571
572 #define VALIDATE_TX_SW_IF_INDEX(mp)                             \
573  do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index);         \
574     if (!vnet_sw_if_index_is_api_valid(__tx_sw_if_index)) {     \
575         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
576         goto bad_tx_sw_if_index;                                \
577     }                                                           \
578 } while(0);
579
580 #define VALIDATE_TX_SW_IF_INDEX_END(mp)                                       \
581   do                                                                          \
582     {                                                                         \
583       if (!vnet_sw_if_index_is_api_valid (mp->tx_sw_if_index))                \
584         {                                                                     \
585           rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                            \
586           goto bad_tx_sw_if_index;                                            \
587         }                                                                     \
588     }                                                                         \
589   while (0);
590
591 #define BAD_TX_SW_IF_INDEX_LABEL                \
592 do {                                            \
593 bad_tx_sw_if_index:                             \
594     ;                                           \
595 } while (0);
596
597 #define VALIDATE_BD_ID(mp)                      \
598  do { u32 __rx_bd_id = ntohl(mp->bd_id);        \
599     if (__rx_bd_id > L2_BD_ID_MAX) {            \
600         rv = VNET_API_ERROR_BD_ID_EXCEED_MAX;   \
601         goto bad_bd_id;                         \
602     }                                           \
603 } while(0);
604
605 #define VALIDATE_BD_ID_END(mp)                                                \
606   do                                                                          \
607     {                                                                         \
608       if (mp->bd_id > L2_BD_ID_MAX)                                           \
609         {                                                                     \
610           rv = VNET_API_ERROR_BD_ID_EXCEED_MAX;                               \
611           goto bad_bd_id;                                                     \
612         }                                                                     \
613     }                                                                         \
614   while (0);
615
616 #define BAD_BD_ID_LABEL                         \
617 do {                                            \
618 bad_bd_id:                                      \
619     ;                                           \
620 } while (0);
621
622 #define pub_sub_handler(lca,UCA)                                        \
623 static void vl_api_want_##lca##_t_handler (                             \
624     vl_api_want_##lca##_t *mp)                                          \
625 {                                                                       \
626     vpe_api_main_t *vam = &vpe_api_main;                                \
627     vpe_client_registration_t *rp;                                      \
628     vl_api_want_##lca##_reply_t *rmp;                                   \
629     uword *p;                                                           \
630     i32 rv = 0;                                                         \
631                                                                         \
632     p = hash_get (vam->lca##_registration_hash, mp->client_index);      \
633     if (p) {                                                            \
634         if (mp->enable_disable) {                                       \
635             clib_warning ("pid %d: already enabled...", ntohl(mp->pid)); \
636             rv = VNET_API_ERROR_INVALID_REGISTRATION;                   \
637             goto reply;                                                 \
638         } else {                                                        \
639             rp = pool_elt_at_index (vam->lca##_registrations, p[0]);    \
640             pool_put (vam->lca##_registrations, rp);                    \
641             hash_unset (vam->lca##_registration_hash,                   \
642                 mp->client_index);                                      \
643             goto reply;                                                 \
644         }                                                               \
645     }                                                                   \
646     if (mp->enable_disable == 0) {                                      \
647         clib_warning ("pid %d: already disabled...", mp->pid);          \
648         rv = VNET_API_ERROR_INVALID_REGISTRATION;                       \
649         goto reply;                                                     \
650     }                                                                   \
651     pool_get (vam->lca##_registrations, rp);                            \
652     rp->client_index = mp->client_index;                                \
653     rp->client_pid = mp->pid;                                           \
654     hash_set (vam->lca##_registration_hash, rp->client_index,           \
655               rp - vam->lca##_registrations);                           \
656                                                                         \
657 reply:                                                                  \
658     REPLY_MACRO (VL_API_WANT_##UCA##_REPLY);                            \
659 }                                                                       \
660                                                                         \
661 static clib_error_t * vl_api_want_##lca##_t_reaper (u32 client_index)   \
662 {                                                                       \
663     vpe_api_main_t *vam = &vpe_api_main;                                \
664     vpe_client_registration_t *rp;                                      \
665     uword *p;                                                           \
666                                                                         \
667     p = hash_get (vam->lca##_registration_hash, client_index);          \
668     if (p)                                                              \
669       {                                                                 \
670         rp = pool_elt_at_index (vam->lca##_registrations, p[0]);        \
671         pool_put (vam->lca##_registrations, rp);                        \
672         hash_unset (vam->lca##_registration_hash, client_index);        \
673       }                                                                 \
674     return (NULL);                                                      \
675 }                                                                       \
676                                                                         \
677 VL_MSG_API_REAPER_FUNCTION (vl_api_want_##lca##_t_reaper);              \
678
679 #define foreach_registration_hash               \
680 _(interface_events)                             \
681 _(to_netconf_server)                            \
682 _(from_netconf_server)                          \
683 _(to_netconf_client)                            \
684 _(from_netconf_client)                          \
685 _(oam_events)                                   \
686 _(bfd_events)                                   \
687 _(l2_arp_term_events)                           \
688 _(ip6_ra_events)                                \
689 _(dhcp6_pd_reply_events)                        \
690 _(dhcp6_reply_events)                           \
691 _(vrrp_vr_events)
692
693 typedef struct
694 {
695   u32 client_index;             /* in memclnt registration pool */
696   u32 client_pid;
697 } vpe_client_registration_t;
698
699 typedef struct
700 {
701 #define _(a)                                            \
702   uword *a##_registration_hash;                         \
703   vpe_client_registration_t * a##_registrations;
704   foreach_registration_hash
705 #undef _
706     /* notifications happen really early in the game */
707   u8 link_state_process_up;
708
709   /* convenience */
710   vlib_main_t *vlib_main;
711   struct vnet_main_t *vnet_main;
712 } vpe_api_main_t;
713
714 extern vpe_api_main_t vpe_api_main;
715
716 #endif /* __api_helper_macros_h__ */
717
718 /*
719  * fd.io coding-style-patch-verification: ON
720  *
721  * Local Variables:
722  * eval: (c-set-style "gnu")
723  * End:
724  */