NAT: VPP-1537 IPFIX per worker processing
[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 (vm->thread_index,
77                                     &this_addr, vrf_id, is_add);
78
79       switch (rv)
80         {
81         case VNET_API_ERROR_NO_SUCH_ENTRY:
82           error =
83             clib_error_return (0, "NAT64 pool address %U not exist.",
84                                format_ip4_address, &this_addr);
85           goto done;
86         case VNET_API_ERROR_VALUE_EXIST:
87           error =
88             clib_error_return (0, "NAT64 pool address %U exist.",
89                                format_ip4_address, &this_addr);
90           goto done;
91         default:
92           break;
93
94         }
95       increment_v4_address (&this_addr);
96     }
97
98 done:
99   unformat_free (line_input);
100
101   return error;
102 }
103
104 static int
105 nat64_cli_pool_walk (snat_address_t * ap, void *ctx)
106 {
107   vlib_main_t *vm = ctx;
108
109   if (ap->fib_index != ~0)
110     {
111       fib_table_t *fib;
112       fib = fib_table_get (ap->fib_index, FIB_PROTOCOL_IP6);
113       if (!fib)
114         return -1;
115       vlib_cli_output (vm, " %U tenant VRF: %u", format_ip4_address,
116                        &ap->addr, fib->ft_table_id);
117     }
118   else
119     vlib_cli_output (vm, " %U", format_ip4_address, &ap->addr);
120
121 #define _(N, i, n, s) \
122   vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
123   foreach_snat_protocol
124 #undef _
125     return 0;
126 }
127
128 static clib_error_t *
129 nat64_show_pool_command_fn (vlib_main_t * vm,
130                             unformat_input_t * input,
131                             vlib_cli_command_t * cmd)
132 {
133   vlib_cli_output (vm, "NAT64 pool:");
134   nat64_pool_addr_walk (nat64_cli_pool_walk, vm);
135
136   return 0;
137 }
138
139 static clib_error_t *
140 nat64_interface_feature_command_fn (vlib_main_t * vm,
141                                     unformat_input_t *
142                                     input, vlib_cli_command_t * cmd)
143 {
144   unformat_input_t _line_input, *line_input = &_line_input;
145   vnet_main_t *vnm = vnet_get_main ();
146   clib_error_t *error = 0;
147   u32 sw_if_index;
148   u32 *inside_sw_if_indices = 0;
149   u32 *outside_sw_if_indices = 0;
150   u8 is_add = 1;
151   int i, rv;
152
153   /* Get a line of input. */
154   if (!unformat_user (input, unformat_line_input, line_input))
155     return 0;
156
157   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
158     {
159       if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
160                     vnm, &sw_if_index))
161         vec_add1 (inside_sw_if_indices, sw_if_index);
162       else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
163                          vnm, &sw_if_index))
164         vec_add1 (outside_sw_if_indices, sw_if_index);
165       else if (unformat (line_input, "del"))
166         is_add = 0;
167       else
168         {
169           error = clib_error_return (0, "unknown input '%U'",
170                                      format_unformat_error, line_input);
171           goto done;
172         }
173     }
174
175   if (vec_len (inside_sw_if_indices))
176     {
177       for (i = 0; i < vec_len (inside_sw_if_indices); i++)
178         {
179           sw_if_index = inside_sw_if_indices[i];
180           rv = nat64_add_del_interface (sw_if_index, 1, is_add);
181           switch (rv)
182             {
183             case VNET_API_ERROR_NO_SUCH_ENTRY:
184               error =
185                 clib_error_return (0, "%U NAT64 feature not enabled.",
186                                    format_vnet_sw_if_index_name, vnm,
187                                    sw_if_index);
188               goto done;
189             case VNET_API_ERROR_VALUE_EXIST:
190               error =
191                 clib_error_return (0, "%U NAT64 feature already enabled.",
192                                    format_vnet_sw_if_index_name, vnm,
193                                    vnm, sw_if_index);
194               goto done;
195             case VNET_API_ERROR_INVALID_VALUE:
196             case VNET_API_ERROR_INVALID_VALUE_2:
197               error =
198                 clib_error_return (0,
199                                    "%U NAT64 feature enable/disable failed.",
200                                    format_vnet_sw_if_index_name, vnm,
201                                    sw_if_index);
202               goto done;
203             default:
204               break;
205
206             }
207         }
208     }
209
210   if (vec_len (outside_sw_if_indices))
211     {
212       for (i = 0; i < vec_len (outside_sw_if_indices); i++)
213         {
214           sw_if_index = outside_sw_if_indices[i];
215           rv = nat64_add_del_interface (sw_if_index, 0, is_add);
216           switch (rv)
217             {
218             case VNET_API_ERROR_NO_SUCH_ENTRY:
219               error =
220                 clib_error_return (0, "%U NAT64 feature not enabled.",
221                                    format_vnet_sw_if_index_name, vnm,
222                                    sw_if_index);
223               goto done;
224             case VNET_API_ERROR_VALUE_EXIST:
225               error =
226                 clib_error_return (0, "%U NAT64 feature already enabled.",
227                                    format_vnet_sw_if_index_name, vnm,
228                                    sw_if_index);
229               goto done;
230             case VNET_API_ERROR_INVALID_VALUE:
231             case VNET_API_ERROR_INVALID_VALUE_2:
232               error =
233                 clib_error_return (0,
234                                    "%U NAT64 feature enable/disable failed.",
235                                    format_vnet_sw_if_index_name, vnm,
236                                    sw_if_index);
237               goto done;
238             default:
239               break;
240
241             }
242         }
243     }
244
245 done:
246   unformat_free (line_input);
247   vec_free (inside_sw_if_indices);
248   vec_free (outside_sw_if_indices);
249
250   return error;
251 }
252
253 static int
254 nat64_cli_interface_walk (snat_interface_t * i, void *ctx)
255 {
256   vlib_main_t *vm = ctx;
257   vnet_main_t *vnm = vnet_get_main ();
258
259   vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
260                    i->sw_if_index,
261                    (nat_interface_is_inside (i)
262                     && nat_interface_is_outside (i)) ? "in out" :
263                    nat_interface_is_inside (i) ? "in" : "out");
264   return 0;
265 }
266
267 static clib_error_t *
268 nat64_show_interfaces_command_fn (vlib_main_t * vm,
269                                   unformat_input_t *
270                                   input, vlib_cli_command_t * cmd)
271 {
272   vlib_cli_output (vm, "NAT64 interfaces:");
273   nat64_interfaces_walk (nat64_cli_interface_walk, vm);
274
275   return 0;
276 }
277
278 static clib_error_t *
279 nat64_add_del_static_bib_command_fn (vlib_main_t *
280                                      vm,
281                                      unformat_input_t
282                                      * input, vlib_cli_command_t * cmd)
283 {
284   unformat_input_t _line_input, *line_input = &_line_input;
285   clib_error_t *error = 0;
286   u8 is_add = 1;
287   ip6_address_t in_addr;
288   ip4_address_t out_addr;
289   u32 in_port = 0;
290   u32 out_port = 0;
291   u32 vrf_id = 0, protocol;
292   snat_protocol_t proto = 0;
293   u8 p = 0;
294   int rv;
295
296   if (!unformat_user (input, unformat_line_input, line_input))
297     return 0;
298
299   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
300     {
301       if (unformat (line_input, "%U %u", unformat_ip6_address,
302                     &in_addr, &in_port))
303         ;
304       else if (unformat (line_input, "%U %u", unformat_ip4_address,
305                          &out_addr, &out_port))
306         ;
307       else if (unformat (line_input, "vrf %u", &vrf_id))
308         ;
309       else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
310         ;
311       else
312         if (unformat
313             (line_input, "%U %U %u", unformat_ip6_address, &in_addr,
314              unformat_ip4_address, &out_addr, &protocol))
315         p = (u8) protocol;
316       else if (unformat (line_input, "del"))
317         is_add = 0;
318       else
319         {
320           error = clib_error_return (0, "unknown input: '%U'",
321                                      format_unformat_error, line_input);
322           goto done;
323         }
324     }
325
326   if (!p)
327     {
328       if (!in_port)
329         {
330           error =
331             clib_error_return (0, "inside port and address  must be set");
332           goto done;
333         }
334
335       if (!out_port)
336         {
337           error =
338             clib_error_return (0, "outside port and address  must be set");
339           goto done;
340         }
341
342       p = snat_proto_to_ip_proto (proto);
343     }
344
345   rv =
346     nat64_add_del_static_bib_entry (&in_addr, &out_addr, (u16) in_port,
347                                     (u16) out_port, p, vrf_id, is_add);
348
349   switch (rv)
350     {
351     case VNET_API_ERROR_NO_SUCH_ENTRY:
352       error = clib_error_return (0, "NAT64 BIB entry not exist.");
353       goto done;
354     case VNET_API_ERROR_VALUE_EXIST:
355       error = clib_error_return (0, "NAT64 BIB entry exist.");
356       goto done;
357     case VNET_API_ERROR_UNSPECIFIED:
358       error = clib_error_return (0, "Crerate NAT64 BIB entry failed.");
359       goto done;
360     case VNET_API_ERROR_INVALID_VALUE:
361       error =
362         clib_error_return (0, "Outside addres %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  */