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