acl-plugin: remove clib_warnings on plugin init
[vpp.git] / src / plugins / snat / nat64_cli.c
1 /*
2  * Copyright (c) 2017 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  * @file
17  * @brief NAT64 CLI
18  */
19
20 #include <snat/nat64.h>
21 #include <snat/snat.h>
22 #include <vnet/fib/fib_table.h>
23
24 static clib_error_t *
25 nat64_add_del_pool_addr_command_fn (vlib_main_t * vm,
26                                     unformat_input_t * input,
27                                     vlib_cli_command_t * cmd)
28 {
29   unformat_input_t _line_input, *line_input = &_line_input;
30   ip4_address_t start_addr, end_addr, this_addr;
31   u32 start_host_order, end_host_order;
32   int i, count, rv;
33   u32 vrf_id = ~0;
34   u8 is_add = 1;
35   clib_error_t *error = 0;
36
37   /* Get a line of input. */
38   if (!unformat_user (input, unformat_line_input, line_input))
39     return 0;
40
41   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
42     {
43       if (unformat (line_input, "%U - %U",
44                     unformat_ip4_address, &start_addr,
45                     unformat_ip4_address, &end_addr))
46         ;
47       else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
48         ;
49       else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
50         end_addr = start_addr;
51       else if (unformat (line_input, "del"))
52         is_add = 0;
53       else
54         {
55           error = clib_error_return (0, "unknown input '%U'",
56                                      format_unformat_error, line_input);
57           goto done;
58         }
59     }
60
61   start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
62   end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
63
64   if (end_host_order < start_host_order)
65     {
66       error = clib_error_return (0, "end address less than start address");
67       goto done;
68     }
69
70   count = (end_host_order - start_host_order) + 1;
71   this_addr = start_addr;
72
73   for (i = 0; i < count; i++)
74     {
75       rv = nat64_add_del_pool_addr (&this_addr, vrf_id, is_add);
76
77       switch (rv)
78         {
79         case VNET_API_ERROR_NO_SUCH_ENTRY:
80           error =
81             clib_error_return (0, "NAT64 pool address %U not exist.",
82                                format_ip4_address, &this_addr);
83           goto done;
84         case VNET_API_ERROR_VALUE_EXIST:
85           error =
86             clib_error_return (0, "NAT64 pool address %U exist.",
87                                format_ip4_address, &this_addr);
88           goto done;
89         default:
90           break;
91
92         }
93       increment_v4_address (&this_addr);
94     }
95
96 done:
97   unformat_free (line_input);
98
99   return error;
100 }
101
102 static int
103 nat64_cli_pool_walk (snat_address_t * ap, void *ctx)
104 {
105   vlib_main_t *vm = ctx;
106
107   if (ap->fib_index != ~0)
108     {
109       fib_table_t *fib;
110       fib = fib_table_get (ap->fib_index, FIB_PROTOCOL_IP4);
111       if (!fib)
112         return -1;
113       vlib_cli_output (vm, " %U tenant VRF: %u", format_ip4_address,
114                        &ap->addr, fib->ft_table_id);
115     }
116   else
117     vlib_cli_output (vm, " %U", format_ip4_address, &ap->addr);
118
119   return 0;
120 }
121
122 static clib_error_t *
123 nat64_show_pool_command_fn (vlib_main_t * vm,
124                             unformat_input_t * input,
125                             vlib_cli_command_t * cmd)
126 {
127   vlib_cli_output (vm, "NAT64 pool:");
128   nat64_pool_addr_walk (nat64_cli_pool_walk, vm);
129
130   return 0;
131 }
132
133 static clib_error_t *
134 nat64_interface_feature_command_fn (vlib_main_t * vm,
135                                     unformat_input_t *
136                                     input, vlib_cli_command_t * cmd)
137 {
138   unformat_input_t _line_input, *line_input = &_line_input;
139   vnet_main_t *vnm = vnet_get_main ();
140   clib_error_t *error = 0;
141   u32 sw_if_index;
142   u32 *inside_sw_if_indices = 0;
143   u32 *outside_sw_if_indices = 0;
144   u8 is_add = 1;
145   int i, rv;
146
147   /* Get a line of input. */
148   if (!unformat_user (input, unformat_line_input, line_input))
149     return 0;
150
151   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
152     {
153       if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
154                     vnm, &sw_if_index))
155         vec_add1 (inside_sw_if_indices, sw_if_index);
156       else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
157                          vnm, &sw_if_index))
158         vec_add1 (outside_sw_if_indices, sw_if_index);
159       else if (unformat (line_input, "del"))
160         is_add = 0;
161       else
162         {
163           error = clib_error_return (0, "unknown input '%U'",
164                                      format_unformat_error, line_input);
165           goto done;
166         }
167     }
168
169   if (vec_len (inside_sw_if_indices))
170     {
171       for (i = 0; i < vec_len (inside_sw_if_indices); i++)
172         {
173           sw_if_index = inside_sw_if_indices[i];
174           rv = nat64_add_del_interface (sw_if_index, 1, is_add);
175           switch (rv)
176             {
177             case VNET_API_ERROR_NO_SUCH_ENTRY:
178               error =
179                 clib_error_return (0, "%U NAT64 feature not enabled.",
180                                    format_vnet_sw_interface_name, vnm,
181                                    vnet_get_sw_interface (vnm, sw_if_index));
182               goto done;
183             case VNET_API_ERROR_VALUE_EXIST:
184               error =
185                 clib_error_return (0, "%U NAT64 feature already enabled.",
186                                    format_vnet_sw_interface_name, vnm,
187                                    vnet_get_sw_interface (vnm, sw_if_index));
188               goto done;
189             case VNET_API_ERROR_INVALID_VALUE:
190             case VNET_API_ERROR_INVALID_VALUE_2:
191               error =
192                 clib_error_return (0,
193                                    "%U NAT64 feature enable/disable failed.",
194                                    format_vnet_sw_interface_name, vnm,
195                                    vnet_get_sw_interface (vnm, sw_if_index));
196               goto done;
197             default:
198               break;
199
200             }
201         }
202     }
203
204   if (vec_len (outside_sw_if_indices))
205     {
206       for (i = 0; i < vec_len (outside_sw_if_indices); i++)
207         {
208           sw_if_index = outside_sw_if_indices[i];
209           rv = nat64_add_del_interface (sw_if_index, 0, is_add);
210           switch (rv)
211             {
212             case VNET_API_ERROR_NO_SUCH_ENTRY:
213               error =
214                 clib_error_return (0, "%U NAT64 feature not enabled.",
215                                    format_vnet_sw_interface_name, vnm,
216                                    vnet_get_sw_interface (vnm, sw_if_index));
217               goto done;
218             case VNET_API_ERROR_VALUE_EXIST:
219               error =
220                 clib_error_return (0, "%U NAT64 feature already enabled.",
221                                    format_vnet_sw_interface_name, vnm,
222                                    vnet_get_sw_interface (vnm, sw_if_index));
223               goto done;
224             case VNET_API_ERROR_INVALID_VALUE:
225             case VNET_API_ERROR_INVALID_VALUE_2:
226               error =
227                 clib_error_return (0,
228                                    "%U NAT64 feature enable/disable failed.",
229                                    format_vnet_sw_interface_name, vnm,
230                                    vnet_get_sw_interface (vnm, sw_if_index));
231               goto done;
232             default:
233               break;
234
235             }
236         }
237     }
238
239 done:
240   unformat_free (line_input);
241   vec_free (inside_sw_if_indices);
242   vec_free (outside_sw_if_indices);
243
244   return error;
245 }
246
247 static int
248 nat64_cli_interface_walk (snat_interface_t * i, void *ctx)
249 {
250   vlib_main_t *vm = ctx;
251   vnet_main_t *vnm = vnet_get_main ();
252
253   vlib_cli_output (vm, " %U %s", format_vnet_sw_interface_name, vnm,
254                    vnet_get_sw_interface (vnm, i->sw_if_index),
255                    i->is_inside ? "in" : "out");
256   return 0;
257 }
258
259 static clib_error_t *
260 nat64_show_interfaces_command_fn (vlib_main_t * vm,
261                                   unformat_input_t *
262                                   input, vlib_cli_command_t * cmd)
263 {
264   vlib_cli_output (vm, "NAT64 interfaces:");
265   nat64_interfaces_walk (nat64_cli_interface_walk, vm);
266
267   return 0;
268 }
269
270 static clib_error_t *
271 nat64_add_del_static_bib_command_fn (vlib_main_t *
272                                      vm,
273                                      unformat_input_t
274                                      * input, vlib_cli_command_t * cmd)
275 {
276   unformat_input_t _line_input, *line_input = &_line_input;
277   clib_error_t *error = 0;
278   u8 is_add = 1;
279   ip6_address_t in_addr;
280   ip4_address_t out_addr;
281   u16 in_port;
282   u16 out_port;
283   u32 vrf_id = 0;
284   snat_protocol_t proto = 0;
285   u8 p = 0;
286   int rv;
287
288   if (!unformat_user (input, unformat_line_input, line_input))
289     return 0;
290
291   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
292     {
293       if (unformat (line_input, "%U %u", unformat_ip6_address,
294                     &in_addr, &in_port))
295         ;
296       else if (unformat (line_input, "%U %u", unformat_ip4_address,
297                          &out_addr, &out_port))
298         ;
299       else if (unformat (line_input, "vrf %u", &vrf_id))
300         ;
301       else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
302         ;
303       else if (unformat (line_input, "del"))
304         is_add = 0;
305       else
306         {
307           error = clib_error_return (0, "unknown input: '%U'",
308                                      format_unformat_error, line_input);
309           goto done;
310         }
311     }
312
313   p = snat_proto_to_ip_proto (proto);
314
315   rv =
316     nat64_add_del_static_bib_entry (&in_addr, &out_addr, in_port, out_port, p,
317                                     vrf_id, is_add);
318
319   switch (rv)
320     {
321     case VNET_API_ERROR_NO_SUCH_ENTRY:
322       error = clib_error_return (0, "NAT64 BIB entry not exist.");
323       goto done;
324     case VNET_API_ERROR_VALUE_EXIST:
325       error = clib_error_return (0, "NAT64 BIB entry exist.");
326       goto done;
327     case VNET_API_ERROR_UNSPECIFIED:
328       error = clib_error_return (0, "Crerate NAT64 BIB entry failed.");
329       goto done;
330     case VNET_API_ERROR_INVALID_VALUE:
331       error =
332         clib_error_return (0, "Outside addres %U and port %u already in use.",
333                            format_ip4_address, &out_addr, out_port);
334       goto done;
335     default:
336       break;
337     }
338
339 done:
340   unformat_free (line_input);
341
342   return error;
343 }
344
345 static int
346 nat64_cli_bib_walk (nat64_db_bib_entry_t * bibe, void *ctx)
347 {
348   vlib_main_t *vm = ctx;
349   fib_table_t *fib;
350
351   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
352   if (!fib)
353     return -1;
354
355   vlib_cli_output (vm, " %U %u %U %u %U vrf %u %s %u sessions",
356                    format_ip6_address, &bibe->in_addr,
357                    clib_net_to_host_u16 (bibe->in_port), format_ip4_address,
358                    &bibe->out_addr, clib_net_to_host_u16 (bibe->out_port),
359                    format_snat_protocol, bibe->proto, fib->ft_table_id,
360                    bibe->is_static ? "static" : "dynamic", bibe->ses_num);
361   return 0;
362 }
363
364 static clib_error_t *
365 nat64_show_bib_command_fn (vlib_main_t * vm,
366                            unformat_input_t * input, vlib_cli_command_t * cmd)
367 {
368   nat64_main_t *nm = &nat64_main;
369   unformat_input_t _line_input, *line_input = &_line_input;
370   clib_error_t *error = 0;
371   snat_protocol_t proto = 0;
372
373   if (!unformat_user (input, unformat_line_input, line_input))
374     return 0;
375
376   if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
377     ;
378   else
379     {
380       error = clib_error_return (0, "unknown input: '%U'",
381                                  format_unformat_error, line_input);
382       goto done;
383     }
384
385   vlib_cli_output (vm, "NAT64 %U BIB:", format_snat_protocol, proto);
386   nat64_db_bib_walk (&nm->db, proto, nat64_cli_bib_walk, vm);
387
388 done:
389   unformat_free (line_input);
390
391   return error;
392 }
393
394 static clib_error_t *
395 nat64_set_timeouts_command_fn (vlib_main_t * vm, unformat_input_t * input,
396                                vlib_cli_command_t * cmd)
397 {
398   unformat_input_t _line_input, *line_input = &_line_input;
399   clib_error_t *error = 0;
400   u32 timeout, tcp_trans, tcp_est, tcp_incoming_syn;
401
402   tcp_trans = nat64_get_tcp_trans_timeout ();
403   tcp_est = nat64_get_tcp_est_timeout ();
404   tcp_incoming_syn = nat64_get_tcp_incoming_syn_timeout ();
405
406   if (!unformat_user (input, unformat_line_input, line_input))
407     return 0;
408
409   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
410     {
411       if (unformat (line_input, "udp %u", &timeout))
412         {
413           if (nat64_set_udp_timeout (timeout))
414             {
415               error = clib_error_return (0, "Invalid UDP timeout value");
416               goto done;
417             }
418         }
419       else if (unformat (line_input, "icmp %u", &timeout))
420         {
421           if (nat64_set_icmp_timeout (timeout))
422             {
423               error = clib_error_return (0, "Invalid ICMP timeout value");
424               goto done;
425             }
426         }
427       else if (unformat (line_input, "tcp-trans %u", &tcp_trans))
428         {
429           if (nat64_set_tcp_timeouts (tcp_trans, tcp_est, tcp_incoming_syn))
430             {
431               error =
432                 clib_error_return (0, "Invalid TCP transitory tiemout value");
433               goto done;
434             }
435         }
436       else if (unformat (line_input, "tcp-est %u", &tcp_est))
437         {
438           if (nat64_set_tcp_timeouts (tcp_trans, tcp_est, tcp_incoming_syn))
439             {
440               error =
441                 clib_error_return (0,
442                                    "Invalid TCP established tiemout value");
443               goto done;
444             }
445         }
446       else
447         if (unformat (line_input, "tcp-incoming-syn %u", &tcp_incoming_syn))
448         {
449           if (nat64_set_tcp_timeouts (tcp_trans, tcp_est, tcp_incoming_syn))
450             {
451               error =
452                 clib_error_return (0,
453                                    "Invalid TCP incoming SYN tiemout value");
454               goto done;
455             }
456         }
457       else if (unformat (line_input, "reset"))
458         {
459           nat64_set_udp_timeout (0);
460           nat64_set_icmp_timeout (0);
461           nat64_set_tcp_timeouts (0, 0, 0);
462         }
463       else
464         {
465           error = clib_error_return (0, "unknown input '%U'",
466                                      format_unformat_error, line_input);
467           goto done;
468         }
469     }
470
471 done:
472   unformat_free (line_input);
473
474   return error;
475 }
476
477 static clib_error_t *
478 nat64_show_timeouts_command_fn (vlib_main_t * vm, unformat_input_t * input,
479                                 vlib_cli_command_t * cmd)
480 {
481   vlib_cli_output (vm, "NAT64 session timeouts:");
482   vlib_cli_output (vm, " UDP %usec", nat64_get_udp_timeout ());
483   vlib_cli_output (vm, " ICMP %usec", nat64_get_icmp_timeout ());
484   vlib_cli_output (vm, " TCP transitory %usec",
485                    nat64_get_tcp_trans_timeout ());
486   vlib_cli_output (vm, " TCP established %usec",
487                    nat64_get_tcp_est_timeout ());
488   vlib_cli_output (vm, " TCP incoming SYN %usec",
489                    nat64_get_tcp_incoming_syn_timeout ());
490
491   return 0;
492 }
493
494 static int
495 nat64_cli_st_walk (nat64_db_st_entry_t * ste, void *ctx)
496 {
497   vlib_main_t *vm = ctx;
498   nat64_main_t *nm = &nat64_main;
499   nat64_db_bib_entry_t *bibe;
500   fib_table_t *fib;
501
502   bibe = nat64_db_bib_entry_by_index (&nm->db, ste->proto, ste->bibe_index);
503   if (!bibe)
504     return -1;
505
506   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
507   if (!fib)
508     return -1;
509
510   u32 vrf_id = fib->ft_table_id;
511
512   if (ste->proto == SNAT_PROTOCOL_ICMP)
513     vlib_cli_output (vm, " %U %U %u %U %U %u %U vrf %u",
514                      format_ip6_address, &bibe->in_addr,
515                      format_ip6_address, &ste->in_r_addr,
516                      clib_net_to_host_u16 (bibe->in_port),
517                      format_ip4_address, &bibe->out_addr,
518                      format_ip4_address, &ste->out_r_addr,
519                      clib_net_to_host_u16 (bibe->out_port),
520                      format_snat_protocol, bibe->proto, vrf_id);
521   else
522     vlib_cli_output (vm, " %U %u %U %u %U %u %U %u %U vrf %u",
523                      format_ip6_address, &bibe->in_addr,
524                      clib_net_to_host_u16 (bibe->in_port),
525                      format_ip6_address, &ste->in_r_addr,
526                      clib_net_to_host_u16 (ste->r_port),
527                      format_ip4_address, &bibe->out_addr,
528                      clib_net_to_host_u16 (bibe->out_port),
529                      format_ip4_address, &ste->out_r_addr,
530                      clib_net_to_host_u16 (ste->r_port),
531                      format_snat_protocol, bibe->proto, vrf_id);
532   return 0;
533 }
534
535 static clib_error_t *
536 nat64_show_st_command_fn (vlib_main_t * vm,
537                           unformat_input_t * input, vlib_cli_command_t * cmd)
538 {
539   nat64_main_t *nm = &nat64_main;
540   unformat_input_t _line_input, *line_input = &_line_input;
541   clib_error_t *error = 0;
542   snat_protocol_t proto = 0;
543
544   if (!unformat_user (input, unformat_line_input, line_input))
545     return 0;
546
547   if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
548     ;
549   else
550     {
551       error = clib_error_return (0, "unknown input: '%U'",
552                                  format_unformat_error, line_input);
553       goto done;
554     }
555
556   vlib_cli_output (vm, "NAT64 %U session table:", format_snat_protocol,
557                    proto);
558   nat64_db_st_walk (&nm->db, proto, nat64_cli_st_walk, vm);
559
560 done:
561   unformat_free (line_input);
562
563   return error;
564 }
565
566 /* *INDENT-OFF* */
567
568 VLIB_CLI_COMMAND (nat64_add_pool_address_command, static) = {
569   .path = "nat64 add pool address",
570   .short_help = "nat64 add pool address <ip4-range-start> [- <ip4-range-end>] "
571                 "[tenant-vrf <vrf-id>] [del]",
572   .function = nat64_add_del_pool_addr_command_fn,
573 };
574
575 VLIB_CLI_COMMAND (show_nat64_pool_command, static) = {
576   .path = "show nat64 pool",
577   .short_help = "show nat64 pool",
578   .function = nat64_show_pool_command_fn,
579 };
580
581 VLIB_CLI_COMMAND (set_interface_nat64_command, static) = {
582   .path = "set interface nat64",
583   .short_help = "set interface nat64 in|out <intfc> [del]",
584   .function = nat64_interface_feature_command_fn,
585 };
586
587 VLIB_CLI_COMMAND (show_nat64_interfaces_command, static) = {
588   .path = "show nat64 interfaces",
589   .short_help = "show nat64 interfaces",
590   .function = nat64_show_interfaces_command_fn,
591 };
592
593 VLIB_CLI_COMMAND (nat64_add_del_static_bib_command, static) = {
594   .path = "nat64 add static bib",
595   .short_help = "nat64 add static bib <ip6-addr> <port> <ip4-addr> <port> "
596                 "tcp|udp|icmp [vfr <table-id>] [del]",
597   .function = nat64_add_del_static_bib_command_fn,
598 };
599
600 VLIB_CLI_COMMAND (show_nat64_bib_command, static) = {
601   .path = "show nat64 bib",
602   .short_help = "show nat64 bib tcp|udp|icmp",
603   .function = nat64_show_bib_command_fn,
604 };
605
606 VLIB_CLI_COMMAND (set_nat64_timeouts_command, static) = {
607   .path = "set nat64 timeouts",
608   .short_help = "set nat64 timeouts udp <sec> icmp <sec> tcp-trans <sec> "
609                 "tcp-est <sec> tcp-incoming-syn <sec> | reset",
610   .function = nat64_set_timeouts_command_fn,
611 };
612
613 VLIB_CLI_COMMAND (show_nat64_timeouts_command, static) = {
614   .path = "show nat64 tiemouts",
615   .short_help = "show nat64 tiemouts",
616   .function = nat64_show_timeouts_command_fn,
617 };
618
619 VLIB_CLI_COMMAND (show_nat64_st_command, static) = {
620   .path = "show nat64 session table",
621   .short_help = "show nat64 session table tcp|udp|icmp",
622   .function = nat64_show_st_command_fn,
623 };
624
625 /* *INDENT-ON* */
626
627 /*
628  * fd.io coding-style-patch-verification: ON
629  *
630  * Local Variables:
631  * eval: (c-set-style "gnu")
632  * End:
633  */