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