16f34cfc762ef1bacd8307c9838539d7f7984b1a
[vpp.git] / vlib-api / 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
21 #ifndef __api_helper_macros_h__
22 #define __api_helper_macros_h__
23
24 #define f64_endian(a)
25 #define f64_print(a,b)
26
27 #define REPLY_MACRO(t)                                          \
28 do {                                                            \
29     unix_shared_memory_queue_t * q;                             \
30     rv = vl_msg_api_pd_handler (mp, rv);                        \
31     q = vl_api_client_index_to_input_queue (mp->client_index);  \
32     if (!q)                                                     \
33         return;                                                 \
34                                                                 \
35     rmp = vl_msg_api_alloc (sizeof (*rmp));                     \
36     rmp->_vl_msg_id = ntohs((t));                               \
37     rmp->context = mp->context;                                 \
38     rmp->retval = ntohl(rv);                                    \
39                                                                 \
40     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
41 } while(0);
42
43 #define REPLY_MACRO2(t, body)                                   \
44 do {                                                            \
45     unix_shared_memory_queue_t * q;                             \
46     rv = vl_msg_api_pd_handler (mp, rv);                        \
47     q = vl_api_client_index_to_input_queue (mp->client_index);  \
48     if (!q)                                                     \
49         return;                                                 \
50                                                                 \
51     rmp = vl_msg_api_alloc (sizeof (*rmp));                     \
52     rmp->_vl_msg_id = ntohs((t));                               \
53     rmp->context = mp->context;                                 \
54     rmp->retval = ntohl(rv);                                    \
55     do {body;} while (0);                                       \
56     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
57 } while(0);
58
59 #define REPLY_MACRO3(t, n, body)                                \
60 do {                                                            \
61     unix_shared_memory_queue_t * q;                             \
62     rv = vl_msg_api_pd_handler (mp, rv);                        \
63     q = vl_api_client_index_to_input_queue (mp->client_index);  \
64     if (!q)                                                     \
65         return;                                                 \
66                                                                 \
67     rmp = vl_msg_api_alloc (sizeof (*rmp) + n);                 \
68     rmp->_vl_msg_id = ntohs((t));                               \
69     rmp->context = mp->context;                                 \
70     rmp->retval = ntohl(rv);                                    \
71     do {body;} while (0);                                       \
72     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
73 } while(0);
74
75 #define REPLY_MACRO4(t, n, body)                                \
76 do {                                                            \
77     unix_shared_memory_queue_t * q;                             \
78     u8 is_error = 0;                                            \
79     rv = vl_msg_api_pd_handler (mp, rv);                        \
80     q = vl_api_client_index_to_input_queue (mp->client_index);  \
81     if (!q)                                                     \
82         return;                                                 \
83                                                                 \
84     rmp = vl_msg_api_alloc_or_null (sizeof (*rmp) + n);         \
85     if (!rmp)                                                   \
86       {                                                         \
87         /* if there isn't enough memory, try to allocate */     \
88         /* some at least for returning an error */              \
89         rmp = vl_msg_api_alloc (sizeof (*rmp));                 \
90         if (!rmp)                                               \
91           return;                                               \
92                                                                 \
93         memset (rmp, 0, sizeof (*rmp));                         \
94         rv = VNET_API_ERROR_TABLE_TOO_BIG;                      \
95         is_error = 1;                                           \
96       }                                                         \
97     rmp->_vl_msg_id = ntohs((t));                               \
98     rmp->context = mp->context;                                 \
99     rmp->retval = ntohl(rv);                                    \
100     if (!is_error)                                              \
101       do {body;} while (0);                                     \
102     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
103 } while(0);
104
105 /* "trust, but verify" */
106
107 #define VALIDATE_SW_IF_INDEX(mp)                                \
108  do { u32 __sw_if_index = ntohl(mp->sw_if_index);               \
109     vnet_main_t *__vnm = vnet_get_main();                       \
110     if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
111                            __sw_if_index)) {                    \
112         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
113         goto bad_sw_if_index;                                   \
114     }                                                           \
115 } while(0);
116
117 #define BAD_SW_IF_INDEX_LABEL                   \
118 do {                                            \
119 bad_sw_if_index:                                \
120     ;                                           \
121 } while (0);
122
123 #define VALIDATE_RX_SW_IF_INDEX(mp)                             \
124  do { u32 __rx_sw_if_index = ntohl(mp->rx_sw_if_index);         \
125     vnet_main_t *__vnm = vnet_get_main();                       \
126     if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
127                            __rx_sw_if_index)) {                 \
128         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
129         goto bad_rx_sw_if_index;                                \
130     }                                                           \
131 } while(0);
132
133 #define BAD_RX_SW_IF_INDEX_LABEL                \
134 do {                                            \
135 bad_rx_sw_if_index:                             \
136     ;                                           \
137 } while (0);
138
139 #define VALIDATE_TX_SW_IF_INDEX(mp)                             \
140  do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index);         \
141     vnet_main_t *__vnm = vnet_get_main();                       \
142     if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
143                            __tx_sw_if_index)) {                 \
144         rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;                \
145         goto bad_tx_sw_if_index;                                \
146     }                                                           \
147 } while(0);
148
149 #define BAD_TX_SW_IF_INDEX_LABEL                \
150 do {                                            \
151 bad_tx_sw_if_index:                             \
152     ;                                           \
153 } while (0);
154
155 #define pub_sub_handler(lca,UCA)                                        \
156 static void vl_api_want_##lca##_t_handler (                             \
157     vl_api_want_##lca##_t *mp)                                          \
158 {                                                                       \
159     vpe_api_main_t *vam = &vpe_api_main;                                \
160     vpe_client_registration_t *rp;                                      \
161     vl_api_want_##lca##_reply_t *rmp;                                   \
162     uword *p;                                                           \
163     i32 rv = 0;                                                         \
164                                                                         \
165     p = hash_get (vam->lca##_registration_hash, mp->client_index);      \
166     if (p) {                                                            \
167         if (mp->enable_disable) {                                       \
168             clib_warning ("pid %d: already enabled...", mp->pid);       \
169             rv = VNET_API_ERROR_INVALID_REGISTRATION;                   \
170             goto reply;                                                 \
171         } else {                                                        \
172             rp = pool_elt_at_index (vam->lca##_registrations, p[0]);    \
173             pool_put (vam->lca##_registrations, rp);                    \
174             hash_unset (vam->lca##_registration_hash,                   \
175                 mp->client_index);                                      \
176             goto reply;                                                 \
177         }                                                               \
178     }                                                                   \
179     if (mp->enable_disable == 0) {                                      \
180         clib_warning ("pid %d: already disabled...", mp->pid);          \
181         rv = VNET_API_ERROR_INVALID_REGISTRATION;                       \
182         goto reply;                                                     \
183     }                                                                   \
184     pool_get (vam->lca##_registrations, rp);                            \
185     rp->client_index = mp->client_index;                                \
186     rp->client_pid = mp->pid;                                           \
187     hash_set (vam->lca##_registration_hash, rp->client_index,           \
188               rp - vam->lca##_registrations);                           \
189                                                                         \
190 reply:                                                                  \
191     REPLY_MACRO (VL_API_WANT_##UCA##_REPLY);                            \
192 }
193
194 #define foreach_registration_hash               \
195 _(interface_events)                             \
196 _(to_netconf_server)                            \
197 _(from_netconf_server)                          \
198 _(to_netconf_client)                            \
199 _(from_netconf_client)                          \
200 _(oam_events)                                   \
201 _(bfd_events)
202
203 /* WARNING: replicated in vpp/stats.h */
204 typedef struct
205 {
206   u32 client_index;             /* in memclnt registration pool */
207   u32 client_pid;
208 } vpe_client_registration_t;
209
210 struct _vl_api_ip4_arp_event;
211 struct _vl_api_ip6_nd_event;
212
213 typedef struct
214 {
215 #define _(a) uword *a##_registration_hash;              \
216     vpe_client_registration_t * a##_registrations;
217   foreach_registration_hash
218 #undef _
219     /* notifications happen really early in the game */
220   u8 link_state_process_up;
221
222   /* ip4 arp event registration pool */
223   struct _vl_api_ip4_arp_event *arp_events;
224
225   /* ip6 nd event registration pool */
226   struct _vl_api_ip6_nd_event *nd_events;
227
228   /* convenience */
229   vlib_main_t *vlib_main;
230   vnet_main_t *vnet_main;
231 } vpe_api_main_t;
232
233 extern vpe_api_main_t vpe_api_main;
234
235 #endif /* __api_helper_macros_h__ */
236
237 /*
238  * fd.io coding-style-patch-verification: ON
239  *
240  * Local Variables:
241  * eval: (c-set-style "gnu")
242  * End:
243  */