Line data Source code
1 : /*
2 : * Copyright (c) 2020 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 <vnet/fib/fib_table.h>
17 : #include <nat/nat64/nat64.h>
18 :
19 : #define NAT64_EXPECTED_ARGUMENT "expected required argument(s)"
20 :
21 : static clib_error_t *
22 0 : nat64_plugin_enable_disable_command_fn (vlib_main_t * vm,
23 : unformat_input_t * input,
24 : vlib_cli_command_t * cmd)
25 : {
26 0 : unformat_input_t _line_input, *line_input = &_line_input;
27 0 : u8 enable = 0, is_set = 0;
28 0 : clib_error_t *error = 0;
29 0 : nat64_config_t c = { 0 };
30 :
31 0 : if (!unformat_user (input, unformat_line_input, line_input))
32 0 : return clib_error_return (0, NAT64_EXPECTED_ARGUMENT);
33 :
34 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
35 : {
36 0 : if (!is_set && unformat (line_input, "enable"))
37 : {
38 0 : unformat (line_input, "bib-buckets %u", &c.bib_buckets);
39 0 : unformat (line_input, "bib-memory %u", &c.bib_memory_size);
40 0 : unformat (line_input, "st-buckets %u", &c.st_buckets);
41 0 : unformat (line_input, "st-memory %u", &c.st_memory_size);
42 0 : enable = 1;
43 : }
44 0 : else if (!is_set && unformat (line_input, "disable"));
45 : else
46 : {
47 0 : error = clib_error_return (0, "unknown input '%U'",
48 : format_unformat_error, line_input);
49 0 : goto done;
50 : }
51 0 : is_set = 1;
52 : }
53 :
54 0 : if (enable)
55 : {
56 0 : if (nat64_plugin_enable (c))
57 0 : error = clib_error_return (0, "plugin enable failed");
58 : }
59 : else
60 : {
61 0 : if (nat64_plugin_disable ())
62 0 : error = clib_error_return (0, "plugin disable failed");
63 : }
64 0 : done:
65 0 : unformat_free (line_input);
66 0 : return error;
67 : }
68 :
69 : static clib_error_t *
70 0 : nat64_add_del_pool_addr_command_fn (vlib_main_t * vm,
71 : unformat_input_t * input,
72 : vlib_cli_command_t * cmd)
73 : {
74 0 : unformat_input_t _line_input, *line_input = &_line_input;
75 : ip4_address_t start_addr, end_addr, this_addr;
76 : u32 start_host_order, end_host_order;
77 : int i, count, rv;
78 0 : u32 vrf_id = ~0;
79 0 : u8 is_add = 1;
80 0 : clib_error_t *error = 0;
81 :
82 : /* Get a line of input. */
83 0 : if (!unformat_user (input, unformat_line_input, line_input))
84 0 : return clib_error_return (0, NAT64_EXPECTED_ARGUMENT);
85 :
86 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
87 : {
88 0 : if (unformat (line_input, "%U - %U",
89 : unformat_ip4_address, &start_addr,
90 : unformat_ip4_address, &end_addr))
91 : ;
92 0 : else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
93 : ;
94 0 : else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
95 0 : end_addr = start_addr;
96 0 : else if (unformat (line_input, "del"))
97 0 : is_add = 0;
98 : else
99 : {
100 0 : error = clib_error_return (0, "unknown input '%U'",
101 : format_unformat_error, line_input);
102 0 : goto done;
103 : }
104 : }
105 :
106 0 : start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
107 0 : end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
108 :
109 0 : if (end_host_order < start_host_order)
110 : {
111 0 : error = clib_error_return (0, "end address less than start address");
112 0 : goto done;
113 : }
114 :
115 0 : count = (end_host_order - start_host_order) + 1;
116 0 : this_addr = start_addr;
117 :
118 0 : for (i = 0; i < count; i++)
119 : {
120 0 : rv = nat64_add_del_pool_addr (0, &this_addr, vrf_id, is_add);
121 :
122 0 : switch (rv)
123 : {
124 0 : case VNET_API_ERROR_NO_SUCH_ENTRY:
125 : error =
126 0 : clib_error_return (0, "NAT64 pool address %U not exist.",
127 : format_ip4_address, &this_addr);
128 0 : goto done;
129 0 : case VNET_API_ERROR_VALUE_EXIST:
130 : error =
131 0 : clib_error_return (0, "NAT64 pool address %U exist.",
132 : format_ip4_address, &this_addr);
133 0 : goto done;
134 0 : default:
135 0 : break;
136 :
137 : }
138 0 : increment_v4_address (&this_addr);
139 : }
140 :
141 0 : done:
142 0 : unformat_free (line_input);
143 :
144 0 : return error;
145 : }
146 :
147 : static int
148 24 : nat64_cli_pool_walk (nat64_address_t * ap, void *ctx)
149 : {
150 24 : vlib_main_t *vm = ctx;
151 :
152 24 : if (ap->fib_index != ~0)
153 : {
154 : fib_table_t *fib;
155 2 : fib = fib_table_get (ap->fib_index, FIB_PROTOCOL_IP6);
156 2 : if (!fib)
157 0 : return -1;
158 2 : vlib_cli_output (vm, " %U tenant VRF: %u", format_ip4_address,
159 : &ap->addr, fib->ft_table_id);
160 : }
161 : else
162 22 : vlib_cli_output (vm, " %U", format_ip4_address, &ap->addr);
163 :
164 : #define _(N, i, n, s) \
165 : vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s);
166 24 : foreach_nat_protocol
167 : #undef _
168 24 : return 0;
169 : }
170 :
171 : static clib_error_t *
172 20 : nat64_show_pool_command_fn (vlib_main_t * vm,
173 : unformat_input_t * input,
174 : vlib_cli_command_t * cmd)
175 : {
176 20 : vlib_cli_output (vm, "NAT64 pool:");
177 20 : nat64_pool_addr_walk (nat64_cli_pool_walk, vm);
178 :
179 20 : return 0;
180 : }
181 :
182 : static clib_error_t *
183 0 : nat64_interface_feature_command_fn (vlib_main_t * vm,
184 : unformat_input_t *
185 : input, vlib_cli_command_t * cmd)
186 : {
187 0 : unformat_input_t _line_input, *line_input = &_line_input;
188 0 : vnet_main_t *vnm = vnet_get_main ();
189 0 : clib_error_t *error = 0;
190 : u32 sw_if_index;
191 0 : u32 *inside_sw_if_indices = 0;
192 0 : u32 *outside_sw_if_indices = 0;
193 0 : u8 is_add = 1;
194 : int i, rv;
195 :
196 : /* Get a line of input. */
197 0 : if (!unformat_user (input, unformat_line_input, line_input))
198 0 : return clib_error_return (0, NAT64_EXPECTED_ARGUMENT);
199 :
200 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
201 : {
202 0 : if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
203 : vnm, &sw_if_index))
204 0 : vec_add1 (inside_sw_if_indices, sw_if_index);
205 0 : else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
206 : vnm, &sw_if_index))
207 0 : vec_add1 (outside_sw_if_indices, sw_if_index);
208 0 : else if (unformat (line_input, "del"))
209 0 : is_add = 0;
210 : else
211 : {
212 0 : error = clib_error_return (0, "unknown input '%U'",
213 : format_unformat_error, line_input);
214 0 : goto done;
215 : }
216 : }
217 :
218 0 : if (vec_len (inside_sw_if_indices))
219 : {
220 0 : for (i = 0; i < vec_len (inside_sw_if_indices); i++)
221 : {
222 0 : sw_if_index = inside_sw_if_indices[i];
223 0 : rv = nat64_interface_add_del (sw_if_index, 1, is_add);
224 0 : switch (rv)
225 : {
226 0 : case VNET_API_ERROR_NO_SUCH_ENTRY:
227 : error =
228 0 : clib_error_return (0, "%U NAT64 feature not enabled.",
229 : format_vnet_sw_if_index_name, vnm,
230 : sw_if_index);
231 0 : goto done;
232 0 : case VNET_API_ERROR_VALUE_EXIST:
233 : error =
234 0 : clib_error_return (0, "%U NAT64 feature already enabled.",
235 : format_vnet_sw_if_index_name, vnm,
236 : vnm, sw_if_index);
237 0 : goto done;
238 0 : case VNET_API_ERROR_INVALID_VALUE:
239 : case VNET_API_ERROR_INVALID_VALUE_2:
240 : error =
241 0 : clib_error_return (0,
242 : "%U NAT64 feature enable/disable failed.",
243 : format_vnet_sw_if_index_name, vnm,
244 : sw_if_index);
245 0 : goto done;
246 0 : default:
247 0 : break;
248 :
249 : }
250 : }
251 : }
252 :
253 0 : if (vec_len (outside_sw_if_indices))
254 : {
255 0 : for (i = 0; i < vec_len (outside_sw_if_indices); i++)
256 : {
257 0 : sw_if_index = outside_sw_if_indices[i];
258 0 : rv = nat64_interface_add_del (sw_if_index, 0, is_add);
259 0 : switch (rv)
260 : {
261 0 : case VNET_API_ERROR_NO_SUCH_ENTRY:
262 : error =
263 0 : clib_error_return (0, "%U NAT64 feature not enabled.",
264 : format_vnet_sw_if_index_name, vnm,
265 : sw_if_index);
266 0 : goto done;
267 0 : case VNET_API_ERROR_VALUE_EXIST:
268 : error =
269 0 : clib_error_return (0, "%U NAT64 feature already enabled.",
270 : format_vnet_sw_if_index_name, vnm,
271 : sw_if_index);
272 0 : goto done;
273 0 : case VNET_API_ERROR_INVALID_VALUE:
274 : case VNET_API_ERROR_INVALID_VALUE_2:
275 : error =
276 0 : clib_error_return (0,
277 : "%U NAT64 feature enable/disable failed.",
278 : format_vnet_sw_if_index_name, vnm,
279 : sw_if_index);
280 0 : goto done;
281 0 : default:
282 0 : break;
283 :
284 : }
285 : }
286 : }
287 :
288 0 : done:
289 0 : unformat_free (line_input);
290 0 : vec_free (inside_sw_if_indices);
291 0 : vec_free (outside_sw_if_indices);
292 :
293 0 : return error;
294 : }
295 :
296 : static int
297 30 : nat64_cli_interface_walk (nat64_interface_t * i, void *ctx)
298 : {
299 30 : vlib_main_t *vm = ctx;
300 30 : vnet_main_t *vnm = vnet_get_main ();
301 :
302 30 : vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
303 : i->sw_if_index,
304 30 : (nat64_interface_is_inside (i)
305 17 : && nat64_interface_is_outside (i)) ? "in out" :
306 29 : nat64_interface_is_inside (i) ? "in" : "out");
307 30 : return 0;
308 : }
309 :
310 : static clib_error_t *
311 20 : nat64_show_interfaces_command_fn (vlib_main_t * vm,
312 : unformat_input_t *
313 : input, vlib_cli_command_t * cmd)
314 : {
315 20 : vlib_cli_output (vm, "NAT64 interfaces:");
316 20 : nat64_interfaces_walk (nat64_cli_interface_walk, vm);
317 :
318 20 : return 0;
319 : }
320 :
321 : static clib_error_t *
322 0 : nat64_add_del_static_bib_command_fn (vlib_main_t *
323 : vm,
324 : unformat_input_t
325 : * input, vlib_cli_command_t * cmd)
326 : {
327 0 : unformat_input_t _line_input, *line_input = &_line_input;
328 0 : clib_error_t *error = 0;
329 0 : u8 is_add = 1;
330 : ip6_address_t in_addr;
331 : ip4_address_t out_addr;
332 0 : u32 in_port = 0;
333 0 : u32 out_port = 0;
334 0 : u32 vrf_id = 0, protocol;
335 0 : nat_protocol_t proto = 0;
336 0 : u8 p = 0;
337 : int rv;
338 :
339 0 : if (!unformat_user (input, unformat_line_input, line_input))
340 0 : return clib_error_return (0, NAT64_EXPECTED_ARGUMENT);
341 :
342 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
343 : {
344 0 : if (unformat (line_input, "%U %u", unformat_ip6_address,
345 : &in_addr, &in_port))
346 : ;
347 0 : else if (unformat (line_input, "%U %u", unformat_ip4_address,
348 : &out_addr, &out_port))
349 : ;
350 0 : else if (unformat (line_input, "vrf %u", &vrf_id))
351 : ;
352 0 : else if (unformat (line_input, "%U", unformat_nat_protocol, &proto))
353 : ;
354 : else
355 0 : if (unformat
356 : (line_input, "%U %U %u", unformat_ip6_address, &in_addr,
357 : unformat_ip4_address, &out_addr, &protocol))
358 0 : p = (u8) protocol;
359 0 : else if (unformat (line_input, "del"))
360 0 : is_add = 0;
361 : else
362 : {
363 0 : error = clib_error_return (0, "unknown input: '%U'",
364 : format_unformat_error, line_input);
365 0 : goto done;
366 : }
367 : }
368 :
369 0 : if (!p)
370 : {
371 0 : if (!in_port)
372 : {
373 : error =
374 0 : clib_error_return (0, "inside port and address must be set");
375 0 : goto done;
376 : }
377 :
378 0 : if (!out_port)
379 : {
380 : error =
381 0 : clib_error_return (0, "outside port and address must be set");
382 0 : goto done;
383 : }
384 :
385 0 : p = nat_proto_to_ip_proto (proto);
386 : }
387 :
388 : rv =
389 0 : nat64_add_del_static_bib_entry (&in_addr, &out_addr, (u16) in_port,
390 0 : (u16) out_port, p, vrf_id, is_add);
391 :
392 0 : switch (rv)
393 : {
394 0 : case VNET_API_ERROR_NO_SUCH_ENTRY:
395 0 : error = clib_error_return (0, "NAT64 BIB entry not exist.");
396 0 : goto done;
397 0 : case VNET_API_ERROR_VALUE_EXIST:
398 0 : error = clib_error_return (0, "NAT64 BIB entry exist.");
399 0 : goto done;
400 0 : case VNET_API_ERROR_UNSPECIFIED:
401 0 : error = clib_error_return (0, "Crerate NAT64 BIB entry failed.");
402 0 : goto done;
403 0 : case VNET_API_ERROR_INVALID_VALUE:
404 : error =
405 0 : clib_error_return (0,
406 : "Outside address %U and port %u already in use.",
407 : format_ip4_address, &out_addr, out_port);
408 0 : goto done;
409 0 : case VNET_API_ERROR_INVALID_VALUE_2:
410 0 : error = clib_error_return (0, "Invalid outside port.");
411 0 : default:
412 0 : break;
413 : }
414 :
415 0 : done:
416 0 : unformat_free (line_input);
417 :
418 0 : return error;
419 : }
420 :
421 : static int
422 34 : nat64_cli_bib_walk (nat64_db_bib_entry_t * bibe, void *ctx)
423 : {
424 34 : vlib_main_t *vm = ctx;
425 : fib_table_t *fib;
426 :
427 34 : fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
428 34 : if (!fib)
429 0 : return -1;
430 :
431 34 : switch (bibe->proto)
432 : {
433 31 : case IP_PROTOCOL_ICMP:
434 : case IP_PROTOCOL_TCP:
435 : case IP_PROTOCOL_UDP:
436 62 : vlib_cli_output (vm, " %U %u %U %u protocol %U vrf %u %s %u sessions",
437 : format_ip6_address, &bibe->in_addr,
438 31 : clib_net_to_host_u16 (bibe->in_port),
439 : format_ip4_address, &bibe->out_addr,
440 31 : clib_net_to_host_u16 (bibe->out_port),
441 : format_nat_protocol,
442 31 : ip_proto_to_nat_proto (bibe->proto), fib->ft_table_id,
443 31 : bibe->is_static ? "static" : "dynamic", bibe->ses_num);
444 31 : break;
445 3 : default:
446 3 : vlib_cli_output (vm, " %U %U protocol %u vrf %u %s %u sessions",
447 : format_ip6_address, &bibe->in_addr,
448 : format_ip4_address, &bibe->out_addr,
449 3 : bibe->proto, fib->ft_table_id,
450 3 : bibe->is_static ? "static" : "dynamic", bibe->ses_num);
451 : }
452 34 : return 0;
453 : }
454 :
455 : static clib_error_t *
456 20 : nat64_show_bib_command_fn (vlib_main_t * vm,
457 : unformat_input_t * input, vlib_cli_command_t * cmd)
458 : {
459 20 : nat64_main_t *nm = &nat64_main;
460 20 : unformat_input_t _line_input, *line_input = &_line_input;
461 20 : clib_error_t *error = 0;
462 20 : u32 proto = NAT_PROTOCOL_OTHER;
463 20 : u8 p = 255;
464 : nat64_db_t *db;
465 :
466 20 : if (!unformat_user (input, unformat_line_input, line_input))
467 0 : return clib_error_return (0, NAT64_EXPECTED_ARGUMENT);
468 :
469 20 : if (unformat (line_input, "%U", unformat_nat_protocol, &proto))
470 0 : p = nat_proto_to_ip_proto (proto);
471 20 : else if (unformat (line_input, "unknown"))
472 0 : p = 0;
473 20 : else if (unformat (line_input, "all"))
474 : ;
475 : else
476 : {
477 0 : error = clib_error_return (0, "unknown input: '%U'",
478 : format_unformat_error, line_input);
479 0 : goto done;
480 : }
481 :
482 20 : if (p == 255)
483 20 : vlib_cli_output (vm, "NAT64 BIB entries:");
484 : else
485 0 : vlib_cli_output (vm, "NAT64 %U BIB entries:", format_nat_protocol, proto);
486 :
487 : /* *INDENT-OFF* */
488 40 : vec_foreach (db, nm->db)
489 20 : nat64_db_bib_walk (db, p, nat64_cli_bib_walk, vm);
490 : /* *INDENT-ON* */
491 :
492 20 : done:
493 20 : unformat_free (line_input);
494 :
495 20 : return error;
496 : }
497 :
498 : typedef struct nat64_cli_st_walk_ctx_t_
499 : {
500 : vlib_main_t *vm;
501 : nat64_db_t *db;
502 : } nat64_cli_st_walk_ctx_t;
503 :
504 : static int
505 32 : nat64_cli_st_walk (nat64_db_st_entry_t * ste, void *arg)
506 : {
507 32 : nat64_cli_st_walk_ctx_t *ctx = arg;
508 32 : vlib_main_t *vm = ctx->vm;
509 : nat64_db_bib_entry_t *bibe;
510 : fib_table_t *fib;
511 :
512 32 : bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
513 32 : if (!bibe)
514 0 : return -1;
515 :
516 32 : fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
517 32 : if (!fib)
518 0 : return -1;
519 :
520 32 : u32 vrf_id = fib->ft_table_id;
521 :
522 32 : if (ste->proto == IP_PROTOCOL_ICMP)
523 6 : vlib_cli_output (vm, " %U %U %u %U %U %u protocol %U vrf %u",
524 : format_ip6_address, &bibe->in_addr,
525 : format_ip6_address, &ste->in_r_addr,
526 6 : clib_net_to_host_u16 (bibe->in_port),
527 : format_ip4_address, &bibe->out_addr,
528 : format_ip4_address, &ste->out_r_addr,
529 6 : clib_net_to_host_u16 (bibe->out_port),
530 : format_nat_protocol,
531 6 : ip_proto_to_nat_proto (bibe->proto), vrf_id);
532 26 : else if (ste->proto == IP_PROTOCOL_TCP || ste->proto == IP_PROTOCOL_UDP)
533 23 : vlib_cli_output (vm, " %U %u %U %u %U %u %U %u protcol %U vrf %u",
534 : format_ip6_address, &bibe->in_addr,
535 23 : clib_net_to_host_u16 (bibe->in_port),
536 : format_ip6_address, &ste->in_r_addr,
537 23 : clib_net_to_host_u16 (ste->r_port),
538 : format_ip4_address, &bibe->out_addr,
539 23 : clib_net_to_host_u16 (bibe->out_port),
540 : format_ip4_address, &ste->out_r_addr,
541 23 : clib_net_to_host_u16 (ste->r_port),
542 : format_nat_protocol,
543 23 : ip_proto_to_nat_proto (bibe->proto), vrf_id);
544 : else
545 3 : vlib_cli_output (vm, " %U %U %U %U protocol %u vrf %u",
546 : format_ip6_address, &bibe->in_addr,
547 : format_ip6_address, &ste->in_r_addr,
548 : format_ip4_address, &bibe->out_addr,
549 : format_ip4_address, &ste->out_r_addr,
550 3 : bibe->proto, vrf_id);
551 :
552 32 : return 0;
553 : }
554 :
555 : static clib_error_t *
556 20 : nat64_show_st_command_fn (vlib_main_t * vm,
557 : unformat_input_t * input, vlib_cli_command_t * cmd)
558 : {
559 20 : nat64_main_t *nm = &nat64_main;
560 20 : unformat_input_t _line_input, *line_input = &_line_input;
561 20 : clib_error_t *error = 0;
562 20 : u32 proto = NAT_PROTOCOL_OTHER;
563 20 : u8 p = 255;
564 : nat64_db_t *db;
565 20 : nat64_cli_st_walk_ctx_t ctx = {
566 : .vm = vm,
567 : };
568 :
569 20 : if (!unformat_user (input, unformat_line_input, line_input))
570 0 : return clib_error_return (0, NAT64_EXPECTED_ARGUMENT);
571 :
572 20 : if (unformat (line_input, "%U", unformat_nat_protocol, &proto))
573 0 : p = nat_proto_to_ip_proto (proto);
574 20 : else if (unformat (line_input, "unknown"))
575 0 : p = 0;
576 20 : else if (unformat (line_input, "all"))
577 : ;
578 : else
579 : {
580 0 : error = clib_error_return (0, "unknown input: '%U'",
581 : format_unformat_error, line_input);
582 0 : goto done;
583 : }
584 :
585 20 : if (p == 255)
586 20 : vlib_cli_output (vm, "NAT64 sessions:");
587 : else
588 0 : vlib_cli_output (vm, "NAT64 %U sessions:", format_nat_protocol, proto);
589 : /* *INDENT-OFF* */
590 40 : vec_foreach (db, nm->db)
591 : {
592 20 : ctx.db = db;
593 20 : nat64_db_st_walk (db, p, nat64_cli_st_walk, &ctx);
594 : }
595 : /* *INDENT-ON* */
596 :
597 20 : done:
598 20 : unformat_free (line_input);
599 :
600 20 : return error;
601 : }
602 :
603 : static clib_error_t *
604 0 : nat64_add_del_prefix_command_fn (vlib_main_t * vm, unformat_input_t * input,
605 : vlib_cli_command_t * cmd)
606 : {
607 0 : nat64_main_t *nm = &nat64_main;
608 0 : vnet_main_t *vnm = vnet_get_main ();
609 0 : clib_error_t *error = 0;
610 0 : unformat_input_t _line_input, *line_input = &_line_input;
611 0 : u8 is_add = 1;
612 0 : u32 vrf_id = 0, sw_if_index = ~0;
613 : ip6_address_t prefix;
614 0 : u32 plen = 0;
615 : int rv;
616 :
617 0 : if (!unformat_user (input, unformat_line_input, line_input))
618 0 : return clib_error_return (0, NAT64_EXPECTED_ARGUMENT);
619 :
620 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
621 : {
622 0 : if (unformat
623 : (line_input, "%U/%u", unformat_ip6_address, &prefix, &plen))
624 : ;
625 0 : else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
626 : ;
627 0 : else if (unformat (line_input, "del"))
628 0 : is_add = 0;
629 : else
630 0 : if (unformat
631 : (line_input, "interface %U", unformat_vnet_sw_interface, vnm,
632 : &sw_if_index))
633 : ;
634 : else
635 : {
636 0 : error = clib_error_return (0, "unknown input: '%U'",
637 : format_unformat_error, line_input);
638 0 : goto done;
639 : }
640 : }
641 :
642 0 : if (!plen)
643 : {
644 0 : error = clib_error_return (0, "NAT64 prefix must be set.");
645 0 : goto done;
646 : }
647 :
648 0 : rv = nat64_add_del_prefix (&prefix, (u8) plen, vrf_id, is_add);
649 :
650 0 : switch (rv)
651 : {
652 0 : case VNET_API_ERROR_NO_SUCH_ENTRY:
653 0 : error = clib_error_return (0, "NAT64 prefix not exist.");
654 0 : goto done;
655 0 : case VNET_API_ERROR_INVALID_VALUE:
656 0 : error = clib_error_return (0, "Invalid prefix length.");
657 0 : goto done;
658 0 : default:
659 0 : break;
660 : }
661 :
662 : /*
663 : * Add RX interface route, whenNAT isn't running on the real input
664 : * interface
665 : */
666 0 : if (sw_if_index != ~0)
667 : {
668 : u32 fib_index;
669 0 : fib_prefix_t fibpfx = {
670 : .fp_len = plen,
671 : .fp_proto = FIB_PROTOCOL_IP6,
672 : .fp_addr = {
673 : .ip6 = prefix}
674 : };
675 :
676 0 : if (is_add)
677 : {
678 : fib_index =
679 0 : fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
680 0 : vrf_id, nm->fib_src_hi);
681 0 : fib_table_entry_update_one_path (fib_index, &fibpfx,
682 0 : nm->fib_src_hi,
683 : FIB_ENTRY_FLAG_NONE,
684 : DPO_PROTO_IP6, NULL,
685 : sw_if_index, ~0, 0,
686 : NULL, FIB_ROUTE_PATH_INTF_RX);
687 : }
688 : else
689 : {
690 0 : fib_index = fib_table_find (FIB_PROTOCOL_IP6, vrf_id);
691 0 : fib_table_entry_path_remove (fib_index, &fibpfx,
692 0 : nm->fib_src_hi,
693 : DPO_PROTO_IP6, NULL,
694 : sw_if_index, ~0, 1,
695 : FIB_ROUTE_PATH_INTF_RX);
696 0 : fib_table_unlock (fib_index, FIB_PROTOCOL_IP6, nm->fib_src_hi);
697 : }
698 : }
699 :
700 0 : done:
701 0 : unformat_free (line_input);
702 :
703 0 : return error;
704 : }
705 :
706 : static int
707 2 : nat64_cli_prefix_walk (nat64_prefix_t * p, void *ctx)
708 : {
709 2 : vlib_main_t *vm = ctx;
710 :
711 2 : vlib_cli_output (vm, " %U/%u tenant-vrf %u",
712 2 : format_ip6_address, &p->prefix, p->plen, p->vrf_id);
713 :
714 2 : return 0;
715 : }
716 :
717 : static clib_error_t *
718 20 : nat64_show_prefix_command_fn (vlib_main_t * vm,
719 : unformat_input_t * input,
720 : vlib_cli_command_t * cmd)
721 : {
722 20 : vlib_cli_output (vm, "NAT64 prefix:");
723 20 : nat64_prefix_walk (nat64_cli_prefix_walk, vm);
724 :
725 20 : return 0;
726 : }
727 :
728 : static clib_error_t *
729 0 : nat64_add_interface_address_command_fn (vlib_main_t * vm,
730 : unformat_input_t * input,
731 : vlib_cli_command_t * cmd)
732 : {
733 0 : vnet_main_t *vnm = vnet_get_main ();
734 0 : unformat_input_t _line_input, *line_input = &_line_input;
735 : u32 sw_if_index;
736 : int rv;
737 0 : int is_add = 1;
738 0 : clib_error_t *error = 0;
739 :
740 : /* Get a line of input. */
741 0 : if (!unformat_user (input, unformat_line_input, line_input))
742 0 : return clib_error_return (0, NAT64_EXPECTED_ARGUMENT);
743 :
744 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
745 : {
746 0 : if (unformat
747 : (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index));
748 0 : else if (unformat (line_input, "del"))
749 0 : is_add = 0;
750 : else
751 : {
752 0 : error = clib_error_return (0, "unknown input '%U'",
753 : format_unformat_error, line_input);
754 0 : goto done;
755 : }
756 : }
757 :
758 0 : rv = nat64_add_interface_address (sw_if_index, is_add);
759 :
760 0 : switch (rv)
761 : {
762 0 : case VNET_API_ERROR_NO_SUCH_ENTRY:
763 0 : error = clib_error_return (0, "entry not exist");
764 0 : break;
765 0 : case VNET_API_ERROR_VALUE_EXIST:
766 0 : error = clib_error_return (0, "entry exist");
767 0 : break;
768 0 : default:
769 0 : break;
770 : }
771 :
772 0 : done:
773 0 : unformat_free (line_input);
774 :
775 0 : return error;
776 : }
777 :
778 : /* *INDENT-OFF* */
779 : /*?
780 : * @cliexpar
781 : * @cliexstart{nat64 plugin}
782 : * Enable/disable NAT64 plugin.
783 : * To enable NAT64 plugin use:
784 : * vpp# nat64 plugin enable
785 : * To enable NAT64 plugin and configure buckets/memory:
786 : * vpp# nat64 plugin enable bib-buckets <n> bib-memory <s> \
787 : * st-buckets <n> st-memory <s>
788 : * To disable NAT64 plugin:
789 : * vpp# nat64 plugin disable
790 : * @cliexend
791 : ?*/
792 83095 : VLIB_CLI_COMMAND (nat64_plugin_enable_disable_command, static) =
793 : {
794 : .path = "nat64 plugin",
795 : .short_help = "nat64 plugin <enable "
796 : "[bib-buckets <count>] [bib-memory <size>] "
797 : "[st-buckets <count>] [st-memory <size>] | disable>",
798 : .function = nat64_plugin_enable_disable_command_fn,
799 : };
800 :
801 : /*?
802 : * @cliexpar
803 : * @cliexstart{nat64 add pool address}
804 : * Add/delete NAT64 pool address.
805 : * To add single NAT64 pool address use:
806 : * vpp# nat64 add pool address 10.1.1.10
807 : * To add NAT64 pool address range use:
808 : * vpp# nat64 add pool address 10.1.1.2 - 10.1.1.5
809 : * To add NAT64 pool address for specific tenant use:
810 : * vpp# nat64 add pool address 10.1.1.100 tenant-vrf 100
811 : * @cliexend
812 : ?*/
813 83095 : VLIB_CLI_COMMAND (nat64_add_pool_address_command, static) = {
814 : .path = "nat64 add pool address",
815 : .short_help = "nat64 add pool address <ip4-range-start> [- <ip4-range-end>] "
816 : "[tenant-vrf <vrf-id>] [del]",
817 : .function = nat64_add_del_pool_addr_command_fn,
818 : };
819 :
820 : /*?
821 : * @cliexpar
822 : * @cliexstart{show nat64 pool}
823 : * Show NAT64 pool.
824 : * vpp# show nat64 pool
825 : * NAT64 pool:
826 : * 10.1.1.3 tenant VRF: 0
827 : * 10.1.1.10 tenant VRF: 10
828 : * @cliexend
829 : ?*/
830 83095 : VLIB_CLI_COMMAND (show_nat64_pool_command, static) = {
831 : .path = "show nat64 pool",
832 : .short_help = "show nat64 pool",
833 : .function = nat64_show_pool_command_fn,
834 : };
835 :
836 : /*?
837 : * @cliexpar
838 : * @cliexstart{set interface nat64}
839 : * Enable/disable NAT64 feature on the interface.
840 : * To enable NAT64 feature with local (IPv6) network interface
841 : * GigabitEthernet0/8/0 and external (IPv4) network interface
842 : * GigabitEthernet0/a/0 use:
843 : * vpp# set interface nat64 in GigabitEthernet0/8/0 out GigabitEthernet0/a/0
844 : * @cliexend
845 : ?*/
846 83095 : VLIB_CLI_COMMAND (set_interface_nat64_command, static) = {
847 : .path = "set interface nat64",
848 : .short_help = "set interface nat64 in|out <intfc> [del]",
849 : .function = nat64_interface_feature_command_fn,
850 : };
851 :
852 : /*?
853 : * @cliexpar
854 : * @cliexstart{show nat64 interfaces}
855 : * Show interfaces with NAT64 feature.
856 : * To show interfaces with NAT64 feature use:
857 : * vpp# show nat64 interfaces
858 : * NAT64 interfaces:
859 : * GigabitEthernet0/8/0 in
860 : * GigabitEthernet0/a/0 out
861 : * @cliexend
862 : ?*/
863 83095 : VLIB_CLI_COMMAND (show_nat64_interfaces_command, static) = {
864 : .path = "show nat64 interfaces",
865 : .short_help = "show nat64 interfaces",
866 : .function = nat64_show_interfaces_command_fn,
867 : };
868 :
869 : /*?
870 : * @cliexpar
871 : * @cliexstart{nat64 add static bib}
872 : * Add/delete NAT64 static BIB entry.
873 : * To create NAT64 satatic BIB entry use:
874 : * vpp# nat64 add static bib 2001:db8:c000:221:: 1234 10.1.1.3 5678 tcp
875 : * vpp# nat64 add static bib 2001:db8:c000:221:: 1234 10.1.1.3 5678 udp vrf 10
876 : * @cliexend
877 : ?*/
878 83095 : VLIB_CLI_COMMAND (nat64_add_del_static_bib_command, static) = {
879 : .path = "nat64 add static bib",
880 : .short_help = "nat64 add static bib <ip6-addr> <port> <ip4-addr> <port> "
881 : "tcp|udp|icmp [vfr <table-id>] [del]",
882 : .function = nat64_add_del_static_bib_command_fn,
883 : };
884 :
885 : /*?
886 : * @cliexpar
887 : * @cliexstart{show nat64 bib}
888 : * Show NAT64 BIB entries.
889 : * To show NAT64 TCP BIB entries use:
890 : * vpp# show nat64 bib tcp
891 : * NAT64 tcp BIB:
892 : * fd01:1::2 6303 10.0.0.3 62303 tcp vrf 0 dynamic 1 sessions
893 : * 2001:db8:c000:221:: 1234 10.1.1.3 5678 tcp vrf 0 static 2 sessions
894 : * To show NAT64 UDP BIB entries use:
895 : * vpp# show nat64 bib udp
896 : * NAT64 udp BIB:
897 : * fd01:1::2 6304 10.0.0.3 10546 udp vrf 0 dynamic 10 sessions
898 : * 2001:db8:c000:221:: 1234 10.1.1.3 5678 udp vrf 10 static 0 sessions
899 : * To show NAT64 ICMP BIB entries use:
900 : * vpp# show nat64 bib icmp
901 : * NAT64 icmp BIB:
902 : * fd01:1::2 6305 10.0.0.3 63209 icmp vrf 10 dynamic 1 sessions
903 : * @cliexend
904 : ?*/
905 83095 : VLIB_CLI_COMMAND (show_nat64_bib_command, static) = {
906 : .path = "show nat64 bib",
907 : .short_help = "show nat64 bib all|tcp|udp|icmp|unknown",
908 : .function = nat64_show_bib_command_fn,
909 : };
910 :
911 : /*?
912 : * @cliexpar
913 : * @cliexstart{show nat64 session table}
914 : * Show NAT64 session table.
915 : * To show NAT64 TCP session table use:
916 : * vpp# show nat64 session table tcp
917 : * NAT64 tcp session table:
918 : * fd01:1::2 6303 64:ff9b::ac10:202 20 10.0.0.3 62303 172.16.2.2 20 tcp vrf 0
919 : * fd01:3::2 6303 64:ff9b::ac10:202 20 10.0.10.3 21300 172.16.2.2 20 tcp vrf 10
920 : * To show NAT64 UDP session table use:
921 : * #vpp show nat64 session table udp
922 : * NAT64 udp session table:
923 : * fd01:1::2 6304 64:ff9b::ac10:202 20 10.0.0.3 10546 172.16.2.2 20 udp vrf 0
924 : * fd01:3::2 6304 64:ff9b::ac10:202 20 10.0.10.3 58627 172.16.2.2 20 udp vrf 10
925 : * fd01:1::2 1235 64:ff9b::a00:3 4023 10.0.0.3 24488 10.0.0.3 4023 udp vrf 0
926 : * fd01:1::3 23 64:ff9b::a00:3 24488 10.0.0.3 4023 10.0.0.3 24488 udp vrf 0
927 : * To show NAT64 ICMP session table use:
928 : * #vpp show nat64 session table icmp
929 : * NAT64 icmp session table:
930 : * fd01:1::2 64:ff9b::ac10:202 6305 10.0.0.3 172.16.2.2 63209 icmp vrf 0
931 : * @cliexend
932 : ?*/
933 83095 : VLIB_CLI_COMMAND (show_nat64_st_command, static) = {
934 : .path = "show nat64 session table",
935 : .short_help = "show nat64 session table all|tcp|udp|icmp|unknown",
936 : .function = nat64_show_st_command_fn,
937 : };
938 :
939 : /*?
940 : * @cliexpar
941 : * @cliexstart{nat64 add prefix}
942 : * Set NAT64 prefix for generating IPv6 representations of IPv4 addresses.
943 : * To set NAT64 global prefix use:
944 : * vpp# nat64 add prefix 2001:db8::/32
945 : * To set NAT64 prefix for specific tenant use:
946 : * vpp# nat64 add prefix 2001:db8:122:300::/56 tenant-vrf 10
947 : * @cliexend
948 : ?*/
949 83095 : VLIB_CLI_COMMAND (nat64_add_del_prefix_command, static) = {
950 : .path = "nat64 add prefix",
951 : .short_help = "nat64 add prefix <ip6-prefix>/<plen> [tenant-vrf <vrf-id>] "
952 : "[del] [interface <interface]",
953 : .function = nat64_add_del_prefix_command_fn,
954 : };
955 :
956 : /*?
957 : * @cliexpar
958 : * @cliexstart{show nat64 prefix}
959 : * Show NAT64 prefix.
960 : * To show NAT64 prefix use:
961 : * vpp# show nat64 prefix
962 : * NAT64 prefix:
963 : * 2001:db8::/32 tenant-vrf 0
964 : * 2001:db8:122:300::/56 tenant-vrf 10
965 : * @cliexend
966 : ?*/
967 83095 : VLIB_CLI_COMMAND (show_nat64_prefix_command, static) = {
968 : .path = "show nat64 prefix",
969 : .short_help = "show nat64 prefix",
970 : .function = nat64_show_prefix_command_fn,
971 : };
972 :
973 : /*?
974 : * @cliexpar
975 : * @cliexstart{nat64 add interface address}
976 : * Add/delete NAT64 pool address from specific (DHCP addressed) interface.
977 : * To add NAT64 pool address from specific interface use:
978 : * vpp# nat64 add interface address GigabitEthernet0/8/0
979 : * @cliexend
980 : ?*/
981 83095 : VLIB_CLI_COMMAND (nat64_add_interface_address_command, static) = {
982 : .path = "nat64 add interface address",
983 : .short_help = "nat64 add interface address <interface> [del]",
984 : .function = nat64_add_interface_address_command_fn,
985 : };
986 : /* *INDENT-ON* */
987 :
988 : /*
989 : * fd.io coding-style-patch-verification: ON
990 : *
991 : * Local Variables:
992 : * eval: (c-set-style "gnu")
993 : * End:
994 : */
|