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