api: autogenerate api trace print/endian
[vpp.git] / src / plugins / lb / lb_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 #include <vat/vat.h>
17 #include <vlibapi/api.h>
18 #include <vlibmemory/api.h>
19
20 #include <vppinfra/error.h>
21 #include <lb/lb.h>
22
23 #define __plugin_msg_base lb_test_main.msg_id_base
24 #include <vlibapi/vat_helper_macros.h>
25
26 //TODO: Move that to vat/plugin_api.c
27 //////////////////////////
28 uword unformat_ip46_address (unformat_input_t * input, va_list * args)
29 {
30   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
31   ip46_type_t type = va_arg (*args, ip46_type_t);
32   if ((type != IP46_TYPE_IP6) &&
33       unformat(input, "%U", unformat_ip4_address, &ip46->ip4)) {
34     ip46_address_mask_ip4(ip46);
35     return 1;
36   } else if ((type != IP46_TYPE_IP4) &&
37       unformat(input, "%U", unformat_ip6_address, &ip46->ip6)) {
38     return 1;
39   }
40   return 0;
41 }
42 uword unformat_ip46_prefix (unformat_input_t * input, va_list * args)
43 {
44   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
45   u8 *len = va_arg (*args, u8 *);
46   ip46_type_t type = va_arg (*args, ip46_type_t);
47
48   u32 l;
49   if ((type != IP46_TYPE_IP6) && unformat(input, "%U/%u", unformat_ip4_address, &ip46->ip4, &l)) {
50     if (l > 32)
51       return 0;
52     *len = l + 96;
53     ip46->pad[0] = ip46->pad[1] = ip46->pad[2] = 0;
54   } else if ((type != IP46_TYPE_IP4) && unformat(input, "%U/%u", unformat_ip6_address, &ip46->ip6, &l)) {
55     if (l > 128)
56       return 0;
57     *len = l;
58   } else {
59     return 0;
60   }
61   return 1;
62 }
63 /////////////////////////
64
65 #define vl_msg_id(n,h) n,
66 typedef enum {
67 #include <lb/lb.api.h>
68     /* We'll want to know how many messages IDs we need... */
69     VL_MSG_FIRST_AVAILABLE,
70 } vl_msg_id_t;
71 #undef vl_msg_id
72
73 /* define message structures */
74 #define vl_typedefs
75 #include <lb/lb.api.h>
76 #undef vl_typedefs
77
78 /* declare message handlers for each api */
79
80 #define vl_endianfun             /* define message structures */
81 #include <lb/lb.api.h>
82 #undef vl_endianfun
83
84 /* instantiate all the print functions we know about */
85 #define vl_print(handle, ...)
86 #define vl_printfun
87 #include <vnet/format_fns.h>
88 #include <lb/lb.api.h>
89 #undef vl_printfun
90
91 /* Get the API version number. */
92 #define vl_api_version(n,v) static u32 api_version=(v);
93 #include <lb/lb.api.h>
94 #undef vl_api_version
95
96 typedef struct {
97     /* API message ID base */
98     u16 msg_id_base;
99     vat_main_t *vat_main;
100 } lb_test_main_t;
101
102 lb_test_main_t lb_test_main;
103
104 #define foreach_standard_reply_retval_handler   \
105 _(lb_conf_reply)                 \
106 _(lb_add_del_vip_reply)          \
107 _(lb_add_del_as_reply)
108
109 #define _(n)                                            \
110     static void vl_api_##n##_t_handler                  \
111     (vl_api_##n##_t * mp)                               \
112     {                                                   \
113         vat_main_t * vam = lb_test_main.vat_main;   \
114         i32 retval = ntohl(mp->retval);                 \
115         if (vam->async_mode) {                          \
116             vam->async_errors += (retval < 0);          \
117         } else {                                        \
118             vam->retval = retval;                       \
119             vam->result_ready = 1;                      \
120         }                                               \
121     }
122 foreach_standard_reply_retval_handler;
123 #undef _
124
125 /*
126  * Table of message reply handlers, must include boilerplate handlers
127  * we just generated
128  */
129 #define foreach_vpe_api_reply_msg                               \
130   _(LB_CONF_REPLY, lb_conf_reply)                               \
131   _(LB_ADD_DEL_VIP_REPLY, lb_add_del_vip_reply)                 \
132   _(LB_ADD_DEL_AS_REPLY, lb_add_del_as_reply)                   \
133   _(LB_VIP_DETAILS, lb_vip_details)                             \
134   _(LB_AS_DETAILS, lb_as_details)
135
136 static int api_lb_conf (vat_main_t * vam)
137 {
138   unformat_input_t *line_input = vam->input;
139   vl_api_lb_conf_t *mp;
140   u32 ip4_src_address = 0xffffffff;
141   ip46_address_t ip6_src_address;
142   u32 sticky_buckets_per_core = LB_DEFAULT_PER_CPU_STICKY_BUCKETS;
143   u32 flow_timeout = LB_DEFAULT_FLOW_TIMEOUT;
144   int ret;
145
146   ip6_src_address.as_u64[0] = 0xffffffffffffffffL;
147   ip6_src_address.as_u64[1] = 0xffffffffffffffffL;
148
149   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
150   {
151     if (unformat(line_input, "ip4-src-address %U", unformat_ip4_address, &ip4_src_address))
152       ;
153     else if (unformat(line_input, "ip6-src-address %U", unformat_ip6_address, &ip6_src_address))
154       ;
155     else if (unformat(line_input, "buckets %d", &sticky_buckets_per_core))
156       ;
157     else if (unformat(line_input, "timeout %d", &flow_timeout))
158       ;
159     else {
160         errmsg ("invalid arguments\n");
161         return -99;
162     }
163   }
164
165   M(LB_CONF, mp);
166   clib_memcpy (&(mp->ip4_src_address), &ip4_src_address, sizeof (ip4_src_address));
167   clib_memcpy (&(mp->ip6_src_address), &ip6_src_address, sizeof (ip6_src_address));
168   mp->sticky_buckets_per_core = htonl (sticky_buckets_per_core);
169   mp->flow_timeout = htonl (flow_timeout);
170
171   S(mp);
172   W (ret);
173   return ret;
174 }
175
176 static int api_lb_add_del_vip (vat_main_t * vam)
177 {
178   unformat_input_t *line_input = vam->input;
179   vl_api_lb_add_del_vip_t *mp;
180   int ret;
181   ip46_address_t ip_prefix;
182   u8 prefix_length = 0;
183   u8 protocol = 0;
184   u32 port = 0;
185   u32 encap = 0;
186   u32 dscp = ~0;
187   u32 srv_type = LB_SRV_TYPE_CLUSTERIP;
188   u32 target_port = 0;
189   u32 new_length = 1024;
190   int is_del = 0;
191
192   if (!unformat(line_input, "%U", unformat_ip46_prefix, &ip_prefix,
193                 &prefix_length, IP46_TYPE_ANY, &prefix_length)) {
194     errmsg ("lb_add_del_vip: invalid vip prefix\n");
195     return -99;
196   }
197
198   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
199   {
200     if (unformat(line_input, "new_len %d", &new_length))
201       ;
202     else if (unformat(line_input, "del"))
203       is_del = 1;
204     else if (unformat(line_input, "protocol tcp"))
205       {
206         protocol = IP_PROTOCOL_TCP;
207       }
208     else if (unformat(line_input, "protocol udp"))
209       {
210         protocol = IP_PROTOCOL_UDP;
211       }
212     else if (unformat(line_input, "port %d", &port))
213       ;
214     else if (unformat(line_input, "encap gre4"))
215       encap = LB_ENCAP_TYPE_GRE4;
216     else if (unformat(line_input, "encap gre6"))
217       encap = LB_ENCAP_TYPE_GRE6;
218     else if (unformat(line_input, "encap l3dsr"))
219       encap = LB_ENCAP_TYPE_L3DSR;
220     else if (unformat(line_input, "encap nat4"))
221       encap = LB_ENCAP_TYPE_NAT4;
222     else if (unformat(line_input, "encap nat6"))
223       encap = LB_ENCAP_TYPE_NAT6;
224     else if (unformat(line_input, "dscp %d", &dscp))
225       ;
226     else if (unformat(line_input, "type clusterip"))
227       srv_type = LB_SRV_TYPE_CLUSTERIP;
228     else if (unformat(line_input, "type nodeport"))
229       srv_type = LB_SRV_TYPE_NODEPORT;
230     else if (unformat(line_input, "target_port %d", &target_port))
231       ;
232     else {
233         errmsg ("invalid arguments\n");
234         return -99;
235     }
236   }
237
238   if ((encap != LB_ENCAP_TYPE_L3DSR) && (dscp != ~0))
239     {
240       errmsg("lb_vip_add error: should not configure dscp for none L3DSR.");
241       return -99;
242     }
243
244   if ((encap == LB_ENCAP_TYPE_L3DSR) && (dscp >= 64))
245     {
246       errmsg("lb_vip_add error: dscp for L3DSR should be less than 64.");
247       return -99;
248     }
249
250   M(LB_ADD_DEL_VIP, mp);
251   clib_memcpy (mp->pfx.address.un.ip6, &ip_prefix.ip6, sizeof (ip_prefix.ip6));
252   mp->pfx.len = prefix_length;
253   mp->protocol = (u8)protocol;
254   mp->port = htons((u16)port);
255   mp->encap = (u8)encap;
256   mp->dscp = (u8)dscp;
257   mp->type = (u8)srv_type;
258   mp->target_port = htons((u16)target_port);
259   mp->node_port = htons((u16)target_port);
260   mp->new_flows_table_length = htonl(new_length);
261   mp->is_del = is_del;
262
263   S(mp);
264   W (ret);
265   return ret;
266 }
267
268 static int api_lb_add_del_as (vat_main_t * vam)
269 {
270
271   unformat_input_t *line_input = vam->input;
272   vl_api_lb_add_del_as_t *mp;
273   int ret;
274   ip46_address_t vip_prefix, as_addr;
275   u8 vip_plen;
276   ip46_address_t *as_array = 0;
277   u32 port = 0;
278   u8 protocol = 0;
279   u8 is_del = 0;
280   u8 is_flush = 0;
281
282   if (!unformat(line_input, "%U", unformat_ip46_prefix,
283                 &vip_prefix, &vip_plen, IP46_TYPE_ANY))
284   {
285       errmsg ("lb_add_del_as: invalid vip prefix\n");
286       return -99;
287   }
288
289   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
290   {
291     if (unformat(line_input, "%U", unformat_ip46_address,
292                  &as_addr, IP46_TYPE_ANY))
293       {
294         vec_add1(as_array, as_addr);
295       }
296     else if (unformat(line_input, "del"))
297       {
298         is_del = 1;
299       }
300     else if (unformat(line_input, "flush"))
301       {
302         is_flush = 1;
303       }
304     else if (unformat(line_input, "protocol tcp"))
305       {
306           protocol = IP_PROTOCOL_TCP;
307       }
308     else if (unformat(line_input, "protocol udp"))
309       {
310           protocol = IP_PROTOCOL_UDP;
311       }
312     else if (unformat(line_input, "port %d", &port))
313       ;
314     else {
315         errmsg ("invalid arguments\n");
316         return -99;
317     }
318   }
319
320   if (!vec_len(as_array)) {
321     errmsg ("No AS address provided \n");
322     return -99;
323   }
324
325   M(LB_ADD_DEL_AS, mp);
326   clib_memcpy (mp->pfx.address.un.ip6, &vip_prefix.ip6, sizeof (vip_prefix.ip6));
327   mp->pfx.len = vip_plen;
328   mp->protocol = (u8)protocol;
329   mp->port = htons((u16)port);
330   clib_memcpy (&mp->as_address, &as_addr, sizeof (as_addr));
331   mp->is_del = is_del;
332   mp->is_flush = is_flush;
333
334   S(mp);
335   W (ret);
336   return ret;
337 }
338
339 static void vl_api_lb_vip_details_t_handler
340   (vl_api_lb_vip_details_t * mp)
341 {
342   vat_main_t *vam = &vat_main;
343
344   print (vam->ofp, "%24U%14d%14d%18d",
345        format_ip46_address, &mp->vip.pfx.address, IP46_TYPE_ANY,
346        mp->vip.pfx.len,
347        mp->vip.protocol,
348        ntohs (mp->vip.port));
349 /*
350   lb_main_t *lbm = &lb_main;
351   u32 i = 0;
352
353   u32 vip_count = pool_len(lbm->vips);
354
355   print (vam->ofp, "%11d", vip_count);
356
357   for (i=0; i<vip_count; i--)
358     {
359       print (vam->ofp, "%24U%14d%14d%18d",
360            format_ip46_address, &mp->vip.pfx.address, IP46_TYPE_ANY,
361            mp->vip.pfx.len,
362            mp->vip.protocol,
363            ntohs (mp->vip.port));
364     }
365 */
366 }
367
368 static int api_lb_vip_dump (vat_main_t * vam)
369 {
370   vl_api_lb_vip_dump_t *mp;
371   int ret;
372
373   M(LB_VIP_DUMP, mp);
374
375   S(mp);
376   W (ret);
377   return ret;
378 }
379
380 static void vl_api_lb_as_details_t_handler
381   (vl_api_lb_as_details_t * mp)
382 {
383   vat_main_t *vam = &vat_main;
384
385   print (vam->ofp, "%24U%14d%14d%18d%d%d",
386        format_ip46_address, &mp->vip.pfx.address, IP46_TYPE_ANY,
387        mp->vip.pfx.len,
388        mp->vip.protocol,
389        ntohs (mp->vip.port),
390        mp->flags,
391        mp->in_use_since);
392
393   //u32 i = 0;
394
395 /*
396   lb_main_t *lbm = &lb_main;
397   print (vam->ofp, "%11d", pool_len(lbm->ass));
398   for (i=0; i<pool_len(lbm->ass); i--)
399     {
400       print (vam->ofp, "%24U%14d%14d%18d",
401            format_ip46_address, &mp->pfx.address, IP46_TYPE_ANY,
402            mp->pfx.len,
403            mp->pfx.protocol,
404            ntohs (mp->pfx.port),
405            ntohl(mp->app_srv),
406            mp->flags,
407            mp->in_use_;
408     }
409     */
410 }
411
412 static int api_lb_as_dump (vat_main_t * vam)
413 {
414
415   unformat_input_t *line_input = vam->input;
416   vl_api_lb_as_dump_t *mp;
417   int ret;
418   ip46_address_t vip_prefix, as_addr;
419   u8 vip_plen;
420   ip46_address_t *as_array = 0;
421   u32 port = 0;
422   u8 protocol = 0;
423
424   if (!unformat(line_input, "%U", unformat_ip46_prefix,
425                 &vip_prefix, &vip_plen, IP46_TYPE_ANY))
426   {
427       errmsg ("lb_add_del_as: invalid vip prefix\n");
428       return -99;
429   }
430
431   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
432   {
433     if (unformat(line_input, "%U", unformat_ip46_address,
434                  &as_addr, IP46_TYPE_ANY))
435       {
436         vec_add1(as_array, as_addr);
437       }
438     else if (unformat(line_input, "protocol tcp"))
439       {
440           protocol = IP_PROTOCOL_TCP;
441       }
442     else if (unformat(line_input, "protocol udp"))
443       {
444           protocol = IP_PROTOCOL_UDP;
445       }
446     else if (unformat(line_input, "port %d", &port))
447       ;
448     else {
449         errmsg ("invalid arguments\n");
450         return -99;
451     }
452   }
453
454   if (!vec_len(as_array)) {
455     errmsg ("No AS address provided \n");
456     return -99;
457   }
458
459   M(LB_AS_DUMP, mp);
460   clib_memcpy (mp->pfx.address.un.ip6, &vip_prefix.ip6, sizeof (vip_prefix.ip6));
461   mp->pfx.len = vip_plen;
462   mp->protocol = (u8)protocol;
463   mp->port = htons((u16)port);
464
465   S(mp);
466   W (ret);
467   return ret;
468 }
469
470 /*
471  * List of messages that the api test plugin sends,
472  * and that the data plane plugin processes
473  */
474 #define foreach_vpe_api_msg                             \
475 _(lb_conf, "[ip4-src-address <addr>] [ip6-src-address <addr>] " \
476            "[buckets <n>] [timeout <s>]")  \
477 _(lb_add_del_vip, "<prefix> "  \
478                   "[protocol (tcp|udp) port <n>] "  \
479                   "[encap (gre6|gre4|l3dsr|nat4|nat6)] " \
480                   "[dscp <n>] "  \
481                   "[type (nodeport|clusterip) target_port <n>] " \
482                   "[new_len <n>] [del]")  \
483 _(lb_add_del_as, "<vip-prefix> [protocol (tcp|udp) port <n>] "  \
484                  "[<address>] [del] [flush]")              \
485 _(lb_vip_dump, "")          \
486 _(lb_as_dump, "<vip-prefix> [protocol (tcp|udp) port <n>]")
487
488 static void
489 lb_api_hookup (vat_main_t *vam)
490 {
491   lb_test_main_t * lbtm = &lb_test_main;
492   /* Hook up handlers for replies from the data plane plug-in */
493 #define _(N,n)                                                  \
494   vl_msg_api_set_handlers((VL_API_##N + lbtm->msg_id_base),       \
495                           #n,                                   \
496                           vl_api_##n##_t_handler,               \
497                           vl_noop_handler,                      \
498                           vl_api_##n##_t_endian,                \
499                           vl_api_##n##_t_print,                 \
500                           sizeof(vl_api_##n##_t), 1);
501   foreach_vpe_api_reply_msg;
502 #undef _
503
504   /* API messages we can send */
505 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
506   foreach_vpe_api_msg;
507 #undef _
508
509   /* Help strings */
510 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
511   foreach_vpe_api_msg;
512 #undef _
513 }
514
515 VAT_PLUGIN_REGISTER(lb);