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