hs-test: logging improvements
[vpp.git] / src / vnet / ipip / ipip_cli.c
1 /*
2  * Copyright (c) 2018 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 "ipip.h"
17 #include <vppinfra/error.h>
18 #include <vnet/vnet.h>
19 #include <vnet/fib/fib_table.h>
20
21 static clib_error_t *
22 create_ipip_tunnel_command_fn (vlib_main_t * vm,
23                                unformat_input_t * input,
24                                vlib_cli_command_t * cmd)
25 {
26   unformat_input_t _line_input, *line_input = &_line_input;
27   ip46_address_t src = ip46_address_initializer, dst =
28     ip46_address_initializer;
29   u32 instance = ~0;
30   u32 fib_index = 0;
31   u32 table_id = 0;
32   int rv;
33   u32 num_m_args = 0;
34   u32 sw_if_index;
35   clib_error_t *error = NULL;
36   bool ip4_set = false, ip6_set = false;
37   tunnel_mode_t mode = TUNNEL_MODE_P2P;
38   tunnel_encap_decap_flags_t flags = TUNNEL_ENCAP_DECAP_FLAG_NONE;
39
40   /* Get a line of input. */
41   if (!unformat_user (input, unformat_line_input, line_input))
42     return 0;
43
44   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
45     {
46       if (unformat (line_input, "instance %d", &instance))
47         ;
48       else
49         if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4))
50         {
51           num_m_args++;
52           ip4_set = true;
53         }
54       else
55         if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4))
56         {
57           num_m_args++;
58           ip4_set = true;
59         }
60       else
61         if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6))
62         {
63           num_m_args++;
64           ip6_set = true;
65         }
66       else
67         if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6))
68         {
69           num_m_args++;
70           ip6_set = true;
71         }
72       else if (unformat (line_input, "%U", unformat_tunnel_mode, &mode))
73         {
74           num_m_args++;
75         }
76       else if (unformat (line_input, "outer-table-id %d", &table_id))
77         ;
78       else
79         if (unformat
80             (line_input, "flags %U", unformat_tunnel_encap_decap_flags,
81              &flags))
82         ;
83       else
84         {
85           error =
86             clib_error_return (0, "unknown input `%U'", format_unformat_error,
87                                line_input);
88           goto done;
89         }
90     }
91
92   if (num_m_args < 2)
93     {
94       error = clib_error_return (0, "mandatory argument(s) missing");
95       goto done;
96     }
97   if (ip4_set && ip6_set)
98     {
99       error =
100         clib_error_return (0,
101                            "source and destination must be of same address family");
102       goto done;
103     }
104
105   fib_index = fib_table_find (fib_ip_proto (ip6_set), table_id);
106
107   if (~0 == fib_index)
108     {
109       rv = VNET_API_ERROR_NO_SUCH_FIB;
110     }
111   else
112     {
113       rv = ipip_add_tunnel (ip6_set ? IPIP_TRANSPORT_IP6 : IPIP_TRANSPORT_IP4,
114                             instance,
115                             &src,
116                             &dst,
117                             fib_index,
118                             flags, IP_DSCP_CS0, mode, &sw_if_index);
119     }
120
121   switch (rv)
122     {
123     case 0:
124       vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
125                        vnet_get_main (), sw_if_index);
126       break;
127     case VNET_API_ERROR_IF_ALREADY_EXISTS:
128       error = clib_error_return (0, "IPIP tunnel already exists...");
129       goto done;
130     case VNET_API_ERROR_NO_SUCH_FIB:
131       error =
132         clib_error_return (0, "outer fib ID %d doesn't exist\n", fib_index);
133       goto done;
134     case VNET_API_ERROR_NO_SUCH_ENTRY:
135       error = clib_error_return (0, "IPIP tunnel doesn't exist");
136       goto done;
137     case VNET_API_ERROR_INSTANCE_IN_USE:
138       error = clib_error_return (0, "Instance is in use");
139       goto done;
140     case VNET_API_ERROR_INVALID_DST_ADDRESS:
141       error =
142         clib_error_return (0,
143                            "destination IP address when mode is multi-point");
144       goto done;
145     default:
146       error =
147         clib_error_return (0, "vnet_ipip_add_del_tunnel returned %d", rv);
148       goto done;
149     }
150
151 done:
152   unformat_free (line_input);
153
154   return error;
155 }
156
157 static clib_error_t *
158 delete_ipip_tunnel_command_fn (vlib_main_t * vm,
159                                unformat_input_t * input,
160                                vlib_cli_command_t * cmd)
161 {
162   unformat_input_t _line_input, *line_input = &_line_input;
163   int rv;
164   u32 num_m_args = 0;
165   u32 sw_if_index = ~0;
166   clib_error_t *error = NULL;
167
168   /* Get a line of input. */
169   if (!unformat_user (input, unformat_line_input, line_input))
170     return 0;
171
172   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
173     {
174       if (unformat (line_input, "sw_if_index %d", &sw_if_index))
175         num_m_args++;
176       else
177         {
178           error =
179             clib_error_return (0, "unknown input `%U'", format_unformat_error,
180                                line_input);
181           goto done;
182         }
183     }
184
185   if (num_m_args < 1)
186     {
187       error = clib_error_return (0, "mandatory argument(s) missing");
188       goto done;
189     }
190
191   rv = ipip_del_tunnel (sw_if_index);
192   printf ("RV %d\n", rv);
193
194 done:
195   unformat_free (line_input);
196
197   return error;
198 }
199
200 VLIB_CLI_COMMAND(create_ipip_tunnel_command, static) = {
201     .path = "create ipip tunnel",
202     .short_help = "create ipip tunnel src <addr> dst <addr> [instance <n>] "
203                   "[outer-table-id <ID>] [p2mp]",
204     .function = create_ipip_tunnel_command_fn,
205 };
206 VLIB_CLI_COMMAND(delete_ipip_tunnel_command, static) = {
207     .path = "delete ipip tunnel",
208     .short_help = "delete ipip tunnel sw_if_index <sw_if_index>",
209     .function = delete_ipip_tunnel_command_fn,
210 };
211
212 static u8 *
213 format_ipip_tunnel (u8 * s, va_list * args)
214 {
215   ipip_tunnel_t *t = va_arg (*args, ipip_tunnel_t *);
216
217   ip46_type_t type =
218     (t->transport == IPIP_TRANSPORT_IP4) ? IP46_TYPE_IP4 : IP46_TYPE_IP6;
219   u32 table_id;
220
221   table_id = fib_table_get_table_id (t->fib_index,
222                                      fib_proto_from_ip46 (type));
223   switch (t->mode)
224     {
225     case IPIP_MODE_6RD:
226       s = format (s, "[%d] 6rd src %U ip6-pfx %U/%d ",
227                   t->dev_instance,
228                   format_ip46_address, &t->tunnel_src, type,
229                   format_ip6_address, &t->sixrd.ip6_prefix,
230                   t->sixrd.ip6_prefix_len);
231       break;
232     case IPIP_MODE_P2P:
233       s = format (s, "[%d] instance %d src %U dst %U ",
234                   t->dev_instance, t->user_instance,
235                   format_ip46_address, &t->tunnel_src, type,
236                   format_ip46_address, &t->tunnel_dst, type);
237       break;
238     case IPIP_MODE_P2MP:
239       s = format (s, "[%d] instance %d p2mp src %U ",
240                   t->dev_instance, t->user_instance,
241                   format_ip46_address, &t->tunnel_src, type);
242       break;
243     }
244
245   s = format (s, "table-ID %d sw-if-idx %d flags [%U] dscp %U",
246               table_id, t->sw_if_index,
247               format_tunnel_encap_decap_flags, t->flags,
248               format_ip_dscp, t->dscp);
249
250   return s;
251 }
252
253 static clib_error_t *
254 show_ipip_tunnel_command_fn (vlib_main_t * vm,
255                              unformat_input_t * input,
256                              vlib_cli_command_t * cmd)
257 {
258   ipip_main_t *gm = &ipip_main;
259   ipip_tunnel_t *t;
260   u32 ti = ~0;
261
262   if (pool_elts (gm->tunnels) == 0)
263     vlib_cli_output (vm, "No IPIP tunnels configured...");
264
265   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
266     {
267       if (unformat (input, "%d", &ti))
268         ;
269       else
270         break;
271     }
272
273   if (ti == ~0)
274     {
275     pool_foreach (t, gm->tunnels)
276                   {vlib_cli_output(vm, "%U", format_ipip_tunnel, t); }
277     }
278   else
279     {
280       if (pool_is_free_index (gm->tunnels, ti))
281         return clib_error_return (0, "unknown index:%d", ti);
282       t = pool_elt_at_index (gm->tunnels, ti);
283       if (t)
284         vlib_cli_output (vm, "%U", format_ipip_tunnel, t);
285     }
286   return 0;
287 }
288
289 VLIB_CLI_COMMAND(show_ipip_tunnel_command, static) = {
290     .path = "show ipip tunnel",
291     .function = show_ipip_tunnel_command_fn,
292 };
293
294 static u8 *
295 format_ipip_tunnel_key (u8 * s, va_list * args)
296 {
297   ipip_tunnel_key_t *t = va_arg (*args, ipip_tunnel_key_t *);
298
299   s = format (s, "src:%U dst:%U fib:%d transport:%d mode:%d",
300               format_ip46_address, &t->src, IP46_TYPE_ANY,
301               format_ip46_address, &t->dst, IP46_TYPE_ANY,
302               t->fib_index, t->transport, t->mode);
303
304   return (s);
305 }
306
307 static clib_error_t *
308 ipip_tunnel_hash_show (vlib_main_t * vm,
309                        unformat_input_t * input, vlib_cli_command_t * cmd)
310 {
311   ipip_main_t *im = &ipip_main;
312   ipip_tunnel_key_t *key;
313   u32 index;
314
315   hash_foreach(key, index, im->tunnel_by_key,
316   ({
317       vlib_cli_output (vm, " %U -> %d", format_ipip_tunnel_key, key, index);
318   }));
319
320   return NULL;
321 }
322
323 /**
324  * show IPSEC tunnel protection hash tables
325  */
326 VLIB_CLI_COMMAND (ipip_tunnel_hash_show_node, static) =
327 {
328   .path = "show ipip tunnel-hash",
329   .function = ipip_tunnel_hash_show,
330   .short_help =  "show ipip tunnel-hash",
331 };
332
333 static clib_error_t *
334 create_sixrd_tunnel_command_fn (vlib_main_t * vm,
335                                 unformat_input_t * input,
336                                 vlib_cli_command_t * cmd)
337 {
338   unformat_input_t _line_input, *line_input = &_line_input;
339   ip4_address_t ip4_prefix;
340   ip6_address_t ip6_prefix;
341   ip4_address_t ip4_src;
342   u32 ip6_prefix_len = 0, ip4_prefix_len = 0, sixrd_tunnel_index;
343   u32 num_m_args = 0;
344   /* Optional arguments */
345   u32 ip4_table_id = 0, ip4_fib_index;
346   u32 ip6_table_id = 0, ip6_fib_index;
347   clib_error_t *error = 0;
348   bool security_check = false;
349   int rv;
350
351   /* Get a line of input. */
352   if (!unformat_user (input, unformat_line_input, line_input))
353     return 0;
354   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
355     {
356       if (unformat (line_input, "security-check"))
357         security_check = true;
358       else if (unformat (line_input, "ip6-pfx %U/%d", unformat_ip6_address,
359                          &ip6_prefix, &ip6_prefix_len))
360         num_m_args++;
361       else if (unformat (line_input, "ip4-pfx %U/%d", unformat_ip4_address,
362                          &ip4_prefix, &ip4_prefix_len))
363         num_m_args++;
364       else
365         if (unformat
366             (line_input, "ip4-src %U", unformat_ip4_address, &ip4_src))
367         num_m_args++;
368       else if (unformat (line_input, "ip4-table-id %d", &ip4_table_id))
369         ;
370       else if (unformat (line_input, "ip6-table-id %d", &ip6_table_id))
371         ;
372       else
373         {
374           error =
375             clib_error_return (0, "unknown input `%U'", format_unformat_error,
376                                line_input);
377           goto done;
378         }
379     }
380
381   if (num_m_args < 3)
382     {
383       error = clib_error_return (0, "mandatory argument(s) missing");
384       goto done;
385     }
386   ip4_fib_index = fib_table_find (FIB_PROTOCOL_IP4, ip4_table_id);
387   ip6_fib_index = fib_table_find (FIB_PROTOCOL_IP6, ip6_table_id);
388
389   if (~0 == ip4_fib_index)
390     {
391       error = clib_error_return (0, "No such IP4 table %d", ip4_table_id);
392       rv = VNET_API_ERROR_NO_SUCH_FIB;
393     }
394   else if (~0 == ip6_fib_index)
395     {
396       error = clib_error_return (0, "No such IP6 table %d", ip6_table_id);
397       rv = VNET_API_ERROR_NO_SUCH_FIB;
398     }
399   else
400     {
401       rv = sixrd_add_tunnel (&ip6_prefix, ip6_prefix_len, &ip4_prefix,
402                              ip4_prefix_len, &ip4_src, security_check,
403                              ip4_fib_index, ip6_fib_index,
404                              &sixrd_tunnel_index);
405
406       if (rv)
407         error = clib_error_return (0, "adding tunnel failed %d", rv);
408     }
409
410 done:
411   unformat_free (line_input);
412
413   return error;
414 }
415
416 static clib_error_t *
417 delete_sixrd_tunnel_command_fn (vlib_main_t * vm,
418                                 unformat_input_t * input,
419                                 vlib_cli_command_t * cmd)
420 {
421   unformat_input_t _line_input, *line_input = &_line_input;
422   u32 num_m_args = 0;
423   /* Optional arguments */
424   clib_error_t *error = 0;
425   u32 sw_if_index = ~0;
426
427   /* Get a line of input. */
428   if (!unformat_user (input, unformat_line_input, line_input))
429     return 0;
430   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
431     {
432       if (unformat (line_input, "sw_if_index %d", &sw_if_index))
433         num_m_args++;
434       else
435         {
436           error =
437             clib_error_return (0, "unknown input `%U'", format_unformat_error,
438                                line_input);
439           goto done;
440         }
441     }
442
443   if (num_m_args < 1)
444     {
445       error = clib_error_return (0, "mandatory argument(s) missing");
446       goto done;
447     }
448   int rv = sixrd_del_tunnel (sw_if_index);
449   printf ("RV %d\n", rv);
450
451 done:
452   unformat_free (line_input);
453
454   return error;
455 }
456
457 VLIB_CLI_COMMAND(create_sixrd_tunnel_command, static) = {
458     .path = "create 6rd tunnel",
459     .short_help = "create 6rd tunnel ip6-pfx <ip6-pfx> ip4-pfx <ip4-pfx> "
460                   "ip4-src <ip4-addr> ip4-table-id <ID> ip6-table-id <ID> "
461                   "[security-check]",
462     .function = create_sixrd_tunnel_command_fn,
463 };
464 VLIB_CLI_COMMAND(delete_sixrd_tunnel_command, static) = {
465     .path = "delete 6rd tunnel",
466     .short_help = "delete 6rd tunnel sw_if_index <sw_if_index>",
467     .function = delete_sixrd_tunnel_command_fn,
468 };
469
470 /*
471  * fd.io coding-style-patch-verification: ON
472  *
473  * Local Variables:
474  * eval: (c-set-style "gnu")
475  * End:
476  */