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