lb: fix that lb_add_del_vip and lb_add_del_as api doesn't work correctly
[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 #include <vnet/ip/ip_types_api.h>
20
21 #include <vppinfra/error.h>
22 #include <lb/lb.h>
23
24 #define __plugin_msg_base lb_test_main.msg_id_base
25 #include <vlibapi/vat_helper_macros.h>
26
27 #include <vnet/format_fns.h>
28 #include <lb/lb.api_enum.h>
29 #include <lb/lb.api_types.h>
30
31 //TODO: Move that to vat/plugin_api.c
32 //////////////////////////
33 uword unformat_ip46_address (unformat_input_t * input, va_list * args)
34 {
35   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
36   ip46_type_t type = va_arg (*args, ip46_type_t);
37   if ((type != IP46_TYPE_IP6) &&
38       unformat(input, "%U", unformat_ip4_address, &ip46->ip4)) {
39     ip46_address_mask_ip4(ip46);
40     return 1;
41   } else if ((type != IP46_TYPE_IP4) &&
42       unformat(input, "%U", unformat_ip6_address, &ip46->ip6)) {
43     return 1;
44   }
45   return 0;
46 }
47 uword unformat_ip46_prefix (unformat_input_t * input, va_list * args)
48 {
49   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
50   u8 *len = va_arg (*args, u8 *);
51   ip46_type_t type = va_arg (*args, ip46_type_t);
52
53   u32 l;
54   if ((type != IP46_TYPE_IP6) && unformat(input, "%U/%u", unformat_ip4_address, &ip46->ip4, &l)) {
55     if (l > 32)
56       return 0;
57     *len = l + 96;
58     ip46->pad[0] = ip46->pad[1] = ip46->pad[2] = 0;
59   } else if ((type != IP46_TYPE_IP4) && unformat(input, "%U/%u", unformat_ip6_address, &ip46->ip6, &l)) {
60     if (l > 128)
61       return 0;
62     *len = l;
63   } else {
64     return 0;
65   }
66   return 1;
67 }
68 /////////////////////////
69
70 typedef struct {
71     /* API message ID base */
72     u16 msg_id_base;
73     vat_main_t *vat_main;
74 } lb_test_main_t;
75
76 lb_test_main_t lb_test_main;
77
78 static int api_lb_conf (vat_main_t * vam)
79 {
80   unformat_input_t *line_input = vam->input;
81   vl_api_lb_conf_t *mp;
82   u32 ip4_src_address = 0xffffffff;
83   ip46_address_t ip6_src_address;
84   u32 sticky_buckets_per_core = LB_DEFAULT_PER_CPU_STICKY_BUCKETS;
85   u32 flow_timeout = LB_DEFAULT_FLOW_TIMEOUT;
86   int ret;
87
88   ip6_src_address.as_u64[0] = 0xffffffffffffffffL;
89   ip6_src_address.as_u64[1] = 0xffffffffffffffffL;
90
91   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
92   {
93     if (unformat(line_input, "ip4-src-address %U", unformat_ip4_address, &ip4_src_address))
94       ;
95     else if (unformat(line_input, "ip6-src-address %U", unformat_ip6_address, &ip6_src_address))
96       ;
97     else if (unformat(line_input, "buckets %d", &sticky_buckets_per_core))
98       ;
99     else if (unformat(line_input, "timeout %d", &flow_timeout))
100       ;
101     else {
102         errmsg ("invalid arguments\n");
103         return -99;
104     }
105   }
106
107   M(LB_CONF, mp);
108   clib_memcpy (&(mp->ip4_src_address), &ip4_src_address, sizeof (ip4_src_address));
109   clib_memcpy (&(mp->ip6_src_address), &ip6_src_address, sizeof (ip6_src_address));
110   mp->sticky_buckets_per_core = htonl (sticky_buckets_per_core);
111   mp->flow_timeout = htonl (flow_timeout);
112
113   S(mp);
114   W (ret);
115   return ret;
116 }
117
118 static int api_lb_add_del_vip (vat_main_t * vam)
119 {
120   unformat_input_t *line_input = vam->input;
121   vl_api_lb_add_del_vip_t *mp;
122   int ret;
123   ip46_address_t ip_prefix;
124   u8 prefix_length = 0;
125   u8 protocol = 0;
126   u32 port = 0;
127   u32 encap = 0;
128   u32 dscp = ~0;
129   u32 srv_type = LB_SRV_TYPE_CLUSTERIP;
130   u32 target_port = 0;
131   u32 new_length = 1024;
132   int is_del = 0;
133
134   if (!unformat(line_input, "%U", unformat_ip46_prefix, &ip_prefix,
135                 &prefix_length, IP46_TYPE_ANY, &prefix_length)) {
136     errmsg ("lb_add_del_vip: invalid vip prefix\n");
137     return -99;
138   }
139
140   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
141   {
142     if (unformat(line_input, "new_len %d", &new_length))
143       ;
144     else if (unformat(line_input, "del"))
145       is_del = 1;
146     else if (unformat(line_input, "protocol tcp"))
147       {
148         protocol = IP_PROTOCOL_TCP;
149       }
150     else if (unformat(line_input, "protocol udp"))
151       {
152         protocol = IP_PROTOCOL_UDP;
153       }
154     else if (unformat(line_input, "port %d", &port))
155       ;
156     else if (unformat(line_input, "encap gre4"))
157       encap = LB_ENCAP_TYPE_GRE4;
158     else if (unformat(line_input, "encap gre6"))
159       encap = LB_ENCAP_TYPE_GRE6;
160     else if (unformat(line_input, "encap l3dsr"))
161       encap = LB_ENCAP_TYPE_L3DSR;
162     else if (unformat(line_input, "encap nat4"))
163       encap = LB_ENCAP_TYPE_NAT4;
164     else if (unformat(line_input, "encap nat6"))
165       encap = LB_ENCAP_TYPE_NAT6;
166     else if (unformat(line_input, "dscp %d", &dscp))
167       ;
168     else if (unformat(line_input, "type clusterip"))
169       srv_type = LB_SRV_TYPE_CLUSTERIP;
170     else if (unformat(line_input, "type nodeport"))
171       srv_type = LB_SRV_TYPE_NODEPORT;
172     else if (unformat(line_input, "target_port %d", &target_port))
173       ;
174     else {
175         errmsg ("invalid arguments\n");
176         return -99;
177     }
178   }
179
180   if ((encap != LB_ENCAP_TYPE_L3DSR) && (dscp != ~0))
181     {
182       errmsg("lb_vip_add error: should not configure dscp for none L3DSR.");
183       return -99;
184     }
185
186   if ((encap == LB_ENCAP_TYPE_L3DSR) && (dscp >= 64))
187     {
188       errmsg("lb_vip_add error: dscp for L3DSR should be less than 64.");
189       return -99;
190     }
191
192   M(LB_ADD_DEL_VIP, mp);
193   ip_address_encode(&ip_prefix, IP46_TYPE_ANY, &mp->pfx.address);
194   mp->pfx.len = prefix_length;
195   mp->protocol = (u8)protocol;
196   mp->port = htons((u16)port);
197   mp->encap = (u8)encap;
198   mp->dscp = (u8)dscp;
199   mp->type = (u8)srv_type;
200   mp->target_port = htons((u16)target_port);
201   mp->node_port = htons((u16)target_port);
202   mp->new_flows_table_length = htonl(new_length);
203   mp->is_del = is_del;
204
205   S(mp);
206   W (ret);
207   return ret;
208 }
209
210 static int api_lb_add_del_as (vat_main_t * vam)
211 {
212
213   unformat_input_t *line_input = vam->input;
214   vl_api_lb_add_del_as_t *mp;
215   int ret;
216   ip46_address_t vip_prefix, as_addr;
217   u8 vip_plen;
218   ip46_address_t *as_array = 0;
219   u32 port = 0;
220   u8 protocol = 0;
221   u8 is_del = 0;
222   u8 is_flush = 0;
223
224   if (!unformat(line_input, "%U", unformat_ip46_prefix,
225                 &vip_prefix, &vip_plen, IP46_TYPE_ANY))
226   {
227       errmsg ("lb_add_del_as: invalid vip prefix\n");
228       return -99;
229   }
230
231   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
232   {
233     if (unformat(line_input, "%U", unformat_ip46_address,
234                  &as_addr, IP46_TYPE_ANY))
235       {
236         vec_add1(as_array, as_addr);
237       }
238     else if (unformat(line_input, "del"))
239       {
240         is_del = 1;
241       }
242     else if (unformat(line_input, "flush"))
243       {
244         is_flush = 1;
245       }
246     else if (unformat(line_input, "protocol tcp"))
247       {
248           protocol = IP_PROTOCOL_TCP;
249       }
250     else if (unformat(line_input, "protocol udp"))
251       {
252           protocol = IP_PROTOCOL_UDP;
253       }
254     else if (unformat(line_input, "port %d", &port))
255       ;
256     else {
257         errmsg ("invalid arguments\n");
258         return -99;
259     }
260   }
261
262   if (!vec_len(as_array)) {
263     errmsg ("No AS address provided \n");
264     return -99;
265   }
266
267   M(LB_ADD_DEL_AS, mp);
268   ip_address_encode(&vip_prefix, IP46_TYPE_ANY, &mp->pfx.address);
269   mp->pfx.len = vip_plen;
270   mp->protocol = (u8)protocol;
271   mp->port = htons((u16)port);
272   ip_address_encode(&as_addr, IP46_TYPE_ANY, &mp->as_address);
273   mp->is_del = is_del;
274   mp->is_flush = is_flush;
275
276   S(mp);
277   W (ret);
278   return ret;
279 }
280
281 static int api_lb_flush_vip (vat_main_t * vam)
282 {
283
284   unformat_input_t *line_input = vam->input;
285   vl_api_lb_flush_vip_t *mp;
286   int ret;
287   ip46_address_t vip_prefix;
288   u8 vip_plen;
289
290   if (!unformat(line_input, "%U", unformat_ip46_prefix,
291                 &vip_prefix, &vip_plen, IP46_TYPE_ANY))
292   {
293       errmsg ("lb_add_del_as: invalid vip prefix\n");
294       return -99;
295   }
296
297   M(LB_FLUSH_VIP, mp);
298   clib_memcpy (mp->pfx.address.un.ip6, &vip_prefix.ip6, sizeof (vip_prefix.ip6));
299   mp->pfx.len = vip_plen;
300   S(mp);
301   W (ret);
302   return ret;
303 }
304 static int api_lb_add_del_intf_nat4 (vat_main_t * vam)
305 {
306   // Not yet implemented
307   return -99;
308 }
309
310 static int api_lb_add_del_intf_nat6 (vat_main_t * vam)
311 {
312   // Not yet implemented
313   return -99;
314 }
315
316 static void vl_api_lb_vip_details_t_handler
317   (vl_api_lb_vip_details_t * mp)
318 {
319   vat_main_t *vam = &vat_main;
320
321   print (vam->ofp, "%24U%14d%14d%18d",
322        format_ip46_address, &mp->vip.pfx.address, IP46_TYPE_ANY,
323        mp->vip.pfx.len,
324        mp->vip.protocol,
325        ntohs (mp->vip.port));
326 /*
327   lb_main_t *lbm = &lb_main;
328   u32 i = 0;
329
330   u32 vip_count = pool_len(lbm->vips);
331
332   print (vam->ofp, "%11d", vip_count);
333
334   for (i=0; i<vip_count; i--)
335     {
336       print (vam->ofp, "%24U%14d%14d%18d",
337            format_ip46_address, &mp->vip.pfx.address, IP46_TYPE_ANY,
338            mp->vip.pfx.len,
339            mp->vip.protocol,
340            ntohs (mp->vip.port));
341     }
342 */
343 }
344
345 static int api_lb_vip_dump (vat_main_t * vam)
346 {
347   vl_api_lb_vip_dump_t *mp;
348   int ret;
349
350   M(LB_VIP_DUMP, mp);
351
352   S(mp);
353   W (ret);
354   return ret;
355 }
356
357 static void vl_api_lb_as_details_t_handler
358   (vl_api_lb_as_details_t * mp)
359 {
360   vat_main_t *vam = &vat_main;
361
362   print (vam->ofp, "%24U%14d%14d%18d%d%d",
363        format_ip46_address, &mp->vip.pfx.address, IP46_TYPE_ANY,
364        mp->vip.pfx.len,
365        mp->vip.protocol,
366        ntohs (mp->vip.port),
367        mp->flags,
368        mp->in_use_since);
369
370   //u32 i = 0;
371
372 /*
373   lb_main_t *lbm = &lb_main;
374   print (vam->ofp, "%11d", pool_len(lbm->ass));
375   for (i=0; i<pool_len(lbm->ass); i--)
376     {
377       print (vam->ofp, "%24U%14d%14d%18d",
378            format_ip46_address, &mp->pfx.address, IP46_TYPE_ANY,
379            mp->pfx.len,
380            mp->pfx.protocol,
381            ntohs (mp->pfx.port),
382            ntohl(mp->app_srv),
383            mp->flags,
384            mp->in_use_;
385     }
386     */
387 }
388
389 static int api_lb_as_dump (vat_main_t * vam)
390 {
391
392   unformat_input_t *line_input = vam->input;
393   vl_api_lb_as_dump_t *mp;
394   int ret;
395   ip46_address_t vip_prefix, as_addr;
396   u8 vip_plen;
397   ip46_address_t *as_array = 0;
398   u32 port = 0;
399   u8 protocol = 0;
400
401   if (!unformat(line_input, "%U", unformat_ip46_prefix,
402                 &vip_prefix, &vip_plen, IP46_TYPE_ANY))
403   {
404       errmsg ("lb_add_del_as: invalid vip prefix\n");
405       return -99;
406   }
407
408   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
409   {
410     if (unformat(line_input, "%U", unformat_ip46_address,
411                  &as_addr, IP46_TYPE_ANY))
412       {
413         vec_add1(as_array, as_addr);
414       }
415     else if (unformat(line_input, "protocol tcp"))
416       {
417           protocol = IP_PROTOCOL_TCP;
418       }
419     else if (unformat(line_input, "protocol udp"))
420       {
421           protocol = IP_PROTOCOL_UDP;
422       }
423     else if (unformat(line_input, "port %d", &port))
424       ;
425     else {
426         errmsg ("invalid arguments\n");
427         return -99;
428     }
429   }
430
431   if (!vec_len(as_array)) {
432     errmsg ("No AS address provided \n");
433     return -99;
434   }
435
436   M(LB_AS_DUMP, mp);
437   clib_memcpy (mp->pfx.address.un.ip6, &vip_prefix.ip6, sizeof (vip_prefix.ip6));
438   mp->pfx.len = vip_plen;
439   mp->protocol = (u8)protocol;
440   mp->port = htons((u16)port);
441
442   S(mp);
443   W (ret);
444   return ret;
445 }
446
447 #include <lb/lb.api_test.c>