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