NAT66 1:1 mapping (VPP-1108)
[vpp.git] / src / plugins / nat / 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.h>
21 #include <nat/nat.h>
22 #include <vnet/fib/fib_table.h>
23
24 static clib_error_t *
25 nat66_interface_feature_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   vnet_main_t *vnm = vnet_get_main ();
31   clib_error_t *error = 0;
32   u32 sw_if_index;
33   u32 *inside_sw_if_indices = 0;
34   u32 *outside_sw_if_indices = 0;
35   u8 is_add = 1;
36   int i, rv;
37
38   /* Get a line of input. */
39   if (!unformat_user (input, unformat_line_input, line_input))
40     return 0;
41
42   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
43     {
44       if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
45                     vnm, &sw_if_index))
46         vec_add1 (inside_sw_if_indices, sw_if_index);
47       else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
48                          vnm, &sw_if_index))
49         vec_add1 (outside_sw_if_indices, sw_if_index);
50       else if (unformat (line_input, "del"))
51         is_add = 0;
52       else
53         {
54           error = clib_error_return (0, "unknown input '%U'",
55                                      format_unformat_error, line_input);
56           goto done;
57         }
58     }
59
60   if (vec_len (inside_sw_if_indices))
61     {
62       for (i = 0; i < vec_len (inside_sw_if_indices); i++)
63         {
64           sw_if_index = inside_sw_if_indices[i];
65           rv = nat66_interface_add_del (sw_if_index, 1, is_add);
66           switch (rv)
67             {
68             case VNET_API_ERROR_NO_SUCH_ENTRY:
69               error =
70                 clib_error_return (0, "%U NAT66 feature not enabled.",
71                                    format_vnet_sw_interface_name, vnm,
72                                    vnet_get_sw_interface (vnm, sw_if_index));
73               goto done;
74             case VNET_API_ERROR_VALUE_EXIST:
75               error =
76                 clib_error_return (0, "%U NAT66 feature already enabled.",
77                                    format_vnet_sw_interface_name, vnm,
78                                    vnet_get_sw_interface (vnm, sw_if_index));
79               goto done;
80             case VNET_API_ERROR_INVALID_VALUE:
81             case VNET_API_ERROR_INVALID_VALUE_2:
82               error =
83                 clib_error_return (0,
84                                    "%U NAT66 feature enable/disable failed.",
85                                    format_vnet_sw_interface_name, vnm,
86                                    vnet_get_sw_interface (vnm, sw_if_index));
87               goto done;
88             default:
89               break;
90
91             }
92         }
93     }
94
95   if (vec_len (outside_sw_if_indices))
96     {
97       for (i = 0; i < vec_len (outside_sw_if_indices); i++)
98         {
99           sw_if_index = outside_sw_if_indices[i];
100           rv = nat66_interface_add_del (sw_if_index, 0, is_add);
101           switch (rv)
102             {
103             case VNET_API_ERROR_NO_SUCH_ENTRY:
104               error =
105                 clib_error_return (0, "%U NAT66 feature not enabled.",
106                                    format_vnet_sw_interface_name, vnm,
107                                    vnet_get_sw_interface (vnm, sw_if_index));
108               goto done;
109             case VNET_API_ERROR_VALUE_EXIST:
110               error =
111                 clib_error_return (0, "%U NAT66 feature already enabled.",
112                                    format_vnet_sw_interface_name, vnm,
113                                    vnet_get_sw_interface (vnm, sw_if_index));
114               goto done;
115             case VNET_API_ERROR_INVALID_VALUE:
116             case VNET_API_ERROR_INVALID_VALUE_2:
117               error =
118                 clib_error_return (0,
119                                    "%U NAT66 feature enable/disable failed.",
120                                    format_vnet_sw_interface_name, vnm,
121                                    vnet_get_sw_interface (vnm, sw_if_index));
122               goto done;
123             default:
124               break;
125
126             }
127         }
128     }
129
130 done:
131   unformat_free (line_input);
132   vec_free (inside_sw_if_indices);
133   vec_free (outside_sw_if_indices);
134
135   return error;
136 }
137
138 static int
139 nat66_cli_interface_walk (snat_interface_t * i, void *ctx)
140 {
141   vlib_main_t *vm = ctx;
142   vnet_main_t *vnm = vnet_get_main ();
143
144   vlib_cli_output (vm, " %U %s", format_vnet_sw_interface_name, vnm,
145                    vnet_get_sw_interface (vnm, i->sw_if_index),
146                    nat_interface_is_inside (i) ? "in" : "out");
147   return 0;
148 }
149
150 static clib_error_t *
151 nat66_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
152                                   vlib_cli_command_t * cmd)
153 {
154   vlib_cli_output (vm, "NAT66 interfaces:");
155   nat66_interfaces_walk (nat66_cli_interface_walk, vm);
156
157   return 0;
158 }
159
160 static clib_error_t *
161 nat66_add_del_static_mapping_command_fn (vlib_main_t * vm,
162                                          unformat_input_t * input,
163                                          vlib_cli_command_t * cmd)
164 {
165   unformat_input_t _line_input, *line_input = &_line_input;
166   clib_error_t *error = 0;
167   u8 is_add = 1;
168   ip6_address_t l_addr, e_addr;
169   u32 vrf_id = 0;
170   int rv;
171
172   /* Get a line of input. */
173   if (!unformat_user (input, unformat_line_input, line_input))
174     return 0;
175
176   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
177     {
178       if (unformat (line_input, "local %U external %U",
179                     unformat_ip6_address, &l_addr,
180                     unformat_ip6_address, &e_addr))
181         ;
182       else if (unformat (line_input, "vrf %u", &vrf_id))
183         ;
184       else if (unformat (line_input, "del"))
185         is_add = 0;
186       else
187         {
188           error = clib_error_return (0, "unknown input: '%U'",
189                                      format_unformat_error, line_input);
190           goto done;
191         }
192     }
193
194   rv = nat66_static_mapping_add_del (&l_addr, &e_addr, vrf_id, is_add);
195
196   switch (rv)
197     {
198     case VNET_API_ERROR_NO_SUCH_ENTRY:
199       error = clib_error_return (0, "NAT66 static mapping entry not exist.");
200       goto done;
201     case VNET_API_ERROR_VALUE_EXIST:
202       error = clib_error_return (0, "NAT66 static mapping entry exist.");
203       goto done;
204     default:
205       break;
206     }
207
208 done:
209   unformat_free (line_input);
210
211   return error;
212 }
213
214 static int
215 nat66_cli_static_mapping_walk (nat66_static_mapping_t * sm, void *ctx)
216 {
217   nat66_main_t *nm = &nat66_main;
218   vlib_main_t *vm = ctx;
219   fib_table_t *fib;
220   vlib_counter_t vc;
221
222   fib = fib_table_get (sm->fib_index, FIB_PROTOCOL_IP6);
223   if (!fib)
224     return -1;
225
226   vlib_get_combined_counter (&nm->session_counters, sm - nm->sm, &vc);
227
228   vlib_cli_output (vm, " local %U external %U vrf %d",
229                    format_ip6_address, &sm->l_addr,
230                    format_ip6_address, &sm->e_addr, fib->ft_table_id);
231   vlib_cli_output (vm, "  total pkts %lld, total bytes %lld", vc.packets,
232                    vc.bytes);
233
234   return 0;
235 }
236
237 static clib_error_t *
238 nat66_show_static_mappings_command_fn (vlib_main_t * vm,
239                                        unformat_input_t * input,
240                                        vlib_cli_command_t * cmd)
241 {
242   vlib_cli_output (vm, "NAT66 static mappings:");
243   nat66_static_mappings_walk (nat66_cli_static_mapping_walk, vm);
244   return 0;
245 }
246
247 /* *INDENT-OFF* */
248 /*?
249  * @cliexpar
250  * @cliexstart{set interface nat66}
251  * Enable/disable NAT66 feature on the interface.
252  * To enable NAT66 feature with local (IPv6) network interface
253  * GigabitEthernet0/8/0 and external (IPv4) network interface
254  * GigabitEthernet0/a/0 use:
255  *  vpp# set interface nat66 in GigabitEthernet0/8/0 out GigabitEthernet0/a/0
256  * @cliexend
257 ?*/
258 VLIB_CLI_COMMAND (set_interface_nat66_command, static) = {
259   .path = "set interface nat66",
260   .short_help = "set interface nat66 in|out <intfc> [del]",
261   .function = nat66_interface_feature_command_fn,
262 };
263
264 /*?
265  * @cliexpar
266  * @cliexstart{show nat66 interfaces}
267  * Show interfaces with NAT66 feature.
268  * To show interfaces with NAT66 feature use:
269  *  vpp# show nat66 interfaces
270  *  NAT66 interfaces:
271  *   GigabitEthernet0/8/0 in
272  *   GigabitEthernet0/a/0 out
273  * @cliexend
274 ?*/
275 VLIB_CLI_COMMAND (show_nat66_interfaces_command, static) = {
276   .path = "show nat66 interfaces",
277   .short_help = "show nat66 interfaces",
278   .function = nat66_show_interfaces_command_fn,
279 };
280
281 /*?
282  * @cliexpar
283  * @cliexstart{nat66 add static mapping}
284  * Add/delete NAT66 static mapping entry.
285  * To add NAT66 static mapping entry use:
286  *  vpp# nat66 add static mapping local fd01:1::4 external 2001:db8:c000:223::
287  *  vpp# nat66 add static mapping local fd01:1::2 external 2001:db8:c000:221:: vrf 10
288  * @cliexend
289 ?*/
290 VLIB_CLI_COMMAND (show_nat66_add_del_static_mapping_command, static) = {
291   .path = "nat66 add static mapping",
292   .short_help = "nat66 add static mapping local <ip6-addr> external <ip6-addr>"
293                 " [vfr <table-id>] [del]",
294   .function = nat66_add_del_static_mapping_command_fn,
295 };
296
297 /*?
298  * @cliexpar
299  * @cliexstart{show nat66 static mappings}
300  * Show NAT66 static mappings.
301  * To show NAT66 static mappings use:
302  *  vpp# show nat66 static mappings
303  *  NAT66 static mappings:
304  *   local fd01:1::4 external 2001:db8:c000:223:: vrf 0
305  *   local fd01:1::2 external 2001:db8:c000:221:: vrf 10
306  * @cliexend
307 ?*/
308 VLIB_CLI_COMMAND (show_nat66_static_mappings_command, static) = {
309   .path = "show nat66 static mappings",
310   .short_help = "show nat66 static mappings",
311   .function = nat66_show_static_mappings_command_fn,
312 };
313
314 /*
315  * fd.io coding-style-patch-verification: ON
316  *
317  * Local Variables:
318  * eval: (c-set-style "gnu")
319  * End:
320  */