gtpu: use explicit types in api
[vpp.git] / src / plugins / gtpu / gtpu_test.c
1 /*
2  * Copyright (c) 2017 Intel 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 #include <gtpu/gtpu.h>
21 #include <vnet/ip/ip_types_api.h>
22
23 #define __plugin_msg_base gtpu_test_main.msg_id_base
24 #include <vlibapi/vat_helper_macros.h>
25
26 #include <vnet/format_fns.h>
27 #include <gtpu/gtpu.api_enum.h>
28 #include <gtpu/gtpu.api_types.h>
29
30 uword unformat_ip46_address (unformat_input_t * input, va_list * args)
31 {
32   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
33   ip46_type_t type = va_arg (*args, ip46_type_t);
34   if ((type != IP46_TYPE_IP6) &&
35       unformat(input, "%U", unformat_ip4_address, &ip46->ip4)) {
36     ip46_address_mask_ip4(ip46);
37     return 1;
38   } else if ((type != IP46_TYPE_IP4) &&
39       unformat(input, "%U", unformat_ip6_address, &ip46->ip6)) {
40     return 1;
41   }
42   return 0;
43 }
44 uword unformat_ip46_prefix (unformat_input_t * input, va_list * args)
45 {
46   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
47   u8 *len = va_arg (*args, u8 *);
48   ip46_type_t type = va_arg (*args, ip46_type_t);
49
50   u32 l;
51   if ((type != IP46_TYPE_IP6) && unformat(input, "%U/%u", unformat_ip4_address, &ip46->ip4, &l)) {
52     if (l > 32)
53       return 0;
54     *len = l + 96;
55     ip46->pad[0] = ip46->pad[1] = ip46->pad[2] = 0;
56   } else if ((type != IP46_TYPE_IP4) && unformat(input, "%U/%u", unformat_ip6_address, &ip46->ip6, &l)) {
57     if (l > 128)
58       return 0;
59     *len = l;
60   } else {
61     return 0;
62   }
63   return 1;
64 }
65 /////////////////////////
66
67 typedef struct {
68     /* API message ID base */
69     u16 msg_id_base;
70     vat_main_t *vat_main;
71 } gtpu_test_main_t;
72
73 gtpu_test_main_t gtpu_test_main;
74
75 static void vl_api_gtpu_add_del_tunnel_reply_t_handler
76   (vl_api_gtpu_add_del_tunnel_reply_t * mp)
77 {
78   vat_main_t *vam = &vat_main;
79   i32 retval = ntohl (mp->retval);
80   if (vam->async_mode)
81     {
82       vam->async_errors += (retval < 0);
83     }
84   else
85     {
86       vam->retval = retval;
87       vam->sw_if_index = ntohl (mp->sw_if_index);
88       vam->result_ready = 1;
89     }
90 }
91
92 static uword
93 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
94 {
95   vat_main_t *vam = va_arg (*args, vat_main_t *);
96   u32 *result = va_arg (*args, u32 *);
97   u8 *if_name;
98   uword *p;
99
100   if (!unformat (input, "%s", &if_name))
101     return 0;
102
103   p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
104   if (p == 0)
105     return 0;
106   *result = p[0];
107   return 1;
108 }
109
110 static int
111 api_sw_interface_set_gtpu_bypass (vat_main_t * vam)
112 {
113   unformat_input_t *i = vam->input;
114   vl_api_sw_interface_set_gtpu_bypass_t *mp;
115   u32 sw_if_index = 0;
116   u8 sw_if_index_set = 0;
117   u8 is_enable = 1;
118   u8 is_ipv6 = 0;
119   int ret;
120
121   /* Parse args required to build the message */
122   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
123     {
124       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
125       sw_if_index_set = 1;
126       else if (unformat (i, "sw_if_index %d", &sw_if_index))
127       sw_if_index_set = 1;
128       else if (unformat (i, "enable"))
129       is_enable = 1;
130       else if (unformat (i, "disable"))
131       is_enable = 0;
132       else if (unformat (i, "ip4"))
133       is_ipv6 = 0;
134       else if (unformat (i, "ip6"))
135       is_ipv6 = 1;
136       else
137       break;
138     }
139
140   if (sw_if_index_set == 0)
141     {
142       errmsg ("missing interface name or sw_if_index");
143       return -99;
144     }
145
146   /* Construct the API message */
147   M (SW_INTERFACE_SET_GTPU_BYPASS, mp);
148
149   mp->sw_if_index = ntohl (sw_if_index);
150   mp->enable = is_enable;
151   mp->is_ipv6 = is_ipv6;
152
153   /* send it... */
154   S (mp);
155
156   /* Wait for a reply... */
157   W (ret);
158   return ret;
159 }
160
161 static uword unformat_gtpu_decap_next
162   (unformat_input_t * input, va_list * args)
163 {
164   u32 *result = va_arg (*args, u32 *);
165   u32 tmp;
166
167   if (unformat (input, "l2"))
168     *result = GTPU_INPUT_NEXT_L2_INPUT;
169   else if (unformat (input, "%d", &tmp))
170     *result = tmp;
171   else
172     return 0;
173   return 1;
174 }
175
176 static int
177 api_gtpu_add_del_tunnel (vat_main_t * vam)
178 {
179   unformat_input_t *line_input = vam->input;
180   vl_api_gtpu_add_del_tunnel_t *mp;
181   ip46_address_t src, dst;
182   u8 is_add = 1;
183   u8 ipv4_set = 0, ipv6_set = 0;
184   u8 src_set = 0;
185   u8 dst_set = 0;
186   u8 grp_set = 0;
187   u32 mcast_sw_if_index = ~0;
188   u32 encap_vrf_id = 0;
189   u32 decap_next_index = ~0;
190   u32 teid = 0;
191   int ret;
192
193   /* Can't "universally zero init" (={0}) due to GCC bug 53119 */
194   clib_memset (&src, 0, sizeof src);
195   clib_memset (&dst, 0, sizeof dst);
196
197   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
198     {
199       if (unformat (line_input, "del"))
200       is_add = 0;
201       else
202       if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4))
203       {
204         ipv4_set = 1;
205         src_set = 1;
206       }
207       else
208       if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4))
209       {
210         ipv4_set = 1;
211         dst_set = 1;
212       }
213       else
214       if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6))
215       {
216         ipv6_set = 1;
217         src_set = 1;
218       }
219       else
220       if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6))
221       {
222         ipv6_set = 1;
223         dst_set = 1;
224       }
225       else if (unformat (line_input, "group %U %U",
226                        unformat_ip4_address, &dst.ip4,
227                        api_unformat_sw_if_index, vam, &mcast_sw_if_index))
228       {
229         grp_set = dst_set = 1;
230         ipv4_set = 1;
231       }
232       else if (unformat (line_input, "group %U",
233                        unformat_ip4_address, &dst.ip4))
234       {
235         grp_set = dst_set = 1;
236         ipv4_set = 1;
237       }
238       else if (unformat (line_input, "group %U %U",
239                        unformat_ip6_address, &dst.ip6,
240                        api_unformat_sw_if_index, vam, &mcast_sw_if_index))
241       {
242         grp_set = dst_set = 1;
243         ipv6_set = 1;
244       }
245       else if (unformat (line_input, "group %U",
246                        unformat_ip6_address, &dst.ip6))
247       {
248         grp_set = dst_set = 1;
249         ipv6_set = 1;
250       }
251       else
252       if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index))
253       ;
254       else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
255       ;
256       else if (unformat (line_input, "decap-next %U",
257                        unformat_gtpu_decap_next, &decap_next_index))
258       ;
259       else if (unformat (line_input, "teid %d", &teid))
260       ;
261       else
262       {
263         errmsg ("parse error '%U'", format_unformat_error, line_input);
264         return -99;
265       }
266     }
267
268   if (src_set == 0)
269     {
270       errmsg ("tunnel src address not specified");
271       return -99;
272     }
273   if (dst_set == 0)
274     {
275       errmsg ("tunnel dst address not specified");
276       return -99;
277     }
278
279   if (grp_set && !ip46_address_is_multicast (&dst))
280     {
281       errmsg ("tunnel group address not multicast");
282       return -99;
283     }
284   if (grp_set && mcast_sw_if_index == ~0)
285     {
286       errmsg ("tunnel nonexistent multicast device");
287       return -99;
288     }
289   if (grp_set == 0 && ip46_address_is_multicast (&dst))
290     {
291       errmsg ("tunnel dst address must be unicast");
292       return -99;
293     }
294
295
296   if (ipv4_set && ipv6_set)
297     {
298       errmsg ("both IPv4 and IPv6 addresses specified");
299       return -99;
300     }
301
302   M (GTPU_ADD_DEL_TUNNEL, mp);
303
304   ip_address_encode(&src, ipv6_set ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
305                     &mp->src_address);
306   ip_address_encode(&dst, ipv6_set ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
307                     &mp->dst_address);
308   mp->encap_vrf_id = ntohl (encap_vrf_id);
309   mp->decap_next_index = ntohl (decap_next_index);
310   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
311   mp->teid = ntohl (teid);
312   mp->is_add = is_add;
313
314   S (mp);
315   W (ret);
316   return ret;
317 }
318
319 static void vl_api_gtpu_tunnel_details_t_handler
320   (vl_api_gtpu_tunnel_details_t * mp)
321 {
322   vat_main_t *vam = &vat_main;
323   ip46_address_t src;
324   ip46_address_t dst;
325   ip_address_decode(&mp->dst_address, &dst);
326   ip_address_decode(&mp->src_address, &src);
327   print (vam->ofp, "%11d%24U%24U%14d%18d%13d%19d",
328        ntohl (mp->sw_if_index),
329        format_ip46_address, &src, IP46_TYPE_ANY,
330        format_ip46_address, &dst, IP46_TYPE_ANY,
331        ntohl (mp->encap_vrf_id),
332        ntohl (mp->decap_next_index), ntohl (mp->teid),
333        ntohl (mp->mcast_sw_if_index));
334 }
335
336 static int
337 api_gtpu_tunnel_dump (vat_main_t * vam)
338 {
339   unformat_input_t *i = vam->input;
340   vl_api_gtpu_tunnel_dump_t *mp;
341   u32 sw_if_index;
342   u8 sw_if_index_set = 0;
343   int ret;
344
345   /* Parse args required to build the message */
346   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
347     {
348       if (unformat (i, "sw_if_index %d", &sw_if_index))
349       sw_if_index_set = 1;
350       else
351       break;
352     }
353
354   if (sw_if_index_set == 0)
355     {
356       sw_if_index = ~0;
357     }
358
359   if (!vam->json_output)
360     {
361       print (vam->ofp, "%11s%24s%24s%14s%18s%13s%19s",
362            "sw_if_index", "src_address", "dst_address",
363            "encap_vrf_id", "decap_next_index", "teid", "mcast_sw_if_index");
364     }
365
366   /* Get list of gtpu-tunnel interfaces */
367   M (GTPU_TUNNEL_DUMP, mp);
368
369   mp->sw_if_index = htonl (sw_if_index);
370
371   S (mp);
372
373   W (ret);
374   return ret;
375 }
376
377 #include <gtpu/gtpu.api_test.c>