Typos. A bunch of typos I've been collecting.
[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 (0, &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,
362                            "Outside address %U and port %u already in use.",
363                            format_ip4_address, &out_addr, out_port);
364       goto done;
365     case VNET_API_ERROR_INVALID_VALUE_2:
366       error = clib_error_return (0, "Invalid outside port.");
367     default:
368       break;
369     }
370
371 done:
372   unformat_free (line_input);
373
374   return error;
375 }
376
377 static int
378 nat64_cli_bib_walk (nat64_db_bib_entry_t * bibe, void *ctx)
379 {
380   vlib_main_t *vm = ctx;
381   fib_table_t *fib;
382
383   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
384   if (!fib)
385     return -1;
386
387   switch (bibe->proto)
388     {
389     case IP_PROTOCOL_ICMP:
390     case IP_PROTOCOL_TCP:
391     case IP_PROTOCOL_UDP:
392       vlib_cli_output (vm, " %U %u %U %u protocol %U vrf %u %s %u sessions",
393                        format_ip6_address, &bibe->in_addr,
394                        clib_net_to_host_u16 (bibe->in_port),
395                        format_ip4_address, &bibe->out_addr,
396                        clib_net_to_host_u16 (bibe->out_port),
397                        format_snat_protocol,
398                        ip_proto_to_snat_proto (bibe->proto), fib->ft_table_id,
399                        bibe->is_static ? "static" : "dynamic", bibe->ses_num);
400       break;
401     default:
402       vlib_cli_output (vm, " %U %U protocol %u vrf %u %s %u sessions",
403                        format_ip6_address, &bibe->in_addr,
404                        format_ip4_address, &bibe->out_addr,
405                        bibe->proto, fib->ft_table_id,
406                        bibe->is_static ? "static" : "dynamic", bibe->ses_num);
407     }
408   return 0;
409 }
410
411 static clib_error_t *
412 nat64_show_bib_command_fn (vlib_main_t * vm,
413                            unformat_input_t * input, vlib_cli_command_t * cmd)
414 {
415   nat64_main_t *nm = &nat64_main;
416   unformat_input_t _line_input, *line_input = &_line_input;
417   clib_error_t *error = 0;
418   u32 proto = ~0;
419   u8 p = 255;
420   nat64_db_t *db;
421
422   if (!unformat_user (input, unformat_line_input, line_input))
423     return 0;
424
425   if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
426     p = snat_proto_to_ip_proto (proto);
427   else if (unformat (line_input, "unknown"))
428     p = 0;
429   else if (unformat (line_input, "all"))
430     ;
431   else
432     {
433       error = clib_error_return (0, "unknown input: '%U'",
434                                  format_unformat_error, line_input);
435       goto done;
436     }
437
438   if (p == 255)
439     vlib_cli_output (vm, "NAT64 BIB entries:");
440   else
441     vlib_cli_output (vm, "NAT64 %U BIB entries:", format_snat_protocol,
442                      proto);
443
444   /* *INDENT-OFF* */
445   vec_foreach (db, nm->db)
446     nat64_db_bib_walk (db, p, nat64_cli_bib_walk, vm);
447   /* *INDENT-ON* */
448
449 done:
450   unformat_free (line_input);
451
452   return error;
453 }
454
455 typedef struct nat64_cli_st_walk_ctx_t_
456 {
457   vlib_main_t *vm;
458   nat64_db_t *db;
459 } nat64_cli_st_walk_ctx_t;
460
461 static int
462 nat64_cli_st_walk (nat64_db_st_entry_t * ste, void *arg)
463 {
464   nat64_cli_st_walk_ctx_t *ctx = arg;
465   vlib_main_t *vm = ctx->vm;
466   nat64_db_bib_entry_t *bibe;
467   fib_table_t *fib;
468
469   bibe = nat64_db_bib_entry_by_index (ctx->db, ste->proto, ste->bibe_index);
470   if (!bibe)
471     return -1;
472
473   fib = fib_table_get (bibe->fib_index, FIB_PROTOCOL_IP6);
474   if (!fib)
475     return -1;
476
477   u32 vrf_id = fib->ft_table_id;
478
479   if (ste->proto == IP_PROTOCOL_ICMP)
480     vlib_cli_output (vm, " %U %U %u %U %U %u protocol %U vrf %u",
481                      format_ip6_address, &bibe->in_addr,
482                      format_ip6_address, &ste->in_r_addr,
483                      clib_net_to_host_u16 (bibe->in_port),
484                      format_ip4_address, &bibe->out_addr,
485                      format_ip4_address, &ste->out_r_addr,
486                      clib_net_to_host_u16 (bibe->out_port),
487                      format_snat_protocol,
488                      ip_proto_to_snat_proto (bibe->proto), vrf_id);
489   else if (ste->proto == IP_PROTOCOL_TCP || ste->proto == IP_PROTOCOL_UDP)
490     vlib_cli_output (vm, " %U %u %U %u %U %u %U %u protcol %U vrf %u",
491                      format_ip6_address, &bibe->in_addr,
492                      clib_net_to_host_u16 (bibe->in_port),
493                      format_ip6_address, &ste->in_r_addr,
494                      clib_net_to_host_u16 (ste->r_port),
495                      format_ip4_address, &bibe->out_addr,
496                      clib_net_to_host_u16 (bibe->out_port),
497                      format_ip4_address, &ste->out_r_addr,
498                      clib_net_to_host_u16 (ste->r_port),
499                      format_snat_protocol,
500                      ip_proto_to_snat_proto (bibe->proto), vrf_id);
501   else
502     vlib_cli_output (vm, " %U %U %U %U protocol %u vrf %u",
503                      format_ip6_address, &bibe->in_addr,
504                      format_ip6_address, &ste->in_r_addr,
505                      format_ip4_address, &bibe->out_addr,
506                      format_ip4_address, &ste->out_r_addr,
507                      bibe->proto, vrf_id);
508
509   return 0;
510 }
511
512 static clib_error_t *
513 nat64_show_st_command_fn (vlib_main_t * vm,
514                           unformat_input_t * input, vlib_cli_command_t * cmd)
515 {
516   nat64_main_t *nm = &nat64_main;
517   unformat_input_t _line_input, *line_input = &_line_input;
518   clib_error_t *error = 0;
519   u32 proto = ~0;
520   u8 p = 255;
521   nat64_db_t *db;
522   nat64_cli_st_walk_ctx_t ctx = {
523     .vm = vm,
524   };
525
526   if (!unformat_user (input, unformat_line_input, line_input))
527     return 0;
528
529   if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
530     p = snat_proto_to_ip_proto (proto);
531   else if (unformat (line_input, "unknown"))
532     p = 0;
533   else if (unformat (line_input, "all"))
534     ;
535   else
536     {
537       error = clib_error_return (0, "unknown input: '%U'",
538                                  format_unformat_error, line_input);
539       goto done;
540     }
541
542   if (p == 255)
543     vlib_cli_output (vm, "NAT64 sessions:");
544   else
545     vlib_cli_output (vm, "NAT64 %U sessions:", format_snat_protocol, proto);
546   /* *INDENT-OFF* */
547   vec_foreach (db, nm->db)
548     {
549       ctx.db = db;
550       nat64_db_st_walk (db, p, nat64_cli_st_walk, &ctx);
551     }
552   /* *INDENT-ON* */
553
554 done:
555   unformat_free (line_input);
556
557   return error;
558 }
559
560 static clib_error_t *
561 nat64_add_del_prefix_command_fn (vlib_main_t * vm, unformat_input_t * input,
562                                  vlib_cli_command_t * cmd)
563 {
564   vnet_main_t *vnm = vnet_get_main ();
565   clib_error_t *error = 0;
566   unformat_input_t _line_input, *line_input = &_line_input;
567   u8 is_add = 1;
568   u32 vrf_id = 0, sw_if_index = ~0;
569   ip6_address_t prefix;
570   u32 plen = 0;
571   int rv;
572
573   if (!unformat_user (input, unformat_line_input, line_input))
574     return 0;
575
576   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
577     {
578       if (unformat
579           (line_input, "%U/%u", unformat_ip6_address, &prefix, &plen))
580         ;
581       else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
582         ;
583       else if (unformat (line_input, "del"))
584         is_add = 0;
585       else
586         if (unformat
587             (line_input, "interface %U", unformat_vnet_sw_interface, vnm,
588              &sw_if_index))
589         ;
590       else
591         {
592           error = clib_error_return (0, "unknown input: '%U'",
593                                      format_unformat_error, line_input);
594           goto done;
595         }
596     }
597
598   if (!plen)
599     {
600       error = clib_error_return (0, "NAT64 prefix must be set.");
601       goto done;
602     }
603
604   rv = nat64_add_del_prefix (&prefix, (u8) plen, vrf_id, is_add);
605
606   switch (rv)
607     {
608     case VNET_API_ERROR_NO_SUCH_ENTRY:
609       error = clib_error_return (0, "NAT64 prefix not exist.");
610       goto done;
611     case VNET_API_ERROR_INVALID_VALUE:
612       error = clib_error_return (0, "Invalid prefix length.");
613       goto done;
614     default:
615       break;
616     }
617
618   /*
619    * Add RX interface route, whenNAT isn't running on the real input
620    * interface
621    */
622   if (sw_if_index != ~0)
623     {
624       u32 fib_index;
625       fib_prefix_t fibpfx = {
626         .fp_len = plen,
627         .fp_proto = FIB_PROTOCOL_IP6,
628         .fp_addr = {
629                     .ip6 = prefix}
630       };
631
632       if (is_add)
633         {
634           fib_index =
635             fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
636                                                vrf_id, FIB_SOURCE_PLUGIN_HI);
637           fib_table_entry_update_one_path (fib_index, &fibpfx,
638                                            FIB_SOURCE_PLUGIN_HI,
639                                            FIB_ENTRY_FLAG_NONE,
640                                            DPO_PROTO_IP6, NULL,
641                                            sw_if_index, ~0, 0,
642                                            NULL, FIB_ROUTE_PATH_INTF_RX);
643         }
644       else
645         {
646           fib_index = fib_table_find (FIB_PROTOCOL_IP6, vrf_id);
647           fib_table_entry_path_remove (fib_index, &fibpfx,
648                                        FIB_SOURCE_PLUGIN_HI,
649                                        DPO_PROTO_IP6, NULL,
650                                        sw_if_index, ~0, 1,
651                                        FIB_ROUTE_PATH_INTF_RX);
652           fib_table_unlock (fib_index, FIB_PROTOCOL_IP6,
653                             FIB_SOURCE_PLUGIN_HI);
654         }
655     }
656
657 done:
658   unformat_free (line_input);
659
660   return error;
661 }
662
663 static int
664 nat64_cli_prefix_walk (nat64_prefix_t * p, void *ctx)
665 {
666   vlib_main_t *vm = ctx;
667
668   vlib_cli_output (vm, " %U/%u tenant-vrf %u",
669                    format_ip6_address, &p->prefix, p->plen, p->vrf_id);
670
671   return 0;
672 }
673
674 static clib_error_t *
675 nat64_show_prefix_command_fn (vlib_main_t * vm,
676                               unformat_input_t * input,
677                               vlib_cli_command_t * cmd)
678 {
679   vlib_cli_output (vm, "NAT64 prefix:");
680   nat64_prefix_walk (nat64_cli_prefix_walk, vm);
681
682   return 0;
683 }
684
685 static clib_error_t *
686 nat64_add_interface_address_command_fn (vlib_main_t * vm,
687                                         unformat_input_t * input,
688                                         vlib_cli_command_t * cmd)
689 {
690   vnet_main_t *vnm = vnet_get_main ();
691   unformat_input_t _line_input, *line_input = &_line_input;
692   u32 sw_if_index;
693   int rv;
694   int is_add = 1;
695   clib_error_t *error = 0;
696
697   /* Get a line of input. */
698   if (!unformat_user (input, unformat_line_input, line_input))
699     return 0;
700
701   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
702     {
703       if (unformat
704           (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index));
705       else if (unformat (line_input, "del"))
706         is_add = 0;
707       else
708         {
709           error = clib_error_return (0, "unknown input '%U'",
710                                      format_unformat_error, line_input);
711           goto done;
712         }
713     }
714
715   rv = nat64_add_interface_address (sw_if_index, is_add);
716
717   switch (rv)
718     {
719     case VNET_API_ERROR_NO_SUCH_ENTRY:
720       error = clib_error_return (0, "entry not exist");
721       break;
722     case VNET_API_ERROR_VALUE_EXIST:
723       error = clib_error_return (0, "entry exist");
724       break;
725     default:
726       break;
727     }
728
729 done:
730   unformat_free (line_input);
731
732   return error;
733 }
734
735 /* *INDENT-OFF* */
736
737 /*?
738  * @cliexpar
739  * @cliexstart{nat64 add pool address}
740  * Add/delete NAT64 pool address.
741  * To add single NAT64 pool address use:
742  *  vpp# nat64 add pool address 10.1.1.10
743  * To add NAT64 pool address range use:
744  *  vpp# nat64 add pool address 10.1.1.2 - 10.1.1.5
745  * To add NAT64 pool address for specific tenant use:
746  *  vpp# nat64 add pool address 10.1.1.100 tenant-vrf 100
747  * @cliexend
748 ?*/
749 VLIB_CLI_COMMAND (nat64_add_pool_address_command, static) = {
750   .path = "nat64 add pool address",
751   .short_help = "nat64 add pool address <ip4-range-start> [- <ip4-range-end>] "
752                 "[tenant-vrf <vrf-id>] [del]",
753   .function = nat64_add_del_pool_addr_command_fn,
754 };
755
756 /*?
757  * @cliexpar
758  * @cliexstart{show nat64 pool}
759  * Show NAT64 pool.
760  *  vpp# show nat64 pool
761  *  NAT64 pool:
762  *   10.1.1.3 tenant VRF: 0
763  *   10.1.1.10 tenant VRF: 10
764  * @cliexend
765 ?*/
766 VLIB_CLI_COMMAND (show_nat64_pool_command, static) = {
767   .path = "show nat64 pool",
768   .short_help = "show nat64 pool",
769   .function = nat64_show_pool_command_fn,
770 };
771
772 /*?
773  * @cliexpar
774  * @cliexstart{set interface nat64}
775  * Enable/disable NAT64 feature on the interface.
776  * To enable NAT64 feature with local (IPv6) network interface
777  * GigabitEthernet0/8/0 and external (IPv4) network interface
778  * GigabitEthernet0/a/0 use:
779  *  vpp# set interface nat64 in GigabitEthernet0/8/0 out GigabitEthernet0/a/0
780  * @cliexend
781 ?*/
782 VLIB_CLI_COMMAND (set_interface_nat64_command, static) = {
783   .path = "set interface nat64",
784   .short_help = "set interface nat64 in|out <intfc> [del]",
785   .function = nat64_interface_feature_command_fn,
786 };
787
788 /*?
789  * @cliexpar
790  * @cliexstart{show nat64 interfaces}
791  * Show interfaces with NAT64 feature.
792  * To show interfaces with NAT64 feature use:
793  *  vpp# show nat64 interfaces
794  *  NAT64 interfaces:
795  *   GigabitEthernet0/8/0 in
796  *   GigabitEthernet0/a/0 out
797  * @cliexend
798 ?*/
799 VLIB_CLI_COMMAND (show_nat64_interfaces_command, static) = {
800   .path = "show nat64 interfaces",
801   .short_help = "show nat64 interfaces",
802   .function = nat64_show_interfaces_command_fn,
803 };
804
805 /*?
806  * @cliexpar
807  * @cliexstart{nat64 add static bib}
808  * Add/delete NAT64 static BIB entry.
809  * To create NAT64 satatic BIB entry use:
810  *  vpp# nat64 add static bib 2001:db8:c000:221:: 1234 10.1.1.3 5678 tcp
811  *  vpp# nat64 add static bib 2001:db8:c000:221:: 1234 10.1.1.3 5678 udp vrf 10
812  * @cliexend
813 ?*/
814 VLIB_CLI_COMMAND (nat64_add_del_static_bib_command, static) = {
815   .path = "nat64 add static bib",
816   .short_help = "nat64 add static bib <ip6-addr> <port> <ip4-addr> <port> "
817                 "tcp|udp|icmp [vfr <table-id>] [del]",
818   .function = nat64_add_del_static_bib_command_fn,
819 };
820
821 /*?
822  * @cliexpar
823  * @cliexstart{show nat64 bib}
824  * Show NAT64 BIB entries.
825  * To show NAT64 TCP BIB entries use:
826  *  vpp# show nat64 bib tcp
827  *  NAT64 tcp BIB:
828  *   fd01:1::2 6303 10.0.0.3 62303 tcp vrf 0 dynamic 1 sessions
829  *   2001:db8:c000:221:: 1234 10.1.1.3 5678 tcp vrf 0 static 2 sessions
830  * To show NAT64 UDP BIB entries use:
831  *  vpp# show nat64 bib udp
832  *  NAT64 udp BIB:
833  *   fd01:1::2 6304 10.0.0.3 10546 udp vrf 0 dynamic 10 sessions
834  *   2001:db8:c000:221:: 1234 10.1.1.3 5678 udp vrf 10 static 0 sessions
835  * To show NAT64 ICMP BIB entries use:
836  *  vpp# show nat64 bib icmp
837  *  NAT64 icmp BIB:
838  *   fd01:1::2 6305 10.0.0.3 63209 icmp vrf 10 dynamic 1 sessions
839  * @cliexend
840 ?*/
841 VLIB_CLI_COMMAND (show_nat64_bib_command, static) = {
842   .path = "show nat64 bib",
843   .short_help = "show nat64 bib all|tcp|udp|icmp|unknown",
844   .function = nat64_show_bib_command_fn,
845 };
846
847 /*?
848  * @cliexpar
849  * @cliexstart{show nat64 session table}
850  * Show NAT64 session table.
851  * To show NAT64 TCP session table use:
852  *  vpp# show nat64 session table tcp
853  *  NAT64 tcp session table:
854  *   fd01:1::2 6303 64:ff9b::ac10:202 20 10.0.0.3 62303 172.16.2.2 20 tcp vrf 0
855  *   fd01:3::2 6303 64:ff9b::ac10:202 20 10.0.10.3 21300 172.16.2.2 20 tcp vrf 10
856  * To show NAT64 UDP session table use:
857  * #vpp show nat64 session table udp
858  * NAT64 udp session table:
859  *  fd01:1::2 6304 64:ff9b::ac10:202 20 10.0.0.3 10546 172.16.2.2 20 udp vrf 0
860  *  fd01:3::2 6304 64:ff9b::ac10:202 20 10.0.10.3 58627 172.16.2.2 20 udp vrf 10
861  *  fd01:1::2 1235 64:ff9b::a00:3 4023 10.0.0.3 24488 10.0.0.3 4023 udp vrf 0
862  *  fd01:1::3 23 64:ff9b::a00:3 24488 10.0.0.3 4023 10.0.0.3 24488 udp vrf 0
863  * To show NAT64 ICMP session table use:
864  * #vpp show nat64 session table icmp
865  * NAT64 icmp session table:
866  *  fd01:1::2 64:ff9b::ac10:202 6305 10.0.0.3 172.16.2.2 63209 icmp vrf 0
867  * @cliexend
868 ?*/
869 VLIB_CLI_COMMAND (show_nat64_st_command, static) = {
870   .path = "show nat64 session table",
871   .short_help = "show nat64 session table all|tcp|udp|icmp|unknown",
872   .function = nat64_show_st_command_fn,
873 };
874
875 /*?
876  * @cliexpar
877  * @cliexstart{nat64 add prefix}
878  * Set NAT64 prefix for generating IPv6 representations of IPv4 addresses.
879  * To set NAT64 global prefix use:
880  *  vpp# nat64 add prefix 2001:db8::/32
881  * To set NAT64 prefix for specific tenant use:
882  *  vpp# nat64 add prefix 2001:db8:122:300::/56 tenant-vrf 10
883  * @cliexend
884 ?*/
885 VLIB_CLI_COMMAND (nat64_add_del_prefix_command, static) = {
886   .path = "nat64 add prefix",
887   .short_help = "nat64 add prefix <ip6-prefix>/<plen> [tenant-vrf <vrf-id>] "
888                 "[del] [interface <interface]",
889   .function = nat64_add_del_prefix_command_fn,
890 };
891
892 /*?
893  * @cliexpar
894  * @cliexstart{show nat64 prefix}
895  * Show NAT64 prefix.
896  * To show NAT64 prefix use:
897  *  vpp# show nat64 prefix
898  *  NAT64 prefix:
899  *   2001:db8::/32 tenant-vrf 0
900  *   2001:db8:122:300::/56 tenant-vrf 10
901  * @cliexend
902 ?*/
903 VLIB_CLI_COMMAND (show_nat64_prefix_command, static) = {
904   .path = "show nat64 prefix",
905   .short_help = "show nat64 prefix",
906   .function = nat64_show_prefix_command_fn,
907 };
908
909 /*?
910  * @cliexpar
911  * @cliexstart{nat64 add interface address}
912  * Add/delete NAT64 pool address from specific (DHCP addressed) interface.
913  * To add NAT64 pool address from specific interface use:
914  *  vpp# nat64 add interface address GigabitEthernet0/8/0
915  * @cliexend
916 ?*/
917 VLIB_CLI_COMMAND (nat64_add_interface_address_command, static) = {
918     .path = "nat64 add interface address",
919     .short_help = "nat64 add interface address <interface> [del]",
920     .function = nat64_add_interface_address_command_fn,
921 };
922 /* *INDENT-ON* */
923
924 /*
925  * fd.io coding-style-patch-verification: ON
926  *
927  * Local Variables:
928  * eval: (c-set-style "gnu")
929  * End:
930  */