c7eea8b64b85b3d355bd09cb15b4bef3576279dc
[vpp.git] / src / plugins / ioam / lib-vxlan-gpe / vxlan_gpe_test.c
1 /*
2  * Copyright (c) 2016 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  *------------------------------------------------------------------
17  * vxlan_gpe_test.c - test harness for vxlan_gpe plugin
18  *------------------------------------------------------------------
19  */
20
21 #include <vat/vat.h>
22 #include <vlibapi/api.h>
23 #include <vlibmemory/api.h>
24
25 #include <vppinfra/error.h>
26
27 #define __plugin_msg_base vxlan_gpe_test_main.msg_id_base
28 #include <vlibapi/vat_helper_macros.h>
29
30 /* Declare message IDs */
31 #include <ioam/lib-vxlan-gpe/ioam_vxlan_gpe.api_enum.h>
32 #include <ioam/lib-vxlan-gpe/ioam_vxlan_gpe.api_types.h>
33
34 #define vl_endianfun            /* define message structures */
35 #define vl_printfun
36 #define vl_api_version(n,v) static u32 api_version=(v);
37 #define vl_print(handle, ...)
38 #include <ioam/lib-vxlan-gpe/ioam_vxlan_gpe.api.h>
39 #undef vl_endianfun
40 #undef vl_printfun
41 #undef vl_api_version
42
43 #include <ioam/lib-vxlan-gpe/vxlan_gpe_ioam_packet.h>
44 #include <ioam/lib-vxlan-gpe/vxlan_gpe_ioam.h>
45
46 typedef struct
47 {
48   /* API message ID base */
49   u16 msg_id_base;
50   vat_main_t *vat_main;
51 } vxlan_gpe_test_main_t;
52
53 vxlan_gpe_test_main_t vxlan_gpe_test_main;
54
55 #define foreach_standard_reply_retval_handler     \
56 _(vxlan_gpe_ioam_enable_reply)                    \
57 _(vxlan_gpe_ioam_disable_reply)                   \
58 _(vxlan_gpe_ioam_vni_enable_reply)                \
59 _(vxlan_gpe_ioam_vni_disable_reply)               \
60 _(vxlan_gpe_ioam_transit_enable_reply)            \
61 _(vxlan_gpe_ioam_transit_disable_reply)
62
63 #define _(n)                                            \
64     static void vl_api_##n##_t_handler                  \
65     (vl_api_##n##_t * mp)                               \
66     {                                                   \
67         vat_main_t * vam = vxlan_gpe_test_main.vat_main;   \
68         i32 retval = ntohl(mp->retval);                 \
69         if (vam->async_mode) {                          \
70             vam->async_errors += (retval < 0);          \
71         } else {                                        \
72             vam->retval = retval;                       \
73             vam->result_ready = 1;                      \
74         }                                               \
75     }
76 foreach_standard_reply_retval_handler;
77 #undef _
78
79 /*
80  * Table of message reply handlers, must include boilerplate handlers
81  * we just generated
82  */
83 #define foreach_vpe_api_reply_msg                                              \
84 _(VXLAN_GPE_IOAM_ENABLE_REPLY, vxlan_gpe_ioam_enable_reply)                    \
85 _(VXLAN_GPE_IOAM_DISABLE_REPLY, vxlan_gpe_ioam_disable_reply)                  \
86 _(VXLAN_GPE_IOAM_VNI_ENABLE_REPLY, vxlan_gpe_ioam_vni_enable_reply)            \
87 _(VXLAN_GPE_IOAM_VNI_DISABLE_REPLY, vxlan_gpe_ioam_vni_disable_reply)          \
88 _(VXLAN_GPE_IOAM_TRANSIT_ENABLE_REPLY, vxlan_gpe_ioam_transit_enable_reply)    \
89 _(VXLAN_GPE_IOAM_TRANSIT_DISABLE_REPLY, vxlan_gpe_ioam_transit_disable_reply)  \
90
91 static int
92 api_vxlan_gpe_ioam_enable (vat_main_t * vam)
93 {
94   unformat_input_t *input = vam->input;
95   vl_api_vxlan_gpe_ioam_enable_t *mp;
96   u32 id = 0;
97   int has_trace_option = 0;
98   int has_pow_option = 0;
99   int has_ppc_option = 0;
100   int ret;
101
102   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
103     {
104       if (unformat (input, "trace"))
105         has_trace_option = 1;
106       else if (unformat (input, "pow"))
107         has_pow_option = 1;
108       else if (unformat (input, "ppc encap"))
109         has_ppc_option = PPC_ENCAP;
110       else if (unformat (input, "ppc decap"))
111         has_ppc_option = PPC_DECAP;
112       else if (unformat (input, "ppc none"))
113         has_ppc_option = PPC_NONE;
114       else
115         break;
116     }
117   M (VXLAN_GPE_IOAM_ENABLE, mp);
118   mp->id = htons (id);
119   mp->trace_ppc = has_ppc_option;
120   mp->pow_enable = has_pow_option;
121   mp->trace_enable = has_trace_option;
122
123
124   S (mp);
125   W (ret);
126   return ret;
127 }
128
129
130 static int
131 api_vxlan_gpe_ioam_disable (vat_main_t * vam)
132 {
133   vl_api_vxlan_gpe_ioam_disable_t *mp;
134   int ret;
135
136   M (VXLAN_GPE_IOAM_DISABLE, mp);
137   S (mp);
138   W (ret);
139   return ret;
140 }
141
142 static int
143 api_vxlan_gpe_ioam_vni_enable (vat_main_t * vam)
144 {
145   unformat_input_t *line_input = vam->input;
146   vl_api_vxlan_gpe_ioam_vni_enable_t *mp;
147   ip4_address_t local4, remote4;
148   ip6_address_t local6, remote6;
149   u8 ipv4_set = 0, ipv6_set = 0;
150   u8 local_set = 0;
151   u8 remote_set = 0;
152   u32 vni;
153   u8 vni_set = 0;
154   int ret;
155
156
157   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
158     {
159       if (unformat (line_input, "local %U", unformat_ip4_address, &local4))
160         {
161           local_set = 1;
162           ipv4_set = 1;
163         }
164       else if (unformat (line_input, "remote %U",
165                          unformat_ip4_address, &remote4))
166         {
167           remote_set = 1;
168           ipv4_set = 1;
169         }
170       else if (unformat (line_input, "local %U",
171                          unformat_ip6_address, &local6))
172         {
173           local_set = 1;
174           ipv6_set = 1;
175         }
176       else if (unformat (line_input, "remote %U",
177                          unformat_ip6_address, &remote6))
178         {
179           remote_set = 1;
180           ipv6_set = 1;
181         }
182
183       else if (unformat (line_input, "vni %d", &vni))
184         vni_set = 1;
185       else
186         {
187           errmsg ("parse error '%U'\n", format_unformat_error, line_input);
188           return -99;
189         }
190     }
191
192   if (local_set == 0)
193     {
194       errmsg ("tunnel local address not specified\n");
195       return -99;
196     }
197   if (remote_set == 0)
198     {
199       errmsg ("tunnel remote address not specified\n");
200       return -99;
201     }
202   if (ipv4_set && ipv6_set)
203     {
204       errmsg ("both IPv4 and IPv6 addresses specified");
205       return -99;
206     }
207
208   if (vni_set == 0)
209     {
210       errmsg ("vni not specified\n");
211       return -99;
212     }
213
214   M (VXLAN_GPE_IOAM_VNI_ENABLE, mp);
215
216
217   if (ipv6_set)
218     {
219       clib_memcpy (&mp->local, &local6, sizeof (local6));
220       clib_memcpy (&mp->remote, &remote6, sizeof (remote6));
221     }
222   else
223     {
224       clib_memcpy (&mp->local, &local4, sizeof (local4));
225       clib_memcpy (&mp->remote, &remote4, sizeof (remote4));
226     }
227
228   mp->vni = ntohl (vni);
229   mp->is_ipv6 = ipv6_set;
230
231   S (mp);
232   W (ret);
233   return ret;
234 }
235
236 static int
237 api_vxlan_gpe_ioam_vni_disable (vat_main_t * vam)
238 {
239   unformat_input_t *line_input = vam->input;
240   vl_api_vxlan_gpe_ioam_vni_disable_t *mp;
241   ip4_address_t local4, remote4;
242   ip6_address_t local6, remote6;
243   u8 ipv4_set = 0, ipv6_set = 0;
244   u8 local_set = 0;
245   u8 remote_set = 0;
246   u32 vni;
247   u8 vni_set = 0;
248   int ret;
249
250
251   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
252     {
253       if (unformat (line_input, "local %U", unformat_ip4_address, &local4))
254         {
255           local_set = 1;
256           ipv4_set = 1;
257         }
258       else if (unformat (line_input, "remote %U",
259                          unformat_ip4_address, &remote4))
260         {
261           remote_set = 1;
262           ipv4_set = 1;
263         }
264       else if (unformat (line_input, "local %U",
265                          unformat_ip6_address, &local6))
266         {
267           local_set = 1;
268           ipv6_set = 1;
269         }
270       else if (unformat (line_input, "remote %U",
271                          unformat_ip6_address, &remote6))
272         {
273           remote_set = 1;
274           ipv6_set = 1;
275         }
276
277       else if (unformat (line_input, "vni %d", &vni))
278         vni_set = 1;
279       else
280         {
281           errmsg ("parse error '%U'\n", format_unformat_error, line_input);
282           return -99;
283         }
284     }
285
286   if (local_set == 0)
287     {
288       errmsg ("tunnel local address not specified\n");
289       return -99;
290     }
291   if (remote_set == 0)
292     {
293       errmsg ("tunnel remote address not specified\n");
294       return -99;
295     }
296   if (ipv4_set && ipv6_set)
297     {
298       errmsg ("both IPv4 and IPv6 addresses specified");
299       return -99;
300     }
301
302   if (vni_set == 0)
303     {
304       errmsg ("vni not specified\n");
305       return -99;
306     }
307
308   M (VXLAN_GPE_IOAM_VNI_DISABLE, mp);
309
310
311   if (ipv6_set)
312     {
313       clib_memcpy (&mp->local, &local6, sizeof (local6));
314       clib_memcpy (&mp->remote, &remote6, sizeof (remote6));
315     }
316   else
317     {
318       clib_memcpy (&mp->local, &local4, sizeof (local4));
319       clib_memcpy (&mp->remote, &remote4, sizeof (remote4));
320     }
321
322   mp->vni = ntohl (vni);
323   mp->is_ipv6 = ipv6_set;
324
325   S (mp);
326   W (ret);
327   return ret;
328 }
329
330 static int
331 api_vxlan_gpe_ioam_transit_enable (vat_main_t * vam)
332 {
333   unformat_input_t *line_input = vam->input;
334   vl_api_vxlan_gpe_ioam_transit_enable_t *mp;
335   ip4_address_t local4;
336   ip6_address_t local6;
337   u8 ipv4_set = 0, ipv6_set = 0;
338   u8 local_set = 0;
339   u32 outer_fib_index = 0;
340   int ret;
341
342
343   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
344     {
345       if (unformat (line_input, "dst-ip %U", unformat_ip4_address, &local4))
346         {
347           local_set = 1;
348           ipv4_set = 1;
349         }
350       else if (unformat (line_input, "dst-ip %U",
351                          unformat_ip6_address, &local6))
352         {
353           local_set = 1;
354           ipv6_set = 1;
355         }
356
357       else if (unformat (line_input, "outer-fib-index %d", &outer_fib_index))
358         ;
359       else
360         {
361           errmsg ("parse error '%U'\n", format_unformat_error, line_input);
362           return -99;
363         }
364     }
365
366   if (local_set == 0)
367     {
368       errmsg ("destination address not specified\n");
369       return -99;
370     }
371   if (ipv4_set && ipv6_set)
372     {
373       errmsg ("both IPv4 and IPv6 addresses specified");
374       return -99;
375     }
376
377
378   M (VXLAN_GPE_IOAM_TRANSIT_ENABLE, mp);
379
380
381   if (ipv6_set)
382     {
383       errmsg ("IPv6 currently unsupported");
384       return -1;
385     }
386   else
387     {
388       clib_memcpy (&mp->dst_addr, &local4, sizeof (local4));
389     }
390
391   mp->outer_fib_index = htonl (outer_fib_index);
392   mp->is_ipv6 = ipv6_set;
393
394   S (mp);
395   W (ret);
396   return ret;
397 }
398
399 static int
400 api_vxlan_gpe_ioam_transit_disable (vat_main_t * vam)
401 {
402   unformat_input_t *line_input = vam->input;
403   vl_api_vxlan_gpe_ioam_transit_disable_t *mp;
404   ip4_address_t local4;
405   ip6_address_t local6;
406   u8 ipv4_set = 0, ipv6_set = 0;
407   u8 local_set = 0;
408   u32 outer_fib_index = 0;
409   int ret;
410
411
412   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
413     {
414       if (unformat (line_input, "dst-ip %U", unformat_ip4_address, &local4))
415         {
416           local_set = 1;
417           ipv4_set = 1;
418         }
419       else if (unformat (line_input, "dst-ip %U",
420                          unformat_ip6_address, &local6))
421         {
422           local_set = 1;
423           ipv6_set = 1;
424         }
425
426       else if (unformat (line_input, "outer-fib-index %d", &outer_fib_index))
427         ;
428       else
429         {
430           errmsg ("parse error '%U'\n", format_unformat_error, line_input);
431           return -99;
432         }
433     }
434
435   if (local_set == 0)
436     {
437       errmsg ("destination address not specified\n");
438       return -99;
439     }
440   if (ipv4_set && ipv6_set)
441     {
442       errmsg ("both IPv4 and IPv6 addresses specified");
443       return -99;
444     }
445
446
447   M (VXLAN_GPE_IOAM_TRANSIT_DISABLE, mp);
448
449
450   if (ipv6_set)
451     {
452       return -1;
453     }
454   else
455     {
456       clib_memcpy (&mp->dst_addr, &local4, sizeof (local4));
457     }
458
459   mp->outer_fib_index = htonl (outer_fib_index);
460   mp->is_ipv6 = ipv6_set;
461
462   S (mp);
463   W (ret);
464   return ret;
465 }
466
467 /*
468  * List of messages that the api test plugin sends,
469  * and that the data plane plugin processes
470  */
471 #define foreach_vpe_api_msg \
472 _(vxlan_gpe_ioam_enable, ""\
473   "[trace] [pow] [ppc <encap|ppc decap>]") \
474 _(vxlan_gpe_ioam_disable, "")                    \
475 _(vxlan_gpe_ioam_vni_enable, ""\
476   "local <local_vtep_ip> remote <remote_vtep_ip> vni <vnid>") \
477 _(vxlan_gpe_ioam_vni_disable, ""\
478   "local <local_vtep_ip> remote <remote_vtep_ip> vni <vnid>") \
479 _(vxlan_gpe_ioam_transit_enable, ""\
480   "dst-ip <dst_ip> [outer-fib-index <outer_fib_index>]") \
481 _(vxlan_gpe_ioam_transit_disable, ""\
482   "dst-ip <dst_ip> [outer-fib-index <outer_fib_index>]") \
483
484
485 static void
486 vxlan_gpe_vat_api_hookup (vat_main_t * vam)
487 {
488   vxlan_gpe_test_main_t *sm = &vxlan_gpe_test_main;
489   /* Hook up handlers for replies from the data plane plug-in */
490 #define _(N,n)                                                  \
491     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
492                            #n,                                  \
493                            vl_api_##n##_t_handler,              \
494                            vl_noop_handler,                     \
495                            vl_api_##n##_t_endian,               \
496                            vl_api_##n##_t_print,                \
497                            sizeof(vl_api_##n##_t), 1);
498   foreach_vpe_api_reply_msg;
499 #undef _
500
501   /* API messages we can send */
502 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
503   foreach_vpe_api_msg;
504 #undef _
505
506   /* Help strings */
507 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
508   foreach_vpe_api_msg;
509 #undef _
510 }
511
512 clib_error_t *
513 vxlan_gpe_vat_plugin_register (vat_main_t * vam)
514 {
515   vxlan_gpe_test_main_t *sm = &vxlan_gpe_test_main;
516   u8 *name;
517
518   sm->vat_main = vam;
519
520   name = format (0, "ioam_vxlan_gpe_%08x%c", api_version, 0);
521   sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name);
522
523   if (sm->msg_id_base != (u16) ~ 0)
524     vxlan_gpe_vat_api_hookup (vam);
525
526   vec_free (name);
527
528   return 0;
529 }
530
531 /*
532  * fd.io coding-style-patch-verification: ON
533  *
534  * Local Variables:
535  * eval: (c-set-style "gnu")
536  * End:
537  */