api: register endian handlers for reply messages
[vpp.git] / src / plugins / dhcp / dhcp_test.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <vat/vat.h>
17 #include <vlibapi/api.h>
18 #include <vlibmemory/api.h>
19 #include <vppinfra/error.h>
20
21 #include <dhcp/client.h>
22 #include <dhcp/dhcp_proxy.h>
23 #include <vnet/ip/ip_format_fns.h>
24 #include <vnet/ethernet/ethernet_format_fns.h>
25
26 /* define message IDs */
27 #include <dhcp/dhcp.api_enum.h>
28 #include <dhcp/dhcp.api_types.h>
29
30 typedef struct
31 {
32   /* API message ID base */
33   u16 msg_id_base;
34   vat_main_t *vat_main;
35 } dhcp_test_main_t;
36
37 dhcp_test_main_t dhcp_test_main;
38
39 #define __plugin_msg_base dhcp_test_main.msg_id_base
40 #include <vlibapi/vat_helper_macros.h>
41
42 /* Macro to finish up custom dump fns */
43 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
44 #define FINISH                                  \
45     vec_add1 (s, 0);                            \
46     vl_print (handle, (char *)s);               \
47     vec_free (s);                               \
48     return handle;
49
50 static int
51 api_dhcp_proxy_config (vat_main_t * vam)
52 {
53   unformat_input_t *i = vam->input;
54   vl_api_dhcp_proxy_config_t *mp;
55   u32 rx_vrf_id = 0;
56   u32 server_vrf_id = 0;
57   u8 is_add = 1;
58   u8 v4_address_set = 0;
59   u8 v6_address_set = 0;
60   ip4_address_t v4address;
61   ip6_address_t v6address;
62   u8 v4_src_address_set = 0;
63   u8 v6_src_address_set = 0;
64   ip4_address_t v4srcaddress;
65   ip6_address_t v6srcaddress;
66   int ret;
67
68   /* Parse args required to build the message */
69   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
70     {
71       if (unformat (i, "del"))
72         is_add = 0;
73       else if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
74         ;
75       else if (unformat (i, "server_vrf_id %d", &server_vrf_id))
76         ;
77       else if (unformat (i, "svr %U", unformat_ip4_address, &v4address))
78         v4_address_set = 1;
79       else if (unformat (i, "svr %U", unformat_ip6_address, &v6address))
80         v6_address_set = 1;
81       else if (unformat (i, "src %U", unformat_ip4_address, &v4srcaddress))
82         v4_src_address_set = 1;
83       else if (unformat (i, "src %U", unformat_ip6_address, &v6srcaddress))
84         v6_src_address_set = 1;
85       else
86         break;
87     }
88
89   if (v4_address_set && v6_address_set)
90     {
91       errmsg ("both v4 and v6 server addresses set");
92       return -99;
93     }
94   if (!v4_address_set && !v6_address_set)
95     {
96       errmsg ("no server addresses set");
97       return -99;
98     }
99
100   if (v4_src_address_set && v6_src_address_set)
101     {
102       errmsg ("both v4 and v6  src addresses set");
103       return -99;
104     }
105   if (!v4_src_address_set && !v6_src_address_set)
106     {
107       errmsg ("no src addresses set");
108       return -99;
109     }
110
111   if (!(v4_src_address_set && v4_address_set) &&
112       !(v6_src_address_set && v6_address_set))
113     {
114       errmsg ("no matching server and src addresses set");
115       return -99;
116     }
117
118   /* Construct the API message */
119   M (DHCP_PROXY_CONFIG, mp);
120
121   mp->is_add = is_add;
122   mp->rx_vrf_id = ntohl (rx_vrf_id);
123   mp->server_vrf_id = ntohl (server_vrf_id);
124   if (v6_address_set)
125     {
126       clib_memcpy (&mp->dhcp_server.un, &v6address, sizeof (v6address));
127       clib_memcpy (&mp->dhcp_src_address.un, &v6srcaddress,
128                    sizeof (v6address));
129     }
130   else
131     {
132       clib_memcpy (&mp->dhcp_server.un, &v4address, sizeof (v4address));
133       clib_memcpy (&mp->dhcp_src_address.un, &v4srcaddress,
134                    sizeof (v4address));
135     }
136
137   /* send it... */
138   S (mp);
139
140   /* Wait for a reply, return good/bad news  */
141   W (ret);
142   return ret;
143 }
144
145 static void
146 vl_api_dhcp_proxy_details_t_handler (vl_api_dhcp_proxy_details_t * mp)
147 {
148   vat_main_t *vam = &vat_main;
149   u32 i, count = mp->count;
150   vl_api_dhcp_server_t *s;
151
152   if (mp->is_ipv6)
153     print (vam->ofp,
154            "RX Table-ID %d, Source Address %U, VSS Type %d, "
155            "VSS ASCII VPN-ID '%s', VSS RFC2685 VPN-ID (oui:id) %d:%d",
156            ntohl (mp->rx_vrf_id),
157            format_ip6_address, mp->dhcp_src_address,
158            mp->vss_type, mp->vss_vpn_ascii_id,
159            ntohl (mp->vss_oui), ntohl (mp->vss_fib_id));
160   else
161     print (vam->ofp,
162            "RX Table-ID %d, Source Address %U, VSS Type %d, "
163            "VSS ASCII VPN-ID '%s', VSS RFC2685 VPN-ID (oui:id) %d:%d",
164            ntohl (mp->rx_vrf_id),
165            format_ip4_address, mp->dhcp_src_address,
166            mp->vss_type, mp->vss_vpn_ascii_id,
167            ntohl (mp->vss_oui), ntohl (mp->vss_fib_id));
168
169   for (i = 0; i < count; i++)
170     {
171       s = &mp->servers[i];
172
173       if (mp->is_ipv6)
174         print (vam->ofp,
175                " Server Table-ID %d, Server Address %U",
176                ntohl (s->server_vrf_id), format_ip6_address, s->dhcp_server);
177       else
178         print (vam->ofp,
179                " Server Table-ID %d, Server Address %U",
180                ntohl (s->server_vrf_id), format_ip4_address, s->dhcp_server);
181     }
182 }
183
184 static int
185 api_dhcp_proxy_dump (vat_main_t * vam)
186 {
187   unformat_input_t *i = vam->input;
188   vl_api_dhcp_plugin_control_ping_t *mp_ping;
189   vl_api_dhcp_proxy_dump_t *mp;
190   u8 is_ipv6 = 0;
191   int ret;
192
193   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
194     {
195       if (unformat (i, "ipv6"))
196         is_ipv6 = 1;
197       else
198         {
199           clib_warning ("parse error '%U'", format_unformat_error, i);
200           return -99;
201         }
202     }
203
204   M (DHCP_PROXY_DUMP, mp);
205
206   mp->is_ip6 = is_ipv6;
207   S (mp);
208
209   /* Use a control ping for synchronization */
210   MPING (DHCP_PLUGIN_CONTROL_PING, mp_ping);
211   S (mp_ping);
212
213   W (ret);
214   return ret;
215 }
216
217 static int
218 api_dhcp_proxy_set_vss (vat_main_t * vam)
219 {
220   unformat_input_t *i = vam->input;
221   vl_api_dhcp_proxy_set_vss_t *mp;
222   u8 is_ipv6 = 0;
223   u8 is_add = 1;
224   u32 tbl_id = ~0;
225   u8 vss_type = VSS_TYPE_DEFAULT;
226   u8 *vpn_ascii_id = 0;
227   u32 oui = 0;
228   u32 fib_id = 0;
229   int ret;
230
231   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
232     {
233       if (unformat (i, "tbl_id %d", &tbl_id))
234         ;
235       else if (unformat (i, "vpn_ascii_id %s", &vpn_ascii_id))
236         vss_type = VSS_TYPE_ASCII;
237       else if (unformat (i, "fib_id %d", &fib_id))
238         vss_type = VSS_TYPE_VPN_ID;
239       else if (unformat (i, "oui %d", &oui))
240         vss_type = VSS_TYPE_VPN_ID;
241       else if (unformat (i, "ipv6"))
242         is_ipv6 = 1;
243       else if (unformat (i, "del"))
244         is_add = 0;
245       else
246         break;
247     }
248
249   if (tbl_id == ~0)
250     {
251       errmsg ("missing tbl_id ");
252       vec_free (vpn_ascii_id);
253       return -99;
254     }
255
256   if ((vpn_ascii_id) && (vec_len (vpn_ascii_id) > 128))
257     {
258       errmsg ("vpn_ascii_id cannot be longer than 128 ");
259       vec_free (vpn_ascii_id);
260       return -99;
261     }
262
263   M (DHCP_PROXY_SET_VSS, mp);
264   mp->tbl_id = ntohl (tbl_id);
265   mp->vss_type = vss_type;
266   if (vpn_ascii_id)
267     {
268       clib_memcpy (mp->vpn_ascii_id, vpn_ascii_id, vec_len (vpn_ascii_id));
269       mp->vpn_ascii_id[vec_len (vpn_ascii_id)] = 0;
270     }
271   mp->vpn_index = ntohl (fib_id);
272   mp->oui = ntohl (oui);
273   mp->is_ipv6 = is_ipv6;
274   mp->is_add = is_add;
275
276   S (mp);
277   W (ret);
278
279   vec_free (vpn_ascii_id);
280   return ret;
281 }
282
283 static int
284 api_dhcp_client_config (vat_main_t * vam)
285 {
286   unformat_input_t *i = vam->input;
287   vl_api_dhcp_client_config_t *mp;
288   u32 sw_if_index;
289   u8 sw_if_index_set = 0;
290   u8 is_add = 1;
291   u8 *hostname = 0;
292   u8 disable_event = 0;
293   int ret;
294
295   /* Parse args required to build the message */
296   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
297     {
298       if (unformat (i, "del"))
299         is_add = 0;
300       else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
301         sw_if_index_set = 1;
302       else if (unformat (i, "sw_if_index %d", &sw_if_index))
303         sw_if_index_set = 1;
304       else if (unformat (i, "hostname %s", &hostname))
305         ;
306       else if (unformat (i, "disable_event"))
307         disable_event = 1;
308       else
309         break;
310     }
311
312   if (sw_if_index_set == 0)
313     {
314       errmsg ("missing interface name or sw_if_index");
315       return -99;
316     }
317
318   if (vec_len (hostname) > 63)
319     {
320       errmsg ("hostname too long");
321     }
322   vec_add1 (hostname, 0);
323
324   /* Construct the API message */
325   M (DHCP_CLIENT_CONFIG, mp);
326
327   mp->is_add = is_add;
328   mp->client.sw_if_index = htonl (sw_if_index);
329   clib_memcpy (mp->client.hostname, hostname, vec_len (hostname));
330   vec_free (hostname);
331   mp->client.want_dhcp_event = disable_event ? 0 : 1;
332   mp->client.pid = htonl (getpid ());
333
334   /* send it... */
335   S (mp);
336
337   /* Wait for a reply, return good/bad news  */
338   W (ret);
339   return ret;
340 }
341
342 static int
343 api_want_dhcp6_reply_events (vat_main_t * vam)
344 {
345   return -1;
346 }
347
348 static int
349 api_want_dhcp6_pd_reply_events (vat_main_t * vam)
350 {
351   return -1;
352 }
353
354 static int
355 api_dhcp6_send_client_message (vat_main_t * vam)
356 {
357   return -1;
358 }
359
360 static int
361 api_dhcp6_pd_send_client_message (vat_main_t * vam)
362 {
363   return -1;
364 }
365
366 static void
367 vl_api_dhcp_client_details_t_handler (vl_api_dhcp_client_details_t * mp)
368 {
369   vat_main_t *vam = &vat_main;
370   vl_api_dhcp_client_t *cp;
371   vl_api_dhcp_lease_t *lp;
372
373   cp = &mp->client;
374   lp = &mp->lease;
375
376   print (vam->ofp, "sw_if_index %d, id '%s'", ntohl (cp->sw_if_index),
377          cp->id);
378
379   print (vam->ofp, "leased address %U, router address %U",
380          format_ip4_address, &lp->host_address.un,
381          format_ip4_address, &lp->router_address.un);
382 }
383
384 static int
385 api_dhcp_client_dump (vat_main_t * vam)
386 {
387   vl_api_dhcp_plugin_control_ping_t *mp_ping;
388   vl_api_dhcp_client_dump_t *mp;
389   int ret;
390
391   M (DHCP_CLIENT_DUMP, mp);
392
393   S (mp);
394
395   /* Use a control ping for synchronization */
396   MPING (DHCP_PLUGIN_CONTROL_PING, mp_ping);
397   S (mp_ping);
398
399   W (ret);
400   return ret;
401 }
402
403 static int
404 api_dhcp6_duid_ll_set (vat_main_t * vam)
405 {
406   return -1;
407 }
408
409 static int
410 api_dhcp6_clients_enable_disable (vat_main_t * vam)
411 {
412   return -1;
413 }
414
415 static int
416 api_dhcp_plugin_control_ping (vat_main_t * vam)
417 {
418   return -1;
419 }
420
421 static int
422 api_dhcp_plugin_get_version (vat_main_t * vam)
423 {
424   return -1;
425 }
426
427 static void
428   vl_api_dhcp_plugin_get_version_reply_t_handler
429   (vl_api_dhcp_plugin_get_version_reply_t * mp)
430 {
431   vat_main_t *vam = dhcp_test_main.vat_main;
432   clib_warning ("DHCP plugin version: %d.%d", ntohl (mp->major),
433                 ntohl (mp->minor));
434   vam->result_ready = 1;
435 }
436
437 static void
438   vl_api_dhcp_plugin_control_ping_reply_t_handler
439   (vl_api_dhcp_plugin_control_ping_reply_t * mp)
440 {
441   vat_main_t *vam = dhcp_test_main.vat_main;
442   i32 retval = ntohl (mp->retval);
443   if (vam->async_mode)
444     {
445       vam->async_errors += (retval < 0);
446     }
447   else
448     {
449       vam->retval = retval;
450       vam->result_ready = 1;
451     }
452 }
453
454 #include <dhcp/dhcp.api_test.c>
455
456 /*
457  * fd.io coding-style-patch-verification: ON
458  *
459  * Local Variables:
460  * eval: (c-set-style "gnu")
461  * End:
462  */