Implement DHCPv6 IA NA client (VPP-1094)
[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 REPLY_MACRO(t)                                                  \
31 do {                                                                    \
32     vl_api_registration_t *rp;                                          \
33     rv = vl_msg_api_pd_handler (mp, rv);                                \
34     rp = vl_api_client_index_to_registration (mp->client_index);        \
35     if (rp == 0)                                                        \
36       return;                                                           \
37                                                                         \
38     rmp = vl_msg_api_alloc (sizeof (*rmp));                             \
39     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
40     rmp->context = mp->context;                                         \
41     rmp->retval = ntohl(rv);                                            \
42                                                                         \
43     vl_api_send_msg (rp, (u8 *)rmp);                                    \
44 } while(0);
45
46 #define REPLY_MACRO2(t, body)                                           \
47 do {                                                                    \
48     vl_api_registration_t *rp;                                          \
49     rv = vl_msg_api_pd_handler (mp, rv);                                \
50     rp = vl_api_client_index_to_registration (mp->client_index);        \
51     if (rp == 0)                                                        \
52       return;                                                           \
53                                                                         \
54     rmp = vl_msg_api_alloc (sizeof (*rmp));                             \
55     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
56     rmp->context = mp->context;                                         \
57     rmp->retval = ntohl(rv);                                            \
58     do {body;} while (0);                                               \
59     vl_api_send_msg (rp, (u8 *)rmp);                                    \
60 } while(0);
61
62 #define REPLY_MACRO3(t, n, body)                                        \
63 do {                                                                    \
64     vl_api_registration_t *rp;                                          \
65     rv = vl_msg_api_pd_handler (mp, rv);                                \
66     rp = vl_api_client_index_to_registration (mp->client_index);        \
67     if (rp == 0)                                                        \
68       return;                                                           \
69                                                                         \
70     rmp = vl_msg_api_alloc (sizeof (*rmp) + n);                         \
71     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
72     rmp->context = mp->context;                                         \
73     rmp->retval = ntohl(rv);                                            \
74     do {body;} while (0);                                               \
75     vl_api_send_msg (rp, (u8 *)rmp);                                    \
76 } while(0);
77
78 #define REPLY_MACRO4(t, n, body)                                        \
79 do {                                                                    \
80     vl_api_registration_t *rp;                                          \
81     u8 is_error = 0;                                                    \
82     rv = vl_msg_api_pd_handler (mp, rv);                                \
83                                                                         \
84     rp = vl_api_client_index_to_registration (mp->client_index);        \
85     if (rp == 0)                                                        \
86       return;                                                           \
87                                                                         \
88     rmp = vl_msg_api_alloc_or_null (sizeof (*rmp) + n);                 \
89     if (!rmp)                                                           \
90       {                                                                 \
91         /* if there isn't enough memory, try to allocate */             \
92         /* some at least for returning an error */                      \
93         rmp = vl_msg_api_alloc (sizeof (*rmp));                         \
94         if (!rmp)                                                       \
95           return;                                                       \
96                                                                         \
97         memset (rmp, 0, sizeof (*rmp));                                 \
98         rv = VNET_API_ERROR_TABLE_TOO_BIG;                              \
99         is_error = 1;                                                   \
100       }                                                                 \
101     rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE));                   \
102     rmp->context = mp->context;                                         \
103     rmp->retval = ntohl(rv);                                            \
104     if (!is_error)                                                      \
105       do {body;} while (0);                                             \
106     vl_api_send_msg (rp, (u8 *)rmp);                                    \
107 } while(0);
108
109 /* "trust, but verify" */
110
111 static inline uword
112 vnet_sw_if_index_is_api_valid (u32 sw_if_index)
113 {
114   return vnet_sw_interface_is_api_valid (vnet_get_main (), sw_if_index);
115 }
116
117 #define VALIDATE_SW_IF_INDEX(mp)                                \
118  do { u32 __sw_if_index = ntohl(mp->sw_if_index);               \
119     if (!vnet_sw_if_index_is_api_valid(__sw_if_index)) {        \
120         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
121         goto bad_sw_if_index;                                   \
122     }                                                           \
123 } while(0);
124
125 #define BAD_SW_IF_INDEX_LABEL                   \
126 do {                                            \
127 bad_sw_if_index:                                \
128     ;                                           \
129 } while (0);
130
131 #define VALIDATE_RX_SW_IF_INDEX(mp)                             \
132  do { u32 __rx_sw_if_index = ntohl(mp->rx_sw_if_index);         \
133     if (!vnet_sw_if_index_is_api_valid(__rx_sw_if_index)) {     \
134         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
135         goto bad_rx_sw_if_index;                                \
136     }                                                           \
137 } while(0);
138
139 #define BAD_RX_SW_IF_INDEX_LABEL                \
140 do {                                            \
141 bad_rx_sw_if_index:                             \
142     ;                                           \
143 } while (0);
144
145 #define VALIDATE_TX_SW_IF_INDEX(mp)                             \
146  do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index);         \
147     if (!vnet_sw_if_index_is_api_valid(__tx_sw_if_index)) {     \
148         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
149         goto bad_tx_sw_if_index;                                \
150     }                                                           \
151 } while(0);
152
153 #define BAD_TX_SW_IF_INDEX_LABEL                \
154 do {                                            \
155 bad_tx_sw_if_index:                             \
156     ;                                           \
157 } while (0);
158
159 #define VALIDATE_BD_ID(mp)                      \
160  do { u32 __rx_bd_id = ntohl(mp->bd_id);        \
161     if (__rx_bd_id > L2_BD_ID_MAX) {            \
162         rv = VNET_API_ERROR_BD_ID_EXCEED_MAX;   \
163         goto bad_bd_id;                         \
164     }                                           \
165 } while(0);
166
167 #define BAD_BD_ID_LABEL                         \
168 do {                                            \
169 bad_bd_id:                                      \
170     ;                                           \
171 } while (0);
172
173 #define pub_sub_handler(lca,UCA)                                        \
174 static void vl_api_want_##lca##_t_handler (                             \
175     vl_api_want_##lca##_t *mp)                                          \
176 {                                                                       \
177     vpe_api_main_t *vam = &vpe_api_main;                                \
178     vpe_client_registration_t *rp;                                      \
179     vl_api_want_##lca##_reply_t *rmp;                                   \
180     uword *p;                                                           \
181     i32 rv = 0;                                                         \
182                                                                         \
183     p = hash_get (vam->lca##_registration_hash, mp->client_index);      \
184     if (p) {                                                            \
185         if (mp->enable_disable) {                                       \
186             clib_warning ("pid %d: already enabled...", mp->pid);       \
187             rv = VNET_API_ERROR_INVALID_REGISTRATION;                   \
188             goto reply;                                                 \
189         } else {                                                        \
190             rp = pool_elt_at_index (vam->lca##_registrations, p[0]);    \
191             pool_put (vam->lca##_registrations, rp);                    \
192             hash_unset (vam->lca##_registration_hash,                   \
193                 mp->client_index);                                      \
194             goto reply;                                                 \
195         }                                                               \
196     }                                                                   \
197     if (mp->enable_disable == 0) {                                      \
198         clib_warning ("pid %d: already disabled...", mp->pid);          \
199         rv = VNET_API_ERROR_INVALID_REGISTRATION;                       \
200         goto reply;                                                     \
201     }                                                                   \
202     pool_get (vam->lca##_registrations, rp);                            \
203     rp->client_index = mp->client_index;                                \
204     rp->client_pid = mp->pid;                                           \
205     hash_set (vam->lca##_registration_hash, rp->client_index,           \
206               rp - vam->lca##_registrations);                           \
207                                                                         \
208 reply:                                                                  \
209     REPLY_MACRO (VL_API_WANT_##UCA##_REPLY);                            \
210 }                                                                       \
211                                                                         \
212 static clib_error_t * vl_api_want_##lca##_t_reaper (u32 client_index)   \
213 {                                                                       \
214     vpe_api_main_t *vam = &vpe_api_main;                                \
215     vpe_client_registration_t *rp;                                      \
216     uword *p;                                                           \
217                                                                         \
218     p = hash_get (vam->lca##_registration_hash, client_index);          \
219     if (p)                                                              \
220       {                                                                 \
221         rp = pool_elt_at_index (vam->lca##_registrations, p[0]);        \
222         pool_put (vam->lca##_registrations, rp);                        \
223         hash_unset (vam->lca##_registration_hash, client_index);        \
224       }                                                                 \
225     return (NULL);                                                      \
226 }                                                                       \
227                                                                         \
228 VL_MSG_API_REAPER_FUNCTION (vl_api_want_##lca##_t_reaper);              \
229
230 #define foreach_registration_hash               \
231 _(interface_events)                             \
232 _(to_netconf_server)                            \
233 _(from_netconf_server)                          \
234 _(to_netconf_client)                            \
235 _(from_netconf_client)                          \
236 _(oam_events)                                   \
237 _(bfd_events)                                   \
238 _(wc_ip6_nd_events)                             \
239 _(wc_ip4_arp_events)                            \
240 _(ip6_ra_events)                                \
241 _(dhcp6_pd_reply_events)                        \
242 _(dhcp6_reply_events)
243
244 typedef struct
245 {
246   u32 client_index;             /* in memclnt registration pool */
247   u32 client_pid;
248 } vpe_client_registration_t;
249
250 struct _vl_api_ip4_arp_event;
251 struct _vl_api_ip6_nd_event;
252
253 typedef struct
254 {
255 #define _(a) uword *a##_registration_hash;              \
256     vpe_client_registration_t * a##_registrations;
257   foreach_registration_hash
258 #undef _
259     /* notifications happen really early in the game */
260   u8 link_state_process_up;
261
262   /* ip4 arp event registration pool */
263   struct _vl_api_ip4_arp_event *arp_events;
264
265   /* ip6 nd event registration pool */
266   struct _vl_api_ip6_nd_event *nd_events;
267
268   /* convenience */
269   vlib_main_t *vlib_main;
270   vnet_main_t *vnet_main;
271 } vpe_api_main_t;
272
273 extern vpe_api_main_t vpe_api_main;
274
275 #endif /* __api_helper_macros_h__ */
276
277 /*
278  * fd.io coding-style-patch-verification: ON
279  *
280  * Local Variables:
281  * eval: (c-set-style "gnu")
282  * End:
283  */