geneve: Move to plugin
[vpp.git] / src / plugins / geneve / geneve_test.c
1 /*
2  * Copyright (c) 2020 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 <vnet/ip/ip.h>
22 #include <vnet/ip/ip_types_api.h>
23 #include <geneve/geneve.h>
24
25 /* define message IDs */
26 #include <vnet/format_fns.h>
27 #include <geneve/geneve.api_enum.h>
28 #include <geneve/geneve.api_types.h>
29 #include <vpp/api/vpe.api_types.h>
30
31 typedef struct
32 {
33   /* API message ID base */
34   u16 msg_id_base;
35   u32 ping_id;
36   vat_main_t *vat_main;
37 } geneve_test_main_t;
38
39 geneve_test_main_t geneve_test_main;
40
41 #define __plugin_msg_base geneve_test_main.msg_id_base
42 #include <vlibapi/vat_helper_macros.h>
43
44 /* Macro to finish up custom dump fns */
45 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
46 #define FINISH                                  \
47     vec_add1 (s, 0);                            \
48     vl_print (handle, (char *)s);               \
49     vec_free (s);                               \
50     return handle;
51
52 static void vl_api_geneve_add_del_tunnel_reply_t_handler
53   (vl_api_geneve_add_del_tunnel_reply_t * mp)
54 {
55   vat_main_t *vam = &vat_main;
56   i32 retval = ntohl (mp->retval);
57   if (vam->async_mode)
58     {
59       vam->async_errors += (retval < 0);
60     }
61   else
62     {
63       vam->retval = retval;
64       vam->sw_if_index = ntohl (mp->sw_if_index);
65       vam->result_ready = 1;
66     }
67 }
68
69 static void vl_api_geneve_add_del_tunnel2_reply_t_handler
70   (vl_api_geneve_add_del_tunnel2_reply_t * mp)
71 {
72   vat_main_t *vam = &vat_main;
73   i32 retval = ntohl (mp->retval);
74   if (vam->async_mode)
75     {
76       vam->async_errors += (retval < 0);
77     }
78   else
79     {
80       vam->retval = retval;
81       vam->sw_if_index = ntohl (mp->sw_if_index);
82       vam->result_ready = 1;
83     }
84 }
85
86 static int
87 api_sw_interface_set_geneve_bypass (vat_main_t * vam)
88 {
89   unformat_input_t *i = vam->input;
90   vl_api_sw_interface_set_geneve_bypass_t *mp;
91   u32 sw_if_index = 0;
92   u8 sw_if_index_set = 0;
93   u8 is_enable = 1;
94   u8 is_ipv6 = 0;
95   int ret;
96
97   /* Parse args required to build the message */
98   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
99     {
100       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
101         sw_if_index_set = 1;
102       else if (unformat (i, "sw_if_index %d", &sw_if_index))
103         sw_if_index_set = 1;
104       else if (unformat (i, "enable"))
105         is_enable = 1;
106       else if (unformat (i, "disable"))
107         is_enable = 0;
108       else if (unformat (i, "ip4"))
109         is_ipv6 = 0;
110       else if (unformat (i, "ip6"))
111         is_ipv6 = 1;
112       else
113         break;
114     }
115
116   if (sw_if_index_set == 0)
117     {
118       errmsg ("missing interface name or sw_if_index");
119       return -99;
120     }
121
122   /* Construct the API message */
123   M (SW_INTERFACE_SET_GENEVE_BYPASS, mp);
124
125   mp->sw_if_index = ntohl (sw_if_index);
126   mp->enable = is_enable;
127   mp->is_ipv6 = is_ipv6;
128
129   /* send it... */
130   S (mp);
131
132   /* Wait for a reply... */
133   W (ret);
134   return ret;
135 }
136
137 static uword unformat_geneve_decap_next
138   (unformat_input_t * input, va_list * args)
139 {
140   u32 *result = va_arg (*args, u32 *);
141   u32 tmp;
142
143   if (unformat (input, "l2"))
144     *result = GENEVE_INPUT_NEXT_L2_INPUT;
145   else if (unformat (input, "%d", &tmp))
146     *result = tmp;
147   else
148     return 0;
149   return 1;
150 }
151
152 static int
153 api_geneve_add_del_tunnel (vat_main_t * vam)
154 {
155   unformat_input_t *line_input = vam->input;
156   vl_api_geneve_add_del_tunnel_t *mp;
157   ip46_address_t src, dst;
158   u8 is_add = 1;
159   u8 ipv4_set = 0, ipv6_set = 0;
160   u8 src_set = 0;
161   u8 dst_set = 0;
162   u8 grp_set = 0;
163   u32 mcast_sw_if_index = ~0;
164   u32 encap_vrf_id = 0;
165   u32 decap_next_index = ~0;
166   u32 vni = 0;
167   int ret;
168
169   /* Can't "universally zero init" (={0}) due to GCC bug 53119 */
170   clib_memset (&src, 0, sizeof src);
171   clib_memset (&dst, 0, sizeof dst);
172
173   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
174     {
175       if (unformat (line_input, "del"))
176         is_add = 0;
177       else
178         if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4))
179         {
180           ipv4_set = 1;
181           src_set = 1;
182         }
183       else
184         if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4))
185         {
186           ipv4_set = 1;
187           dst_set = 1;
188         }
189       else
190         if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6))
191         {
192           ipv6_set = 1;
193           src_set = 1;
194         }
195       else
196         if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6))
197         {
198           ipv6_set = 1;
199           dst_set = 1;
200         }
201       else if (unformat (line_input, "group %U %U",
202                          unformat_ip4_address, &dst.ip4,
203                          unformat_sw_if_index, vam, &mcast_sw_if_index))
204         {
205           grp_set = dst_set = 1;
206           ipv4_set = 1;
207         }
208       else if (unformat (line_input, "group %U",
209                          unformat_ip4_address, &dst.ip4))
210         {
211           grp_set = dst_set = 1;
212           ipv4_set = 1;
213         }
214       else if (unformat (line_input, "group %U %U",
215                          unformat_ip6_address, &dst.ip6,
216                          unformat_sw_if_index, vam, &mcast_sw_if_index))
217         {
218           grp_set = dst_set = 1;
219           ipv6_set = 1;
220         }
221       else if (unformat (line_input, "group %U",
222                          unformat_ip6_address, &dst.ip6))
223         {
224           grp_set = dst_set = 1;
225           ipv6_set = 1;
226         }
227       else
228         if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index))
229         ;
230       else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
231         ;
232       else if (unformat (line_input, "decap-next %U",
233                          unformat_geneve_decap_next, &decap_next_index))
234         ;
235       else if (unformat (line_input, "vni %d", &vni))
236         ;
237       else
238         {
239           errmsg ("parse error '%U'", format_unformat_error, line_input);
240           return -99;
241         }
242     }
243
244   if (src_set == 0)
245     {
246       errmsg ("tunnel src address not specified");
247       return -99;
248     }
249   if (dst_set == 0)
250     {
251       errmsg ("tunnel dst address not specified");
252       return -99;
253     }
254
255   if (grp_set && !ip46_address_is_multicast (&dst))
256     {
257       errmsg ("tunnel group address not multicast");
258       return -99;
259     }
260   if (grp_set && mcast_sw_if_index == ~0)
261     {
262       errmsg ("tunnel nonexistent multicast device");
263       return -99;
264     }
265   if (grp_set == 0 && ip46_address_is_multicast (&dst))
266     {
267       errmsg ("tunnel dst address must be unicast");
268       return -99;
269     }
270
271
272   if (ipv4_set && ipv6_set)
273     {
274       errmsg ("both IPv4 and IPv6 addresses specified");
275       return -99;
276     }
277
278   if ((vni == 0) || (vni >> 24))
279     {
280       errmsg ("vni not specified or out of range");
281       return -99;
282     }
283
284   M (GENEVE_ADD_DEL_TUNNEL, mp);
285
286   if (ipv6_set)
287     {
288       clib_memcpy (&mp->local_address.un.ip6, &src.ip6, sizeof (src.ip6));
289       clib_memcpy (&mp->remote_address.un.ip6, &dst.ip6, sizeof (dst.ip6));
290     }
291   else
292     {
293       clib_memcpy (&mp->local_address.un.ip4, &src.ip4, sizeof (src.ip4));
294       clib_memcpy (&mp->remote_address.un.ip4, &dst.ip4, sizeof (dst.ip4));
295     }
296   mp->encap_vrf_id = ntohl (encap_vrf_id);
297   mp->decap_next_index = ntohl (decap_next_index);
298   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
299   mp->vni = ntohl (vni);
300   mp->is_add = is_add;
301
302   S (mp);
303   W (ret);
304   return ret;
305 }
306
307 static int
308 api_geneve_add_del_tunnel2 (vat_main_t * vam)
309 {
310   return api_geneve_add_del_tunnel (vam);
311 }
312
313 static void vl_api_geneve_tunnel_details_t_handler
314   (vl_api_geneve_tunnel_details_t * mp)
315 {
316   vat_main_t *vam = &vat_main;
317   ip46_address_t src = {.as_u64[0] = 0,.as_u64[1] = 0 };
318   ip46_address_t dst = {.as_u64[0] = 0,.as_u64[1] = 0 };
319
320   if (mp->src_address.af == ADDRESS_IP6)
321     {
322       clib_memcpy (&src.ip6, &mp->src_address.un.ip6, sizeof (ip6_address_t));
323       clib_memcpy (&dst.ip6, &mp->dst_address.un.ip6, sizeof (ip6_address_t));
324     }
325   else
326     {
327       clib_memcpy (&src.ip4, &mp->src_address.un.ip4, sizeof (ip4_address_t));
328       clib_memcpy (&dst.ip4, &mp->dst_address.un.ip4, sizeof (ip4_address_t));
329     }
330
331   print (vam->ofp, "%11d%24U%24U%14d%18d%13d%19d",
332          ntohl (mp->sw_if_index),
333          format_ip46_address, &src, IP46_TYPE_ANY,
334          format_ip46_address, &dst, IP46_TYPE_ANY,
335          ntohl (mp->encap_vrf_id),
336          ntohl (mp->decap_next_index), ntohl (mp->vni),
337          ntohl (mp->mcast_sw_if_index));
338 }
339
340 static int
341 api_geneve_tunnel_dump (vat_main_t * vam)
342 {
343   unformat_input_t *i = vam->input;
344   vl_api_geneve_tunnel_dump_t *mp;
345   vl_api_control_ping_t *mp_ping;
346   u32 sw_if_index;
347   u8 sw_if_index_set = 0;
348   int ret;
349
350   /* Parse args required to build the message */
351   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
352     {
353       if (unformat (i, "sw_if_index %d", &sw_if_index))
354         sw_if_index_set = 1;
355       else
356         break;
357     }
358
359   if (sw_if_index_set == 0)
360     {
361       sw_if_index = ~0;
362     }
363
364   if (!vam->json_output)
365     {
366       print (vam->ofp, "%11s%24s%24s%14s%18s%13s%19s",
367              "sw_if_index", "local_address", "remote_address",
368              "encap_vrf_id", "decap_next_index", "vni", "mcast_sw_if_index");
369     }
370
371   /* Get list of geneve-tunnel interfaces */
372   M (GENEVE_TUNNEL_DUMP, mp);
373
374   mp->sw_if_index = htonl (sw_if_index);
375
376   S (mp);
377
378   /* Use a control ping for synchronization */
379   if (!geneve_test_main.ping_id)
380     geneve_test_main.ping_id =
381       vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC));
382   mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
383   mp_ping->_vl_msg_id = htons (geneve_test_main.ping_id);
384   mp_ping->client_index = vam->my_client_index;
385
386   fformat (vam->ofp, "Sending ping id=%d\n", geneve_test_main.ping_id);
387
388   vam->result_ready = 0;
389   S (mp_ping);
390
391   W (ret);
392   return ret;
393 }
394
395 /* _(sw_interface_set_geneve_bypass,                                        */
396 /*   "<intfc> | sw_if_index <id> [ip4 | ip6] [enable | disable]")           */
397 /* _(geneve_add_del_tunnel,                                                 */
398 /*   "src <ip-addr> { dst <ip-addr> | group <mcast-ip-addr>\n"              */
399 /*   "{ <intfc> | mcast_sw_if_index <nn> } }\n"                             */
400 /*   "vni <vni> [encap-vrf-id <nn>] [decap-next <l2|nn>] [del]")            */
401 /* _(geneve_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    */
402
403
404 #include <geneve/geneve.api_test.c>
405
406 /*
407  * fd.io coding-style-patch-verification: ON
408  *
409  * Local Variables:
410  * eval: (c-set-style "gnu")
411  * End:
412  */