ip: Use .api declarative counters for ICMP.
[vpp.git] / src / vnet / ip / punt_api.c
1 /*
2  *------------------------------------------------------------------
3  * punt_api.c - Punt api
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 #include <vnet/vnet.h>
21 #include <vlibmemory/api.h>
22 #include <vnet/ip/punt.h>
23 #include <vnet/ip/ip_types_api.h>
24
25 #include <vnet/format_fns.h>
26 #include <vnet/ip/punt.api_enum.h>
27 #include <vnet/ip/punt.api_types.h>
28
29 #define REPLY_MSG_ID_BASE punt_main.msg_id_base
30 #include <vlibapi/api_helper_macros.h>
31
32 static int
33 vl_api_punt_type_decode (vl_api_punt_type_t in, punt_type_t * out)
34 {
35   in = clib_net_to_host_u32 (in);
36
37   switch (in)
38     {
39 #define _(v, s)                                 \
40       case PUNT_API_TYPE_##v:                   \
41         *out = PUNT_TYPE_##v;                   \
42         return (0);
43       foreach_punt_type
44 #undef _
45     }
46
47   return (-1);
48 }
49
50 static vl_api_punt_type_t
51 vl_api_punt_type_encode (punt_type_t in)
52 {
53   vl_api_punt_type_t pt = PUNT_API_TYPE_L4;
54
55   switch (in)
56     {
57 #define _(v, s)                                   \
58       case PUNT_TYPE_##v:                         \
59         pt = PUNT_API_TYPE_##v;                   \
60         break;
61       foreach_punt_type
62 #undef _
63     }
64
65   return (clib_host_to_net_u32 (pt));
66 }
67
68 static int
69 vl_api_punt_l4_decode (const vl_api_punt_l4_t * in, punt_l4_t * out)
70 {
71   int rv;
72
73   rv = ip_address_family_decode (in->af, &out->af);
74   if (rv < 0)
75     return (rv);
76   rv = ip_proto_decode (in->protocol, &out->protocol);
77   if (rv < 0)
78     return (rv);
79   out->port = clib_net_to_host_u16 (in->port);
80
81   return (rv);
82 }
83
84 static int
85 vl_api_punt_ip_proto_decode (const vl_api_punt_ip_proto_t * in,
86                              punt_ip_proto_t * out)
87 {
88   int rv;
89
90   rv = ip_address_family_decode (in->af, &out->af);
91   if (rv < 0)
92     return (rv);
93   rv = ip_proto_decode (in->protocol, &out->protocol);
94
95   return (rv);
96 }
97
98 static int
99 vl_api_punt_exception_decode (const vl_api_punt_exception_t * in,
100                               punt_exception_t * out)
101 {
102   int rv;
103
104   out->reason = clib_net_to_host_u32 (in->id);
105   rv = vlib_punt_reason_validate (out->reason);
106
107   return (rv);
108 }
109
110 static int
111 vl_api_punt_decode (const vl_api_punt_t * in, punt_reg_t * out)
112 {
113   int rv;
114
115   rv = vl_api_punt_type_decode (in->type, &out->type);
116
117   if (rv)
118     return (rv);
119
120   switch (out->type)
121     {
122     case PUNT_TYPE_L4:
123       return (vl_api_punt_l4_decode (&in->punt.l4, &out->punt.l4));
124     case PUNT_TYPE_EXCEPTION:
125       return (vl_api_punt_exception_decode (&in->punt.exception,
126                                             &out->punt.exception));
127     case PUNT_TYPE_IP_PROTO:
128       return (vl_api_punt_ip_proto_decode (&in->punt.ip_proto,
129                                            &out->punt.ip_proto));
130     }
131
132   return (-1);
133 }
134
135 static void
136 vl_api_punt_l4_encode (const punt_l4_t * in, vl_api_punt_l4_t * out)
137 {
138   out->af = ip_address_family_encode (in->af);
139   out->protocol = ip_proto_encode (in->protocol);
140   out->port = clib_net_to_host_u16 (in->port);
141 }
142
143 static void
144 vl_api_punt_ip_proto_encode (const punt_ip_proto_t * in,
145                              vl_api_punt_ip_proto_t * out)
146 {
147   out->af = ip_address_family_encode (in->af);
148   out->protocol = ip_proto_encode (in->protocol);
149 }
150
151 static void
152 vl_api_punt_exception_encode (const punt_exception_t * in,
153                               vl_api_punt_exception_t * out)
154 {
155   out->id = clib_host_to_net_u32 (in->reason);
156 }
157
158 static void
159 vl_api_punt_encode (const punt_reg_t * in, vl_api_punt_t * out)
160 {
161   out->type = vl_api_punt_type_encode (in->type);
162
163   switch (in->type)
164     {
165     case PUNT_TYPE_L4:
166       vl_api_punt_l4_encode (&in->punt.l4, &out->punt.l4);
167       break;
168     case PUNT_TYPE_IP_PROTO:
169       vl_api_punt_ip_proto_encode (&in->punt.ip_proto, &out->punt.ip_proto);
170       break;
171     case PUNT_TYPE_EXCEPTION:
172       vl_api_punt_exception_encode (&in->punt.exception,
173                                     &out->punt.exception);
174       break;
175     }
176 }
177
178 static void
179 vl_api_set_punt_t_handler (vl_api_set_punt_t * mp)
180 {
181   vl_api_set_punt_reply_t *rmp;
182   vlib_main_t *vm = vlib_get_main ();
183   clib_error_t *error;
184   punt_reg_t pr;
185   int rv;
186
187   rv = vl_api_punt_decode (&mp->punt, &pr);
188
189   if (rv)
190     goto out;
191
192   error = vnet_punt_add_del (vm, &pr, mp->is_add);
193   if (error)
194     {
195       rv = -1;
196       clib_error_report (error);
197     }
198
199 out:
200   REPLY_MACRO (VL_API_SET_PUNT_REPLY);
201 }
202
203 static void
204 vl_api_punt_socket_register_t_handler (vl_api_punt_socket_register_t * mp)
205 {
206   vl_api_punt_socket_register_reply_t *rmp;
207   vlib_main_t *vm = vlib_get_main ();
208   clib_error_t *error;
209   punt_reg_t pr;
210   int rv;
211
212   rv = vl_api_punt_decode (&mp->punt, &pr);
213
214   if (rv)
215     return;
216
217   error = vnet_punt_socket_add (vm, ntohl (mp->header_version),
218                                 &pr, (char *) mp->pathname);
219   if (error)
220     {
221       rv = -1;
222       clib_error_report (error);
223     }
224
225   char *p = vnet_punt_get_server_pathname ();
226
227   /* *INDENT-OFF* */
228   REPLY_MACRO2 (VL_API_PUNT_SOCKET_REGISTER_REPLY,
229   ({
230     memcpy ((char *) rmp->pathname, p, sizeof (rmp->pathname));
231   }));
232   /* *INDENT-ON* */
233 }
234
235 typedef struct punt_socket_send_ctx_t_
236 {
237   vl_api_registration_t *reg;
238   u32 context;
239 } punt_socket_send_ctx_t;
240
241 static walk_rc_t
242 vl_api_punt_socket_send_details (const punt_client_t * pc, void *args)
243 {
244   punt_socket_send_ctx_t *ctx = args;
245   vl_api_punt_socket_details_t *mp;
246
247   mp = vl_msg_api_alloc (sizeof (*mp));
248   if (!mp)
249     return (WALK_STOP);
250
251   clib_memset (mp, 0, sizeof (*mp));
252   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_PUNT_SOCKET_DETAILS);
253   mp->context = ctx->context;
254   vl_api_punt_encode (&pc->reg, &mp->punt);
255   memcpy (mp->pathname, pc->caddr.sun_path, sizeof (pc->caddr.sun_path));
256
257   vl_api_send_msg (ctx->reg, (u8 *) mp);
258
259   return (WALK_CONTINUE);
260 }
261
262 static void
263 vl_api_punt_socket_dump_t_handler (vl_api_punt_socket_dump_t * mp)
264 {
265   vl_api_registration_t *reg;
266   punt_type_t pt;
267
268   if (0 != vl_api_punt_type_decode (mp->type, &pt))
269     return;
270
271   reg = vl_api_client_index_to_registration (mp->client_index);
272   if (!reg)
273     return;
274
275   punt_socket_send_ctx_t ctx = {
276     .reg = reg,
277     .context = mp->context,
278   };
279
280   punt_client_walk (pt, vl_api_punt_socket_send_details, &ctx);
281 }
282
283 static void
284 vl_api_punt_socket_deregister_t_handler (vl_api_punt_socket_deregister_t * mp)
285 {
286   vl_api_punt_socket_deregister_reply_t *rmp;
287   vlib_main_t *vm = vlib_get_main ();
288   clib_error_t *error;
289   punt_reg_t pr;
290   int rv;
291
292   rv = vl_api_punt_decode (&mp->punt, &pr);
293
294   if (rv)
295     goto out;
296
297   error = vnet_punt_socket_del (vm, &pr);
298   if (error)
299     {
300       rv = -1;
301       clib_error_report (error);
302     }
303
304 out:
305   REPLY_MACRO (VL_API_PUNT_SOCKET_DEREGISTER_REPLY);
306 }
307
308 typedef struct punt_reason_dump_walk_ctx_t_
309 {
310   vl_api_registration_t *reg;
311   u32 context;
312   u8 *name;
313 } punt_reason_dump_walk_ctx_t;
314
315 static int
316 punt_reason_dump_walk_cb (vlib_punt_reason_t id, const u8 * name, void *args)
317 {
318   punt_reason_dump_walk_ctx_t *ctx = args;
319   vl_api_punt_reason_details_t *mp;
320
321   if (ctx->name)
322     {
323       /* user requested a specific punt-reason */
324       if (vec_cmp (name, ctx->name))
325         /* not the reasonn we're lookgin for */
326         return 1;
327     }
328
329   mp = vl_msg_api_alloc (sizeof (*mp) + vec_len (name));
330   if (!mp)
331     return (0);
332
333   clib_memset (mp, 0, sizeof (*mp));
334   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_PUNT_REASON_DETAILS);
335
336   mp->context = ctx->context;
337   mp->reason.id = clib_host_to_net_u32 (id);
338   vl_api_vec_to_api_string (name, &mp->reason.name);
339
340   vl_api_send_msg (ctx->reg, (u8 *) mp);
341
342   return (1);
343 }
344
345 static void
346 vl_api_punt_reason_dump_t_handler (vl_api_punt_reason_dump_t * mp)
347 {
348   vl_api_registration_t *reg;
349
350   reg = vl_api_client_index_to_registration (mp->client_index);
351   if (!reg)
352     return;
353
354   punt_reason_dump_walk_ctx_t ctx = {
355     .reg = reg,
356     .context = mp->context,
357     .name = vl_api_from_api_to_new_vec (mp, &mp->reason.name),
358   };
359
360   punt_reason_walk (punt_reason_dump_walk_cb, &ctx);
361
362   vec_free (ctx.name);
363 }
364
365 #include <vnet/ip/punt.api.c>
366
367 static clib_error_t *
368 punt_api_hookup (vlib_main_t * vm)
369 {
370   /*
371    * Set up the (msg_name, crc, message-id) table
372    */
373   REPLY_MSG_ID_BASE = setup_message_id_table ();
374
375   return 0;
376 }
377
378 VLIB_API_INIT_FUNCTION (punt_api_hookup);
379
380
381 /*
382  * fd.io coding-style-patch-verification: ON
383  *
384  * Local Variables:
385  * eval: (c-set-style "gnu")
386  * End:
387  */