4ba46cb0b759b0a44136daadc1e9ec4bfcd49d81
[vpp.git] / src / plugins / nat / nat66 / nat66_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  * @file
17  * @brief NAT66 CLI
18  */
19
20 #include <nat/nat66/nat66.h>
21 #include <vnet/fib/fib_table.h>
22
23 static clib_error_t *
24 nat66_enable_command_fn (vlib_main_t *vm, unformat_input_t *input,
25                          vlib_cli_command_t *cmd)
26 {
27   nat66_main_t *nm = &nat66_main;
28   unformat_input_t _line_input, *line_input = &_line_input;
29   clib_error_t *error = 0;
30   u32 outside_vrf = 0;
31
32   if (nm->enabled)
33     return clib_error_return (0, "nat66 already enabled");
34
35   /* Get a line of input. */
36   if (!unformat_user (input, unformat_line_input, line_input))
37     {
38       if (nat66_plugin_enable (outside_vrf) != 0)
39         return clib_error_return (0, "nat66 enable failed");
40       return 0;
41     }
42
43   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
44     {
45       if (unformat (line_input, "outside-vrf %u", &outside_vrf))
46         ;
47       else
48         {
49           error = clib_error_return (0, "unknown input '%U'",
50                                      format_unformat_error, line_input);
51           goto done;
52         }
53     }
54
55   if (nat66_plugin_enable (outside_vrf) != 0)
56     error = clib_error_return (0, "nat66 enable failed");
57 done:
58   unformat_free (line_input);
59   return error;
60 }
61
62 static clib_error_t *
63 nat66_disable_command_fn (vlib_main_t *vm, unformat_input_t *input,
64                           vlib_cli_command_t *cmd)
65 {
66   nat66_main_t *nm = &nat66_main;
67   clib_error_t *error = 0;
68
69   if (!nm->enabled)
70     return clib_error_return (0, "nat66 already disabled");
71
72   if (nat66_plugin_disable () != 0)
73     error = clib_error_return (0, "nat66 disable failed");
74
75   return error;
76 }
77
78 static clib_error_t *
79 nat66_interface_feature_command_fn (vlib_main_t * vm,
80                                     unformat_input_t * input,
81                                     vlib_cli_command_t * cmd)
82 {
83   unformat_input_t _line_input, *line_input = &_line_input;
84   vnet_main_t *vnm = vnet_get_main ();
85   nat66_main_t *nm = &nat66_main;
86   clib_error_t *error = 0;
87   u32 sw_if_index;
88   u32 *inside_sw_if_indices = 0;
89   u32 *outside_sw_if_indices = 0;
90   u8 is_add = 1;
91   int i, rv;
92
93   if (!nm->enabled)
94     return clib_error_return (0, "nat66 disabled");
95
96   /* Get a line of input. */
97   if (!unformat_user (input, unformat_line_input, line_input))
98     return 0;
99
100   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
101     {
102       if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
103                     vnm, &sw_if_index))
104         vec_add1 (inside_sw_if_indices, sw_if_index);
105       else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
106                          vnm, &sw_if_index))
107         vec_add1 (outside_sw_if_indices, sw_if_index);
108       else if (unformat (line_input, "del"))
109         is_add = 0;
110       else
111         {
112           error = clib_error_return (0, "unknown input '%U'",
113                                      format_unformat_error, line_input);
114           goto done;
115         }
116     }
117
118   if (vec_len (inside_sw_if_indices))
119     {
120       for (i = 0; i < vec_len (inside_sw_if_indices); i++)
121         {
122           sw_if_index = inside_sw_if_indices[i];
123           rv = nat66_interface_add_del (sw_if_index, 1, is_add);
124           switch (rv)
125             {
126             case VNET_API_ERROR_NO_SUCH_ENTRY:
127               error =
128                 clib_error_return (0, "%U NAT66 feature not enabled.",
129                                    format_vnet_sw_interface_name, vnm,
130                                    vnet_get_sw_interface (vnm, sw_if_index));
131               goto done;
132             case VNET_API_ERROR_VALUE_EXIST:
133               error =
134                 clib_error_return (0, "%U NAT66 feature already enabled.",
135                                    format_vnet_sw_interface_name, vnm,
136                                    vnet_get_sw_interface (vnm, sw_if_index));
137               goto done;
138             case VNET_API_ERROR_INVALID_VALUE:
139             case VNET_API_ERROR_INVALID_VALUE_2:
140               error =
141                 clib_error_return (0,
142                                    "%U NAT66 feature enable/disable failed.",
143                                    format_vnet_sw_interface_name, vnm,
144                                    vnet_get_sw_interface (vnm, sw_if_index));
145               goto done;
146             default:
147               break;
148
149             }
150         }
151     }
152
153   if (vec_len (outside_sw_if_indices))
154     {
155       for (i = 0; i < vec_len (outside_sw_if_indices); i++)
156         {
157           sw_if_index = outside_sw_if_indices[i];
158           rv = nat66_interface_add_del (sw_if_index, 0, is_add);
159           switch (rv)
160             {
161             case VNET_API_ERROR_NO_SUCH_ENTRY:
162               error =
163                 clib_error_return (0, "%U NAT66 feature not enabled.",
164                                    format_vnet_sw_interface_name, vnm,
165                                    vnet_get_sw_interface (vnm, sw_if_index));
166               goto done;
167             case VNET_API_ERROR_VALUE_EXIST:
168               error =
169                 clib_error_return (0, "%U NAT66 feature already enabled.",
170                                    format_vnet_sw_interface_name, vnm,
171                                    vnet_get_sw_interface (vnm, sw_if_index));
172               goto done;
173             case VNET_API_ERROR_INVALID_VALUE:
174             case VNET_API_ERROR_INVALID_VALUE_2:
175               error =
176                 clib_error_return (0,
177                                    "%U NAT66 feature enable/disable failed.",
178                                    format_vnet_sw_interface_name, vnm,
179                                    vnet_get_sw_interface (vnm, sw_if_index));
180               goto done;
181             default:
182               break;
183
184             }
185         }
186     }
187
188 done:
189   unformat_free (line_input);
190   vec_free (inside_sw_if_indices);
191   vec_free (outside_sw_if_indices);
192
193   return error;
194 }
195
196 static int
197 nat66_cli_interface_walk (nat66_interface_t * i, void *ctx)
198 {
199   vlib_main_t *vm = ctx;
200   vnet_main_t *vnm = vnet_get_main ();
201   vlib_cli_output (vm, " %U %s", format_vnet_sw_interface_name, vnm,
202                    vnet_get_sw_interface (vnm, i->sw_if_index),
203                    nat66_interface_is_inside (i) ? "in" : "out");
204   return 0;
205 }
206
207 static clib_error_t *
208 nat66_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
209                                   vlib_cli_command_t * cmd)
210 {
211   nat66_main_t *nm = &nat66_main;
212   if (!nm->enabled)
213     return clib_error_return (0, "nat66 disabled");
214   vlib_cli_output (vm, "NAT66 interfaces:");
215   nat66_interfaces_walk (nat66_cli_interface_walk, vm);
216   return 0;
217 }
218
219 static clib_error_t *
220 nat66_add_del_static_mapping_command_fn (vlib_main_t * vm,
221                                          unformat_input_t * input,
222                                          vlib_cli_command_t * cmd)
223 {
224   nat66_main_t *nm = &nat66_main;
225   unformat_input_t _line_input, *line_input = &_line_input;
226   clib_error_t *error = 0;
227   u8 is_add = 1;
228   ip6_address_t l_addr, e_addr;
229   u32 vrf_id = 0;
230   int rv;
231
232   if (!nm->enabled)
233     return clib_error_return (0, "nat66 disabled");
234
235   /* Get a line of input. */
236   if (!unformat_user (input, unformat_line_input, line_input))
237     return 0;
238
239   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
240     {
241       if (unformat (line_input, "local %U external %U",
242                     unformat_ip6_address, &l_addr,
243                     unformat_ip6_address, &e_addr))
244         ;
245       else if (unformat (line_input, "vrf %u", &vrf_id))
246         ;
247       else if (unformat (line_input, "del"))
248         is_add = 0;
249       else
250         {
251           error = clib_error_return (0, "unknown input: '%U'",
252                                      format_unformat_error, line_input);
253           goto done;
254         }
255     }
256
257   rv = nat66_static_mapping_add_del (&l_addr, &e_addr, vrf_id, is_add);
258
259   switch (rv)
260     {
261     case VNET_API_ERROR_NO_SUCH_ENTRY:
262       error = clib_error_return (0, "NAT66 static mapping entry not exist.");
263       goto done;
264     case VNET_API_ERROR_VALUE_EXIST:
265       error = clib_error_return (0, "NAT66 static mapping entry exist.");
266       goto done;
267     default:
268       break;
269     }
270
271 done:
272   unformat_free (line_input);
273
274   return error;
275 }
276
277 static int
278 nat66_cli_static_mapping_walk (nat66_static_mapping_t * sm, void *ctx)
279 {
280   nat66_main_t *nm = &nat66_main;
281   vlib_main_t *vm = ctx;
282   fib_table_t *fib;
283   vlib_counter_t vc;
284
285   fib = fib_table_get (sm->fib_index, FIB_PROTOCOL_IP6);
286   if (!fib)
287     return -1;
288
289   vlib_get_combined_counter (&nm->session_counters, sm - nm->sm, &vc);
290
291   vlib_cli_output (vm, " local %U external %U vrf %d",
292                    format_ip6_address, &sm->l_addr,
293                    format_ip6_address, &sm->e_addr, fib->ft_table_id);
294   vlib_cli_output (vm, "  total pkts %lld, total bytes %lld", vc.packets,
295                    vc.bytes);
296
297   return 0;
298 }
299
300 static clib_error_t *
301 nat66_show_static_mappings_command_fn (vlib_main_t * vm,
302                                        unformat_input_t * input,
303                                        vlib_cli_command_t * cmd)
304 {
305   nat66_main_t *nm = &nat66_main;
306   if (!nm->enabled)
307     return clib_error_return (0, "nat66 disabled");
308   vlib_cli_output (vm, "NAT66 static mappings:");
309   nat66_static_mappings_walk (nat66_cli_static_mapping_walk, vm);
310   return 0;
311 }
312
313 /*?
314  * @cliexpar
315  * @cliexstart{nat66 enable}
316  * Enable NAT66 plugin
317  * To enable NAT66 plugin
318  *  vpp# nat66 enable
319  * To enable NAT66 plugin with outside-vrf id 10
320  *  vpp# nat66 enable outside-vrf 10
321  * @cliexend
322 ?*/
323 VLIB_CLI_COMMAND (nat66_enable_command, static) = {
324   .path = "nat66 enable",
325   .short_help = "nat66 enable [outside-vrf <vrf-id>]",
326   .function = nat66_enable_command_fn,
327 };
328
329 /*?
330  * @cliexpar
331  * @cliexstart{nat66 disable}
332  * Disable NAT66 plugin
333  * To disable NAT66 plugin
334  *  vpp# nat66 disable
335  * @cliexend
336 ?*/
337 VLIB_CLI_COMMAND (nat66_disable_command, static) = {
338   .path = "nat66 disable",
339   .short_help = "nat66 disable",
340   .function = nat66_disable_command_fn,
341 };
342
343 /*?
344  * @cliexpar
345  * @cliexstart{set interface nat66}
346  * Enable/disable NAT66 feature on the interface.
347  * To enable NAT66 feature with local (IPv6) network interface
348  * GigabitEthernet0/8/0 and external (IPv4) network interface
349  * GigabitEthernet0/a/0 use:
350  *  vpp# set interface nat66 in GigabitEthernet0/8/0 out GigabitEthernet0/a/0
351  * @cliexend
352 ?*/
353 VLIB_CLI_COMMAND (set_interface_nat66_command, static) = {
354   .path = "set interface nat66",
355   .short_help = "set interface nat66 in|out <intfc> [del]",
356   .function = nat66_interface_feature_command_fn,
357 };
358
359 /*?
360  * @cliexpar
361  * @cliexstart{show nat66 interfaces}
362  * Show interfaces with NAT66 feature.
363  * To show interfaces with NAT66 feature use:
364  *  vpp# show nat66 interfaces
365  *  NAT66 interfaces:
366  *   GigabitEthernet0/8/0 in
367  *   GigabitEthernet0/a/0 out
368  * @cliexend
369 ?*/
370 VLIB_CLI_COMMAND (show_nat66_interfaces_command, static) = {
371   .path = "show nat66 interfaces",
372   .short_help = "show nat66 interfaces",
373   .function = nat66_show_interfaces_command_fn,
374 };
375
376 /*?
377  * @cliexpar
378  * @cliexstart{nat66 add static mapping}
379  * Add/delete NAT66 static mapping entry.
380  * To add NAT66 static mapping entry use:
381  *  vpp# nat66 add static mapping local fd01:1::4 external 2001:db8:c000:223::
382  *  vpp# nat66 add static mapping local fd01:1::2 external 2001:db8:c000:221:: vrf 10
383  * @cliexend
384 ?*/
385 VLIB_CLI_COMMAND (show_nat66_add_del_static_mapping_command, static) = {
386   .path = "nat66 add static mapping",
387   .short_help = "nat66 add static mapping local <ip6-addr> external <ip6-addr>"
388                 " [vfr <table-id>] [del]",
389   .function = nat66_add_del_static_mapping_command_fn,
390 };
391
392 /*?
393  * @cliexpar
394  * @cliexstart{show nat66 static mappings}
395  * Show NAT66 static mappings.
396  * To show NAT66 static mappings use:
397  *  vpp# show nat66 static mappings
398  *  NAT66 static mappings:
399  *   local fd01:1::4 external 2001:db8:c000:223:: vrf 0
400  *   local fd01:1::2 external 2001:db8:c000:221:: vrf 10
401  * @cliexend
402 ?*/
403 VLIB_CLI_COMMAND (show_nat66_static_mappings_command, static) = {
404   .path = "show nat66 static mappings",
405   .short_help = "show nat66 static mappings",
406   .function = nat66_show_static_mappings_command_fn,
407 };
408
409 /*
410  * fd.io coding-style-patch-verification: ON
411  *
412  * Local Variables:
413  * eval: (c-set-style "gnu")
414  * End:
415  */