NAT: replace format_vnet_sw_interface_name with format_vnet_sw_if_index_name (VPP...
[vpp.git] / src / plugins / nat / nat44_cli.c
1 /*
2  * Copyright (c) 2018 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /**
16  * @file
17  * @brief NAT44 CLI
18  */
19
20 #include <nat/nat.h>
21 #include <nat/nat_ipfix_logging.h>
22 #include <nat/nat_det.h>
23 #include <vnet/fib/fib_table.h>
24
25 static clib_error_t *
26 set_workers_command_fn (vlib_main_t * vm,
27                         unformat_input_t * input, vlib_cli_command_t * cmd)
28 {
29   unformat_input_t _line_input, *line_input = &_line_input;
30   uword *bitmap = 0;
31   int rv = 0;
32   clib_error_t *error = 0;
33
34   /* Get a line of input. */
35   if (!unformat_user (input, unformat_line_input, line_input))
36     return 0;
37
38   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
39     {
40       if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap))
41         ;
42       else
43         {
44           error = clib_error_return (0, "unknown input '%U'",
45                                      format_unformat_error, line_input);
46           goto done;
47         }
48     }
49
50   if (bitmap == 0)
51     {
52       error = clib_error_return (0, "List of workers must be specified.");
53       goto done;
54     }
55
56   rv = snat_set_workers (bitmap);
57
58   clib_bitmap_free (bitmap);
59
60   switch (rv)
61     {
62     case VNET_API_ERROR_INVALID_WORKER:
63       error = clib_error_return (0, "Invalid worker(s).");
64       goto done;
65     case VNET_API_ERROR_FEATURE_DISABLED:
66       error = clib_error_return (0,
67                                  "Supported only if 2 or more workes available.");
68       goto done;
69     default:
70       break;
71     }
72
73 done:
74   unformat_free (line_input);
75
76   return error;
77 }
78
79 static clib_error_t *
80 nat_show_workers_commnad_fn (vlib_main_t * vm, unformat_input_t * input,
81                              vlib_cli_command_t * cmd)
82 {
83   snat_main_t *sm = &snat_main;
84   u32 *worker;
85
86   if (sm->num_workers > 1)
87     {
88       vlib_cli_output (vm, "%d workers", vec_len (sm->workers));
89       /* *INDENT-OFF* */
90       vec_foreach (worker, sm->workers)
91         {
92           vlib_worker_thread_t *w =
93             vlib_worker_threads + *worker + sm->first_worker_index;
94           vlib_cli_output (vm, "  %s", w->name);
95         }
96       /* *INDENT-ON* */
97     }
98
99   return 0;
100 }
101
102 static clib_error_t *
103 snat_ipfix_logging_enable_disable_command_fn (vlib_main_t * vm,
104                                               unformat_input_t * input,
105                                               vlib_cli_command_t * cmd)
106 {
107   unformat_input_t _line_input, *line_input = &_line_input;
108   u32 domain_id = 0;
109   u32 src_port = 0;
110   u8 enable = 1;
111   int rv = 0;
112   clib_error_t *error = 0;
113
114   /* Get a line of input. */
115   if (!unformat_user (input, unformat_line_input, line_input))
116     return 0;
117
118   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
119     {
120       if (unformat (line_input, "domain %d", &domain_id))
121         ;
122       else if (unformat (line_input, "src-port %d", &src_port))
123         ;
124       else if (unformat (line_input, "disable"))
125         enable = 0;
126       else
127         {
128           error = clib_error_return (0, "unknown input '%U'",
129                                      format_unformat_error, line_input);
130           goto done;
131         }
132     }
133
134   rv = snat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port);
135
136   if (rv)
137     {
138       error = clib_error_return (0, "ipfix logging enable failed");
139       goto done;
140     }
141
142 done:
143   unformat_free (line_input);
144
145   return error;
146 }
147
148 static clib_error_t *
149 nat44_set_alloc_addr_and_port_alg_command_fn (vlib_main_t * vm,
150                                               unformat_input_t * input,
151                                               vlib_cli_command_t * cmd)
152 {
153   unformat_input_t _line_input, *line_input = &_line_input;
154   clib_error_t *error = 0;
155   u32 psid, psid_offset, psid_length;
156
157   /* Get a line of input. */
158   if (!unformat_user (input, unformat_line_input, line_input))
159     return 0;
160
161   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
162     {
163       if (unformat (line_input, "default"))
164         nat_set_alloc_addr_and_port_default ();
165       else
166         if (unformat
167             (line_input, "map-e psid %d psid-offset %d psid-len %d", &psid,
168              &psid_offset, &psid_length))
169         nat_set_alloc_addr_and_port_mape ((u16) psid, (u16) psid_offset,
170                                           (u16) psid_length);
171       else
172         {
173           error = clib_error_return (0, "unknown input '%U'",
174                                      format_unformat_error, line_input);
175           goto done;
176         }
177     }
178
179 done:
180   unformat_free (line_input);
181
182   return error;
183 };
184
185 static clib_error_t *
186 add_address_command_fn (vlib_main_t * vm,
187                         unformat_input_t * input, vlib_cli_command_t * cmd)
188 {
189   unformat_input_t _line_input, *line_input = &_line_input;
190   snat_main_t *sm = &snat_main;
191   ip4_address_t start_addr, end_addr, this_addr;
192   u32 start_host_order, end_host_order;
193   u32 vrf_id = ~0;
194   int i, count;
195   int is_add = 1;
196   int rv = 0;
197   clib_error_t *error = 0;
198   u8 twice_nat = 0;
199
200   /* Get a line of input. */
201   if (!unformat_user (input, unformat_line_input, line_input))
202     return 0;
203
204   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
205     {
206       if (unformat (line_input, "%U - %U",
207                     unformat_ip4_address, &start_addr,
208                     unformat_ip4_address, &end_addr))
209         ;
210       else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
211         ;
212       else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
213         end_addr = start_addr;
214       else if (unformat (line_input, "twice-nat"))
215         twice_nat = 1;
216       else if (unformat (line_input, "del"))
217         is_add = 0;
218       else
219         {
220           error = clib_error_return (0, "unknown input '%U'",
221                                      format_unformat_error, line_input);
222           goto done;
223         }
224     }
225
226   if (sm->static_mapping_only)
227     {
228       error = clib_error_return (0, "static mapping only mode");
229       goto done;
230     }
231
232   start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
233   end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
234
235   if (end_host_order < start_host_order)
236     {
237       error = clib_error_return (0, "end address less than start address");
238       goto done;
239     }
240
241   count = (end_host_order - start_host_order) + 1;
242
243   if (count > 1024)
244     clib_warning ("%U - %U, %d addresses...",
245                   format_ip4_address, &start_addr,
246                   format_ip4_address, &end_addr, count);
247
248   this_addr = start_addr;
249
250   for (i = 0; i < count; i++)
251     {
252       if (is_add)
253         snat_add_address (sm, &this_addr, vrf_id, twice_nat);
254       else
255         rv = snat_del_address (sm, this_addr, 0, twice_nat);
256
257       switch (rv)
258         {
259         case VNET_API_ERROR_NO_SUCH_ENTRY:
260           error = clib_error_return (0, "S-NAT address not exist.");
261           goto done;
262         case VNET_API_ERROR_UNSPECIFIED:
263           error =
264             clib_error_return (0, "S-NAT address used in static mapping.");
265           goto done;
266         default:
267           break;
268         }
269
270       if (sm->out2in_dpo)
271         nat44_add_del_address_dpo (this_addr, is_add);
272
273       increment_v4_address (&this_addr);
274     }
275
276 done:
277   unformat_free (line_input);
278
279   return error;
280 }
281
282 static clib_error_t *
283 nat44_show_addresses_command_fn (vlib_main_t * vm, unformat_input_t * input,
284                                  vlib_cli_command_t * cmd)
285 {
286   snat_main_t *sm = &snat_main;
287   snat_address_t *ap;
288
289   vlib_cli_output (vm, "NAT44 pool addresses:");
290   /* *INDENT-OFF* */
291   vec_foreach (ap, sm->addresses)
292     {
293       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
294       if (ap->fib_index != ~0)
295           vlib_cli_output (vm, "  tenant VRF: %u",
296             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
297       else
298         vlib_cli_output (vm, "  tenant VRF independent");
299     #define _(N, i, n, s) \
300       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
301       foreach_snat_protocol
302     #undef _
303     }
304   vlib_cli_output (vm, "NAT44 twice-nat pool addresses:");
305   vec_foreach (ap, sm->twice_nat_addresses)
306     {
307       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
308       if (ap->fib_index != ~0)
309           vlib_cli_output (vm, "  tenant VRF: %u",
310             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
311       else
312         vlib_cli_output (vm, "  tenant VRF independent");
313     #define _(N, i, n, s) \
314       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
315       foreach_snat_protocol
316     #undef _
317     }
318   /* *INDENT-ON* */
319   return 0;
320 }
321
322 static clib_error_t *
323 snat_feature_command_fn (vlib_main_t * vm,
324                          unformat_input_t * input, vlib_cli_command_t * cmd)
325 {
326   unformat_input_t _line_input, *line_input = &_line_input;
327   vnet_main_t *vnm = vnet_get_main ();
328   clib_error_t *error = 0;
329   u32 sw_if_index;
330   u32 *inside_sw_if_indices = 0;
331   u32 *outside_sw_if_indices = 0;
332   u8 is_output_feature = 0;
333   int is_del = 0;
334   int i;
335
336   sw_if_index = ~0;
337
338   /* Get a line of input. */
339   if (!unformat_user (input, unformat_line_input, line_input))
340     return 0;
341
342   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
343     {
344       if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
345                     vnm, &sw_if_index))
346         vec_add1 (inside_sw_if_indices, sw_if_index);
347       else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
348                          vnm, &sw_if_index))
349         vec_add1 (outside_sw_if_indices, sw_if_index);
350       else if (unformat (line_input, "output-feature"))
351         is_output_feature = 1;
352       else if (unformat (line_input, "del"))
353         is_del = 1;
354       else
355         {
356           error = clib_error_return (0, "unknown input '%U'",
357                                      format_unformat_error, line_input);
358           goto done;
359         }
360     }
361
362   if (vec_len (inside_sw_if_indices))
363     {
364       for (i = 0; i < vec_len (inside_sw_if_indices); i++)
365         {
366           sw_if_index = inside_sw_if_indices[i];
367           if (is_output_feature)
368             {
369               if (snat_interface_add_del_output_feature
370                   (sw_if_index, 1, is_del))
371                 {
372                   error = clib_error_return (0, "%s %U failed",
373                                              is_del ? "del" : "add",
374                                              format_vnet_sw_if_index_name,
375                                              vnm, sw_if_index);
376                   goto done;
377                 }
378             }
379           else
380             {
381               if (snat_interface_add_del (sw_if_index, 1, is_del))
382                 {
383                   error = clib_error_return (0, "%s %U failed",
384                                              is_del ? "del" : "add",
385                                              format_vnet_sw_if_index_name,
386                                              vnm, sw_if_index);
387                   goto done;
388                 }
389             }
390         }
391     }
392
393   if (vec_len (outside_sw_if_indices))
394     {
395       for (i = 0; i < vec_len (outside_sw_if_indices); i++)
396         {
397           sw_if_index = outside_sw_if_indices[i];
398           if (is_output_feature)
399             {
400               if (snat_interface_add_del_output_feature
401                   (sw_if_index, 0, is_del))
402                 {
403                   error = clib_error_return (0, "%s %U failed",
404                                              is_del ? "del" : "add",
405                                              format_vnet_sw_if_index_name,
406                                              vnm, sw_if_index);
407                   goto done;
408                 }
409             }
410           else
411             {
412               if (snat_interface_add_del (sw_if_index, 0, is_del))
413                 {
414                   error = clib_error_return (0, "%s %U failed",
415                                              is_del ? "del" : "add",
416                                              format_vnet_sw_if_index_name,
417                                              vnm, sw_if_index);
418                   goto done;
419                 }
420             }
421         }
422     }
423
424 done:
425   unformat_free (line_input);
426   vec_free (inside_sw_if_indices);
427   vec_free (outside_sw_if_indices);
428
429   return error;
430 }
431
432 static clib_error_t *
433 nat44_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
434                                   vlib_cli_command_t * cmd)
435 {
436   snat_main_t *sm = &snat_main;
437   snat_interface_t *i;
438   vnet_main_t *vnm = vnet_get_main ();
439
440   vlib_cli_output (vm, "NAT44 interfaces:");
441   /* *INDENT-OFF* */
442   pool_foreach (i, sm->interfaces,
443   ({
444     vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
445                      i->sw_if_index,
446                      (nat_interface_is_inside(i) &&
447                       nat_interface_is_outside(i)) ? "in out" :
448                      (nat_interface_is_inside(i) ? "in" : "out"));
449   }));
450
451   pool_foreach (i, sm->output_feature_interfaces,
452   ({
453     vlib_cli_output (vm, " %U output-feature %s",
454                      format_vnet_sw_if_index_name, vnm,
455                      i->sw_if_index,
456                      (nat_interface_is_inside(i) &&
457                       nat_interface_is_outside(i)) ? "in out" :
458                      (nat_interface_is_inside(i) ? "in" : "out"));
459   }));
460   /* *INDENT-ON* */
461
462   return 0;
463 }
464
465 static clib_error_t *
466 add_static_mapping_command_fn (vlib_main_t * vm,
467                                unformat_input_t * input,
468                                vlib_cli_command_t * cmd)
469 {
470   unformat_input_t _line_input, *line_input = &_line_input;
471   clib_error_t *error = 0;
472   ip4_address_t l_addr, e_addr;
473   u32 l_port = 0, e_port = 0, vrf_id = ~0;
474   int is_add = 1;
475   int addr_only = 1;
476   u32 sw_if_index = ~0;
477   vnet_main_t *vnm = vnet_get_main ();
478   int rv;
479   snat_protocol_t proto = ~0;
480   u8 proto_set = 0;
481   u8 twice_nat = 0;
482   u8 out2in_only = 0;
483
484   /* Get a line of input. */
485   if (!unformat_user (input, unformat_line_input, line_input))
486     return 0;
487
488   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
489     {
490       if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
491                     &l_port))
492         addr_only = 0;
493       else
494         if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr))
495         ;
496       else if (unformat (line_input, "external %U %u", unformat_ip4_address,
497                          &e_addr, &e_port))
498         addr_only = 0;
499       else if (unformat (line_input, "external %U", unformat_ip4_address,
500                          &e_addr))
501         ;
502       else if (unformat (line_input, "external %U %u",
503                          unformat_vnet_sw_interface, vnm, &sw_if_index,
504                          &e_port))
505         addr_only = 0;
506
507       else if (unformat (line_input, "external %U",
508                          unformat_vnet_sw_interface, vnm, &sw_if_index))
509         ;
510       else if (unformat (line_input, "vrf %u", &vrf_id))
511         ;
512       else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
513         proto_set = 1;
514       else if (unformat (line_input, "twice-nat"))
515         twice_nat = 1;
516       else if (unformat (line_input, "out2in-only"))
517         out2in_only = 1;
518       else if (unformat (line_input, "del"))
519         is_add = 0;
520       else
521         {
522           error = clib_error_return (0, "unknown input: '%U'",
523                                      format_unformat_error, line_input);
524           goto done;
525         }
526     }
527
528   if (twice_nat && addr_only)
529     {
530       error = clib_error_return (0, "twice NAT only for 1:1 NAPT");
531       goto done;
532     }
533
534   if (!addr_only && !proto_set)
535     {
536       error = clib_error_return (0, "missing protocol");
537       goto done;
538     }
539
540   rv = snat_add_static_mapping (l_addr, e_addr, (u16) l_port, (u16) e_port,
541                                 vrf_id, addr_only, sw_if_index, proto, is_add,
542                                 twice_nat, out2in_only, 0);
543
544   switch (rv)
545     {
546     case VNET_API_ERROR_INVALID_VALUE:
547       error = clib_error_return (0, "External port already in use.");
548       goto done;
549     case VNET_API_ERROR_NO_SUCH_ENTRY:
550       if (is_add)
551         error = clib_error_return (0, "External addres must be allocated.");
552       else
553         error = clib_error_return (0, "Mapping not exist.");
554       goto done;
555     case VNET_API_ERROR_NO_SUCH_FIB:
556       error = clib_error_return (0, "No such VRF id.");
557       goto done;
558     case VNET_API_ERROR_VALUE_EXIST:
559       error = clib_error_return (0, "Mapping already exist.");
560       goto done;
561     default:
562       break;
563     }
564
565 done:
566   unformat_free (line_input);
567
568   return error;
569 }
570
571 static clib_error_t *
572 add_identity_mapping_command_fn (vlib_main_t * vm,
573                                  unformat_input_t * input,
574                                  vlib_cli_command_t * cmd)
575 {
576   unformat_input_t _line_input, *line_input = &_line_input;
577   clib_error_t *error = 0;
578   ip4_address_t addr;
579   u32 port = 0, vrf_id = ~0;
580   int is_add = 1;
581   int addr_only = 1;
582   u32 sw_if_index = ~0;
583   vnet_main_t *vnm = vnet_get_main ();
584   int rv;
585   snat_protocol_t proto;
586
587   addr.as_u32 = 0;
588
589   /* Get a line of input. */
590   if (!unformat_user (input, unformat_line_input, line_input))
591     return 0;
592
593   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
594     {
595       if (unformat (line_input, "%U", unformat_ip4_address, &addr))
596         ;
597       else if (unformat (line_input, "external %U",
598                          unformat_vnet_sw_interface, vnm, &sw_if_index))
599         ;
600       else if (unformat (line_input, "vrf %u", &vrf_id))
601         ;
602       else if (unformat (line_input, "%U %u", unformat_snat_protocol, &proto,
603                          &port))
604         addr_only = 0;
605       else if (unformat (line_input, "del"))
606         is_add = 0;
607       else
608         {
609           error = clib_error_return (0, "unknown input: '%U'",
610                                      format_unformat_error, line_input);
611           goto done;
612         }
613     }
614
615   rv = snat_add_static_mapping (addr, addr, (u16) port, (u16) port,
616                                 vrf_id, addr_only, sw_if_index, proto, is_add,
617                                 0, 0, 0);
618
619   switch (rv)
620     {
621     case VNET_API_ERROR_INVALID_VALUE:
622       error = clib_error_return (0, "External port already in use.");
623       goto done;
624     case VNET_API_ERROR_NO_SUCH_ENTRY:
625       if (is_add)
626         error = clib_error_return (0, "External addres must be allocated.");
627       else
628         error = clib_error_return (0, "Mapping not exist.");
629       goto done;
630     case VNET_API_ERROR_NO_SUCH_FIB:
631       error = clib_error_return (0, "No such VRF id.");
632       goto done;
633     case VNET_API_ERROR_VALUE_EXIST:
634       error = clib_error_return (0, "Mapping already exist.");
635       goto done;
636     default:
637       break;
638     }
639
640 done:
641   unformat_free (line_input);
642
643   return error;
644 }
645
646 static clib_error_t *
647 add_lb_static_mapping_command_fn (vlib_main_t * vm,
648                                   unformat_input_t * input,
649                                   vlib_cli_command_t * cmd)
650 {
651   unformat_input_t _line_input, *line_input = &_line_input;
652   clib_error_t *error = 0;
653   ip4_address_t l_addr, e_addr;
654   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0;
655   int is_add = 1;
656   int rv;
657   snat_protocol_t proto;
658   u8 proto_set = 0;
659   nat44_lb_addr_port_t *locals = 0, local;
660   u8 twice_nat = 0;
661   u8 out2in_only = 0;
662
663   /* Get a line of input. */
664   if (!unformat_user (input, unformat_line_input, line_input))
665     return 0;
666
667   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
668     {
669       if (unformat (line_input, "local %U:%u probability %u",
670                     unformat_ip4_address, &l_addr, &l_port, &probability))
671         {
672           memset (&local, 0, sizeof (local));
673           local.addr = l_addr;
674           local.port = (u16) l_port;
675           local.probability = (u8) probability;
676           vec_add1 (locals, local);
677         }
678       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
679                          &e_addr, &e_port))
680         ;
681       else if (unformat (line_input, "vrf %u", &vrf_id))
682         ;
683       else if (unformat (line_input, "protocol %U", unformat_snat_protocol,
684                          &proto))
685         proto_set = 1;
686       else if (unformat (line_input, "twice-nat"))
687         twice_nat = 1;
688       else if (unformat (line_input, "out2in-only"))
689         out2in_only = 1;
690       else if (unformat (line_input, "del"))
691         is_add = 0;
692       else
693         {
694           error = clib_error_return (0, "unknown input: '%U'",
695                                      format_unformat_error, line_input);
696           goto done;
697         }
698     }
699
700   if (vec_len (locals) < 2)
701     {
702       error = clib_error_return (0, "at least two local must be set");
703       goto done;
704     }
705
706   if (!proto_set)
707     {
708       error = clib_error_return (0, "missing protocol");
709       goto done;
710     }
711
712   rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, vrf_id,
713                                         locals, is_add, twice_nat,
714                                         out2in_only, 0);
715
716   switch (rv)
717     {
718     case VNET_API_ERROR_INVALID_VALUE:
719       error = clib_error_return (0, "External port already in use.");
720       goto done;
721     case VNET_API_ERROR_NO_SUCH_ENTRY:
722       if (is_add)
723         error = clib_error_return (0, "External addres must be allocated.");
724       else
725         error = clib_error_return (0, "Mapping not exist.");
726       goto done;
727     case VNET_API_ERROR_VALUE_EXIST:
728       error = clib_error_return (0, "Mapping already exist.");
729       goto done;
730     default:
731       break;
732     }
733
734 done:
735   unformat_free (line_input);
736   vec_free (locals);
737
738   return error;
739 }
740
741 static clib_error_t *
742 nat44_show_static_mappings_command_fn (vlib_main_t * vm,
743                                        unformat_input_t * input,
744                                        vlib_cli_command_t * cmd)
745 {
746   snat_main_t *sm = &snat_main;
747   snat_static_mapping_t *m;
748   snat_static_map_resolve_t *rp;
749
750   vlib_cli_output (vm, "NAT44 static mappings:");
751   /* *INDENT-OFF* */
752   pool_foreach (m, sm->static_mappings,
753   ({
754     vlib_cli_output (vm, " %U", format_snat_static_mapping, m);
755   }));
756   vec_foreach (rp, sm->to_resolve)
757     vlib_cli_output (vm, " %U", format_snat_static_map_to_resolve, rp);
758   /* *INDENT-ON* */
759
760   return 0;
761 }
762
763 static clib_error_t *
764 snat_add_interface_address_command_fn (vlib_main_t * vm,
765                                        unformat_input_t * input,
766                                        vlib_cli_command_t * cmd)
767 {
768   snat_main_t *sm = &snat_main;
769   unformat_input_t _line_input, *line_input = &_line_input;
770   u32 sw_if_index;
771   int rv;
772   int is_del = 0;
773   clib_error_t *error = 0;
774   u8 twice_nat = 0;
775
776   /* Get a line of input. */
777   if (!unformat_user (input, unformat_line_input, line_input))
778     return 0;
779
780   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
781     {
782       if (unformat (line_input, "%U", unformat_vnet_sw_interface,
783                     sm->vnet_main, &sw_if_index))
784         ;
785       else if (unformat (line_input, "twice-nat"))
786         twice_nat = 1;
787       else if (unformat (line_input, "del"))
788         is_del = 1;
789       else
790         {
791           error = clib_error_return (0, "unknown input '%U'",
792                                      format_unformat_error, line_input);
793           goto done;
794         }
795     }
796
797   rv = snat_add_interface_address (sm, sw_if_index, is_del, twice_nat);
798
799   switch (rv)
800     {
801     case 0:
802       break;
803
804     default:
805       error = clib_error_return (0, "snat_add_interface_address returned %d",
806                                  rv);
807       goto done;
808     }
809
810 done:
811   unformat_free (line_input);
812
813   return error;
814 }
815
816 static clib_error_t *
817 nat44_show_interface_address_command_fn (vlib_main_t * vm,
818                                          unformat_input_t * input,
819                                          vlib_cli_command_t * cmd)
820 {
821   snat_main_t *sm = &snat_main;
822   vnet_main_t *vnm = vnet_get_main ();
823   u32 *sw_if_index;
824
825   /* *INDENT-OFF* */
826   vlib_cli_output (vm, "NAT44 pool address interfaces:");
827   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
828     {
829       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
830                        *sw_if_index);
831     }
832   vlib_cli_output (vm, "NAT44 twice-nat pool address interfaces:");
833   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices_twice_nat)
834     {
835       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
836                        *sw_if_index);
837     }
838   /* *INDENT-ON* */
839
840   return 0;
841 }
842
843 static clib_error_t *
844 nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
845                                 vlib_cli_command_t * cmd)
846 {
847   int verbose = 0;
848   snat_main_t *sm = &snat_main;
849   snat_main_per_thread_data_t *tsm;
850   snat_user_t *u;
851   int i = 0;
852
853   if (unformat (input, "detail"))
854     verbose = 1;
855
856   vlib_cli_output (vm, "NAT44 sessions:");
857
858   /* *INDENT-OFF* */
859   vec_foreach_index (i, sm->per_thread_data)
860     {
861       tsm = vec_elt_at_index (sm->per_thread_data, i);
862
863       pool_foreach (u, tsm->users,
864       ({
865         vlib_cli_output (vm, "  %U", format_snat_user, tsm, u, verbose);
866       }));
867     }
868   /* *INDENT-ON* */
869
870   return 0;
871 }
872
873 static clib_error_t *
874 nat44_del_session_command_fn (vlib_main_t * vm,
875                               unformat_input_t * input,
876                               vlib_cli_command_t * cmd)
877 {
878   snat_main_t *sm = &snat_main;
879   unformat_input_t _line_input, *line_input = &_line_input;
880   int is_in = 0;
881   clib_error_t *error = 0;
882   ip4_address_t addr;
883   u32 port = 0, vrf_id = sm->outside_vrf_id;
884   snat_protocol_t proto;
885   int rv;
886
887   /* Get a line of input. */
888   if (!unformat_user (input, unformat_line_input, line_input))
889     return 0;
890
891   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
892     {
893       if (unformat
894           (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port,
895            unformat_snat_protocol, &proto))
896         ;
897       else if (unformat (line_input, "in"))
898         {
899           is_in = 1;
900           vrf_id = sm->inside_vrf_id;
901         }
902       else if (unformat (line_input, "vrf %u", &vrf_id))
903         ;
904       else
905         {
906           error = clib_error_return (0, "unknown input '%U'",
907                                      format_unformat_error, line_input);
908           goto done;
909         }
910     }
911
912   rv = nat44_del_session (sm, &addr, port, proto, vrf_id, is_in);
913
914   switch (rv)
915     {
916     case 0:
917       break;
918
919     default:
920       error = clib_error_return (0, "nat44_del_session returned %d", rv);
921       goto done;
922     }
923
924 done:
925   unformat_free (line_input);
926
927   return error;
928 }
929
930 static clib_error_t *
931 snat_forwarding_set_command_fn (vlib_main_t * vm,
932                                 unformat_input_t * input,
933                                 vlib_cli_command_t * cmd)
934 {
935   snat_main_t *sm = &snat_main;
936   unformat_input_t _line_input, *line_input = &_line_input;
937   u8 forwarding_enable;
938   u8 forwarding_enable_set = 0;
939   clib_error_t *error = 0;
940
941   /* Get a line of input. */
942   if (!unformat_user (input, unformat_line_input, line_input))
943     return clib_error_return (0, "'enable' or 'disable' expected");
944
945   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
946     {
947       if (!forwarding_enable_set && unformat (line_input, "enable"))
948         {
949           forwarding_enable = 1;
950           forwarding_enable_set = 1;
951         }
952       else if (!forwarding_enable_set && unformat (line_input, "disable"))
953         {
954           forwarding_enable = 0;
955           forwarding_enable_set = 1;
956         }
957       else
958         {
959           error = clib_error_return (0, "unknown input '%U'",
960                                      format_unformat_error, line_input);
961           goto done;
962         }
963     }
964
965   if (!forwarding_enable_set)
966     {
967       error = clib_error_return (0, "'enable' or 'disable' expected");
968       goto done;
969     }
970
971   sm->forwarding_enabled = forwarding_enable;
972
973 done:
974   unformat_free (line_input);
975
976   return error;
977 }
978
979 static clib_error_t *
980 snat_det_map_command_fn (vlib_main_t * vm,
981                          unformat_input_t * input, vlib_cli_command_t * cmd)
982 {
983   snat_main_t *sm = &snat_main;
984   unformat_input_t _line_input, *line_input = &_line_input;
985   ip4_address_t in_addr, out_addr;
986   u32 in_plen, out_plen;
987   int is_add = 1, rv;
988   clib_error_t *error = 0;
989
990   /* Get a line of input. */
991   if (!unformat_user (input, unformat_line_input, line_input))
992     return 0;
993
994   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
995     {
996       if (unformat
997           (line_input, "in %U/%u", unformat_ip4_address, &in_addr, &in_plen))
998         ;
999       else
1000         if (unformat
1001             (line_input, "out %U/%u", unformat_ip4_address, &out_addr,
1002              &out_plen))
1003         ;
1004       else if (unformat (line_input, "del"))
1005         is_add = 0;
1006       else
1007         {
1008           error = clib_error_return (0, "unknown input '%U'",
1009                                      format_unformat_error, line_input);
1010           goto done;
1011         }
1012     }
1013
1014   rv = snat_det_add_map (sm, &in_addr, (u8) in_plen, &out_addr, (u8) out_plen,
1015                          is_add);
1016
1017   if (rv)
1018     {
1019       error = clib_error_return (0, "snat_det_add_map return %d", rv);
1020       goto done;
1021     }
1022
1023 done:
1024   unformat_free (line_input);
1025
1026   return error;
1027 }
1028
1029 static clib_error_t *
1030 nat44_det_show_mappings_command_fn (vlib_main_t * vm,
1031                                     unformat_input_t * input,
1032                                     vlib_cli_command_t * cmd)
1033 {
1034   snat_main_t *sm = &snat_main;
1035   snat_det_map_t *dm;
1036
1037   vlib_cli_output (vm, "NAT44 deterministic mappings:");
1038   /* *INDENT-OFF* */
1039   pool_foreach (dm, sm->det_maps,
1040   ({
1041     vlib_cli_output (vm, " in %U/%d out %U/%d\n",
1042                      format_ip4_address, &dm->in_addr, dm->in_plen,
1043                      format_ip4_address, &dm->out_addr, dm->out_plen);
1044     vlib_cli_output (vm, "  outside address sharing ratio: %d\n",
1045                      dm->sharing_ratio);
1046     vlib_cli_output (vm, "  number of ports per inside host: %d\n",
1047                      dm->ports_per_host);
1048     vlib_cli_output (vm, "  sessions number: %d\n", dm->ses_num);
1049   }));
1050   /* *INDENT-ON* */
1051
1052   return 0;
1053 }
1054
1055 static clib_error_t *
1056 snat_det_forward_command_fn (vlib_main_t * vm,
1057                              unformat_input_t * input,
1058                              vlib_cli_command_t * cmd)
1059 {
1060   snat_main_t *sm = &snat_main;
1061   unformat_input_t _line_input, *line_input = &_line_input;
1062   ip4_address_t in_addr, out_addr;
1063   u16 lo_port;
1064   snat_det_map_t *dm;
1065   clib_error_t *error = 0;
1066
1067   /* Get a line of input. */
1068   if (!unformat_user (input, unformat_line_input, line_input))
1069     return 0;
1070
1071   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1072     {
1073       if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
1074         ;
1075       else
1076         {
1077           error = clib_error_return (0, "unknown input '%U'",
1078                                      format_unformat_error, line_input);
1079           goto done;
1080         }
1081     }
1082
1083   dm = snat_det_map_by_user (sm, &in_addr);
1084   if (!dm)
1085     vlib_cli_output (vm, "no match");
1086   else
1087     {
1088       snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1089       vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
1090                        lo_port, lo_port + dm->ports_per_host - 1);
1091     }
1092
1093 done:
1094   unformat_free (line_input);
1095
1096   return error;
1097 }
1098
1099 static clib_error_t *
1100 snat_det_reverse_command_fn (vlib_main_t * vm,
1101                              unformat_input_t * input,
1102                              vlib_cli_command_t * cmd)
1103 {
1104   snat_main_t *sm = &snat_main;
1105   unformat_input_t _line_input, *line_input = &_line_input;
1106   ip4_address_t in_addr, out_addr;
1107   u32 out_port;
1108   snat_det_map_t *dm;
1109   clib_error_t *error = 0;
1110
1111   /* Get a line of input. */
1112   if (!unformat_user (input, unformat_line_input, line_input))
1113     return 0;
1114
1115   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1116     {
1117       if (unformat
1118           (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
1119         ;
1120       else
1121         {
1122           error = clib_error_return (0, "unknown input '%U'",
1123                                      format_unformat_error, line_input);
1124           goto done;
1125         }
1126     }
1127
1128   if (out_port < 1024 || out_port > 65535)
1129     {
1130       error = clib_error_return (0, "wrong port, must be <1024-65535>");
1131       goto done;
1132     }
1133
1134   dm = snat_det_map_by_out (sm, &out_addr);
1135   if (!dm)
1136     vlib_cli_output (vm, "no match");
1137   else
1138     {
1139       snat_det_reverse (dm, &out_addr, (u16) out_port, &in_addr);
1140       vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
1141     }
1142
1143 done:
1144   unformat_free (line_input);
1145
1146   return error;
1147 }
1148
1149 static clib_error_t *
1150 set_timeout_command_fn (vlib_main_t * vm,
1151                         unformat_input_t * input, vlib_cli_command_t * cmd)
1152 {
1153   snat_main_t *sm = &snat_main;
1154   unformat_input_t _line_input, *line_input = &_line_input;
1155   clib_error_t *error = 0;
1156
1157   /* Get a line of input. */
1158   if (!unformat_user (input, unformat_line_input, line_input))
1159     return 0;
1160
1161   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1162     {
1163       if (unformat (line_input, "udp %u", &sm->udp_timeout))
1164         ;
1165       else if (unformat (line_input, "tcp-established %u",
1166                          &sm->tcp_established_timeout))
1167         ;
1168       else if (unformat (line_input, "tcp-transitory %u",
1169                          &sm->tcp_transitory_timeout))
1170         ;
1171       else if (unformat (line_input, "icmp %u", &sm->icmp_timeout))
1172         ;
1173       else if (unformat (line_input, "reset"))
1174         {
1175           sm->udp_timeout = SNAT_UDP_TIMEOUT;
1176           sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
1177           sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
1178           sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
1179         }
1180       else
1181         {
1182           error = clib_error_return (0, "unknown input '%U'",
1183                                      format_unformat_error, line_input);
1184           goto done;
1185         }
1186     }
1187
1188 done:
1189   unformat_free (line_input);
1190
1191   return error;
1192 }
1193
1194 static clib_error_t *
1195 nat44_det_show_timeouts_command_fn (vlib_main_t * vm,
1196                                     unformat_input_t * input,
1197                                     vlib_cli_command_t * cmd)
1198 {
1199   snat_main_t *sm = &snat_main;
1200
1201   vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
1202   vlib_cli_output (vm, "tcp-established timeout: %dsec",
1203                    sm->tcp_established_timeout);
1204   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
1205                    sm->tcp_transitory_timeout);
1206   vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
1207
1208   return 0;
1209 }
1210
1211 static clib_error_t *
1212 nat44_det_show_sessions_command_fn (vlib_main_t * vm,
1213                                     unformat_input_t * input,
1214                                     vlib_cli_command_t * cmd)
1215 {
1216   snat_main_t *sm = &snat_main;
1217   snat_det_map_t *dm;
1218   snat_det_session_t *ses;
1219   int i;
1220
1221   vlib_cli_output (vm, "NAT44 deterministic sessions:");
1222   /* *INDENT-OFF* */
1223   pool_foreach (dm, sm->det_maps,
1224   ({
1225     vec_foreach_index (i, dm->sessions)
1226       {
1227         ses = vec_elt_at_index (dm->sessions, i);
1228         if (ses->in_port)
1229           vlib_cli_output (vm, "  %U", format_det_map_ses, dm, ses, &i);
1230       }
1231   }));
1232   /* *INDENT-ON* */
1233   return 0;
1234 }
1235
1236 static clib_error_t *
1237 snat_det_close_session_out_fn (vlib_main_t * vm,
1238                                unformat_input_t * input,
1239                                vlib_cli_command_t * cmd)
1240 {
1241   snat_main_t *sm = &snat_main;
1242   unformat_input_t _line_input, *line_input = &_line_input;
1243   ip4_address_t out_addr, ext_addr, in_addr;
1244   u32 out_port, ext_port;
1245   snat_det_map_t *dm;
1246   snat_det_session_t *ses;
1247   snat_det_out_key_t key;
1248   clib_error_t *error = 0;
1249
1250   /* Get a line of input. */
1251   if (!unformat_user (input, unformat_line_input, line_input))
1252     return 0;
1253
1254   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1255     {
1256       if (unformat (line_input, "%U:%d %U:%d",
1257                     unformat_ip4_address, &out_addr, &out_port,
1258                     unformat_ip4_address, &ext_addr, &ext_port))
1259         ;
1260       else
1261         {
1262           error = clib_error_return (0, "unknown input '%U'",
1263                                      format_unformat_error, line_input);
1264           goto done;
1265         }
1266     }
1267
1268   unformat_free (line_input);
1269
1270   dm = snat_det_map_by_out (sm, &out_addr);
1271   if (!dm)
1272     vlib_cli_output (vm, "no match");
1273   else
1274     {
1275       snat_det_reverse (dm, &ext_addr, (u16) out_port, &in_addr);
1276       key.ext_host_addr = out_addr;
1277       key.ext_host_port = ntohs ((u16) ext_port);
1278       key.out_port = ntohs ((u16) out_port);
1279       ses = snat_det_get_ses_by_out (dm, &out_addr, key.as_u64);
1280       if (!ses)
1281         vlib_cli_output (vm, "no match");
1282       else
1283         snat_det_ses_close (dm, ses);
1284     }
1285
1286 done:
1287   unformat_free (line_input);
1288
1289   return error;
1290 }
1291
1292 static clib_error_t *
1293 snat_det_close_session_in_fn (vlib_main_t * vm,
1294                               unformat_input_t * input,
1295                               vlib_cli_command_t * cmd)
1296 {
1297   snat_main_t *sm = &snat_main;
1298   unformat_input_t _line_input, *line_input = &_line_input;
1299   ip4_address_t in_addr, ext_addr;
1300   u32 in_port, ext_port;
1301   snat_det_map_t *dm;
1302   snat_det_session_t *ses;
1303   snat_det_out_key_t key;
1304   clib_error_t *error = 0;
1305
1306   /* Get a line of input. */
1307   if (!unformat_user (input, unformat_line_input, line_input))
1308     return 0;
1309
1310   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1311     {
1312       if (unformat (line_input, "%U:%d %U:%d",
1313                     unformat_ip4_address, &in_addr, &in_port,
1314                     unformat_ip4_address, &ext_addr, &ext_port))
1315         ;
1316       else
1317         {
1318           error = clib_error_return (0, "unknown input '%U'",
1319                                      format_unformat_error, line_input);
1320           goto done;
1321         }
1322     }
1323
1324   unformat_free (line_input);
1325
1326   dm = snat_det_map_by_user (sm, &in_addr);
1327   if (!dm)
1328     vlib_cli_output (vm, "no match");
1329   else
1330     {
1331       key.ext_host_addr = ext_addr;
1332       key.ext_host_port = ntohs ((u16) ext_port);
1333       ses =
1334         snat_det_find_ses_by_in (dm, &in_addr, ntohs ((u16) in_port), key);
1335       if (!ses)
1336         vlib_cli_output (vm, "no match");
1337       else
1338         snat_det_ses_close (dm, ses);
1339     }
1340
1341 done:
1342   unformat_free (line_input);
1343
1344   return error;
1345 }
1346 /* *INDENT-OFF* */
1347
1348 /*?
1349  * @cliexpar
1350  * @cliexstart{set snat workers}
1351  * Set NAT workers if 2 or more workers available, use:
1352  *  vpp# set snat workers 0-2,5
1353  * @cliexend
1354 ?*/
1355 VLIB_CLI_COMMAND (set_workers_command, static) = {
1356   .path = "set nat workers",
1357   .function = set_workers_command_fn,
1358   .short_help = "set nat workers <workers-list>",
1359 };
1360
1361 /*?
1362  * @cliexpar
1363  * @cliexstart{show nat workers}
1364  * Show NAT workers.
1365  *  vpp# show nat workers:
1366  *  2 workers
1367  *    vpp_wk_0
1368  *    vpp_wk_1
1369  * @cliexend
1370 ?*/
1371 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
1372   .path = "show nat workers",
1373   .short_help = "show nat workers",
1374   .function = nat_show_workers_commnad_fn,
1375 };
1376
1377 /*?
1378  * @cliexpar
1379  * @cliexstart{snat ipfix logging}
1380  * To enable NAT IPFIX logging use:
1381  *  vpp# nat ipfix logging
1382  * To set IPFIX exporter use:
1383  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
1384  * @cliexend
1385 ?*/
1386 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
1387   .path = "nat ipfix logging",
1388   .function = snat_ipfix_logging_enable_disable_command_fn,
1389   .short_help = "nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
1390 };
1391
1392 /*?
1393  * @cliexpar
1394  * @cliexstart{nat addr-port-assignment-alg}
1395  * Set address and port assignment algorithm
1396  * For the MAP-E CE limit port choice based on PSID use:
1397  *  vpp# nat addr-port-assignment-alg map-e psid 10 psid-offset 6 psid-len 6
1398  * To set standard (default) address and port assignment algorithm use:
1399  *  vpp# nat addr-port-assignment-alg default
1400  * @cliexend
1401 ?*/
1402 VLIB_CLI_COMMAND (nat44_set_alloc_addr_and_port_alg_command, static) = {
1403     .path = "nat addr-port-assignment-alg",
1404     .short_help = "nat addr-port-assignment-alg <alg-name> [<alg-params>]",
1405     .function = nat44_set_alloc_addr_and_port_alg_command_fn,
1406 };
1407
1408 /*?
1409  * @cliexpar
1410  * @cliexstart{nat44 add address}
1411  * Add/delete NAT44 pool address.
1412  * To add NAT44 pool address use:
1413  *  vpp# nat44 add address 172.16.1.3
1414  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
1415  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
1416  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
1417  * @cliexend
1418 ?*/
1419 VLIB_CLI_COMMAND (add_address_command, static) = {
1420   .path = "nat44 add address",
1421   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
1422                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
1423   .function = add_address_command_fn,
1424 };
1425
1426 /*?
1427  * @cliexpar
1428  * @cliexstart{show nat44 addresses}
1429  * Show NAT44 pool addresses.
1430  * vpp# show nat44 addresses
1431  * NAT44 pool addresses:
1432  * 172.16.2.2
1433  *   tenant VRF independent
1434  *   10 busy udp ports
1435  *   0 busy tcp ports
1436  *   0 busy icmp ports
1437  * 172.16.1.3
1438  *   tenant VRF: 10
1439  *   0 busy udp ports
1440  *   2 busy tcp ports
1441  *   0 busy icmp ports
1442  * NAT44 twice-nat pool addresses:
1443  * 10.20.30.72
1444  *   tenant VRF independent
1445  *   0 busy udp ports
1446  *   0 busy tcp ports
1447  *   0 busy icmp ports
1448  * @cliexend
1449 ?*/
1450 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
1451   .path = "show nat44 addresses",
1452   .short_help = "show nat44 addresses",
1453   .function = nat44_show_addresses_command_fn,
1454 };
1455
1456 /*?
1457  * @cliexpar
1458  * @cliexstart{set interface nat44}
1459  * Enable/disable NAT44 feature on the interface.
1460  * To enable NAT44 feature with local network interface use:
1461  *  vpp# set interface nat44 in GigabitEthernet0/8/0
1462  * To enable NAT44 feature with external network interface use:
1463  *  vpp# set interface nat44 out GigabitEthernet0/a/0
1464  * @cliexend
1465 ?*/
1466 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
1467   .path = "set interface nat44",
1468   .function = snat_feature_command_fn,
1469   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
1470                 "[del]",
1471 };
1472
1473 /*?
1474  * @cliexpar
1475  * @cliexstart{show nat44 interfaces}
1476  * Show interfaces with NAT44 feature.
1477  * vpp# show nat44 interfaces
1478  * NAT44 interfaces:
1479  *  GigabitEthernet0/8/0 in
1480  *  GigabitEthernet0/a/0 out
1481  * @cliexend
1482 ?*/
1483 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
1484   .path = "show nat44 interfaces",
1485   .short_help = "show nat44 interfaces",
1486   .function = nat44_show_interfaces_command_fn,
1487 };
1488
1489 /*?
1490  * @cliexpar
1491  * @cliexstart{nat44 add static mapping}
1492  * Static mapping allows hosts on the external network to initiate connection
1493  * to to the local network host.
1494  * To create static mapping between local host address 10.0.0.3 port 6303 and
1495  * external address 4.4.4.4 port 3606 for TCP protocol use:
1496  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
1497  * If not runnig "static mapping only" NAT plugin mode use before:
1498  *  vpp# nat44 add address 4.4.4.4
1499  * To create static mapping between local and external address use:
1500  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
1501  * @cliexend
1502 ?*/
1503 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
1504   .path = "nat44 add static mapping",
1505   .function = add_static_mapping_command_fn,
1506   .short_help =
1507     "nat44 add static mapping tcp|udp|icmp local <addr> [<port>] "
1508     "external <addr> [<port>] [vrf <table-id>] [twice-nat] [out2in-only] [del]",
1509 };
1510
1511 /*?
1512  * @cliexpar
1513  * @cliexstart{nat44 add identity mapping}
1514  * Identity mapping translate an IP address to itself.
1515  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
1516  * use:
1517  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
1518  * To create identity mapping for address 10.0.0.3 use:
1519  *  vpp# nat44 add identity mapping 10.0.0.3
1520  * To create identity mapping for DHCP addressed interface use:
1521  *  vpp# nat44 add identity mapping GigabitEthernet0/a/0 tcp 3606
1522  * @cliexend
1523 ?*/
1524 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
1525   .path = "nat44 add identity mapping",
1526   .function = add_identity_mapping_command_fn,
1527   .short_help = "nat44 add identity mapping <interface>|<ip4-addr> "
1528     "[<protocol> <port>] [vrf <table-id>] [del]",
1529 };
1530
1531 /*?
1532  * @cliexpar
1533  * @cliexstart{nat44 add load-balancing static mapping}
1534  * Service load balancing using NAT44
1535  * To add static mapping with load balancing for service with external IP
1536  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
1537  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
1538  *  vpp# nat44 add load-balancing static mapping protocol tcp external 1.2.3.4:80 local 10.100.10.10:8080 probability 80 local 10.100.10.20:8080 probability 20
1539  * @cliexend
1540 ?*/
1541 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
1542   .path = "nat44 add load-balancing static mapping",
1543   .function = add_lb_static_mapping_command_fn,
1544   .short_help =
1545     "nat44 add load-balancing static mapping protocol tcp|udp "
1546     "external <addr>:<port> local <addr>:<port> probability <n> [twice-nat] "
1547     "[vrf <table-id>] [out2in-only] [del]",
1548 };
1549
1550 /*?
1551  * @cliexpar
1552  * @cliexstart{show nat44 static mappings}
1553  * Show NAT44 static mappings.
1554  * vpp# show nat44 static mappings
1555  * NAT44 static mappings:
1556  *  local 10.0.0.3 external 4.4.4.4 vrf 0
1557  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
1558  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
1559  *   local 10.100.10.10:8080 probability 80
1560  *   local 10.100.10.20:8080 probability 20
1561  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
1562  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
1563  * @cliexend
1564 ?*/
1565 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
1566   .path = "show nat44 static mappings",
1567   .short_help = "show nat44 static mappings",
1568   .function = nat44_show_static_mappings_command_fn,
1569 };
1570
1571 /*?
1572  * @cliexpar
1573  * @cliexstart{nat44 add interface address}
1574  * Use NAT44 pool address from specific interfce
1575  * To add NAT44 pool address from specific interface use:
1576  *  vpp# nat44 add interface address GigabitEthernet0/8/0
1577  * @cliexend
1578 ?*/
1579 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
1580     .path = "nat44 add interface address",
1581     .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
1582     .function = snat_add_interface_address_command_fn,
1583 };
1584
1585 /*?
1586  * @cliexpar
1587  * @cliexstart{show nat44 interface address}
1588  * Show NAT44 pool address interfaces
1589  * vpp# show nat44 interface address
1590  * NAT44 pool address interfaces:
1591  *  GigabitEthernet0/a/0
1592  * NAT44 twice-nat pool address interfaces:
1593  *  GigabitEthernet0/8/0
1594  * @cliexend
1595 ?*/
1596 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
1597   .path = "show nat44 interface address",
1598   .short_help = "show nat44 interface address",
1599   .function = nat44_show_interface_address_command_fn,
1600 };
1601
1602 /*?
1603  * @cliexpar
1604  * @cliexstart{show nat44 sessions}
1605  * Show NAT44 sessions.
1606  * @cliexend
1607 ?*/
1608 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
1609   .path = "show nat44 sessions",
1610   .short_help = "show nat44 sessions [detail]",
1611   .function = nat44_show_sessions_command_fn,
1612 };
1613
1614 /*?
1615  * @cliexpar
1616  * @cliexstart{nat44 del session}
1617  * To administratively delete NAT44 session by inside address and port use:
1618  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
1619  * To administratively delete NAT44 session by outside address and port use:
1620  *  vpp# nat44 del session out 1.0.0.3:6033 udp
1621  * @cliexend
1622 ?*/
1623 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
1624     .path = "nat44 del session",
1625     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>]",
1626     .function = nat44_del_session_command_fn,
1627 };
1628
1629 /*?
1630  * @cliexpar
1631  * @cliexstart{nat44 forwarding}
1632  * Enable or disable forwarding
1633  * Forward packets which don't match existing translation
1634  * or static mapping instead of dropping them.
1635  * To enable forwarding, use:
1636  *  vpp# nat44 forwarding enable
1637  * To disable forwarding, use:
1638  *  vpp# nat44 forwarding disable
1639  * @cliexend
1640 ?*/
1641 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
1642   .path = "nat44 forwarding",
1643   .short_help = "nat44 forwarding enable|disable",
1644   .function = snat_forwarding_set_command_fn,
1645 };
1646
1647 /*?
1648  * @cliexpar
1649  * @cliexstart{nat44 deterministic add}
1650  * Create bijective mapping of inside address to outside address and port range
1651  * pairs, with the purpose of enabling deterministic NAT to reduce logging in
1652  * CGN deployments.
1653  * To create deterministic mapping between inside network 10.0.0.0/18 and
1654  * outside network 1.1.1.0/30 use:
1655  * # vpp# nat44 deterministic add in 10.0.0.0/18 out 1.1.1.0/30
1656  * @cliexend
1657 ?*/
1658 VLIB_CLI_COMMAND (snat_det_map_command, static) = {
1659     .path = "nat44 deterministic add",
1660     .short_help = "nat44 deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
1661     .function = snat_det_map_command_fn,
1662 };
1663
1664 /*?
1665  * @cliexpar
1666  * @cliexpstart{show nat44 deterministic mappings}
1667  * Show NAT44 deterministic mappings
1668  * vpp# show nat44 deterministic mappings
1669  * NAT44 deterministic mappings:
1670  *  in 10.0.0.0/24 out 1.1.1.1/32
1671  *   outside address sharing ratio: 256
1672  *   number of ports per inside host: 252
1673  *   sessions number: 0
1674  * @cliexend
1675 ?*/
1676 VLIB_CLI_COMMAND (nat44_det_show_mappings_command, static) = {
1677     .path = "show nat44 deterministic mappings",
1678     .short_help = "show nat44 deterministic mappings",
1679     .function = nat44_det_show_mappings_command_fn,
1680 };
1681
1682 /*?
1683  * @cliexpar
1684  * @cliexstart{nat44 deterministic forward}
1685  * Return outside address and port range from inside address for deterministic
1686  * NAT.
1687  * To obtain outside address and port of inside host use:
1688  *  vpp# nat44 deterministic forward 10.0.0.2
1689  *  1.1.1.0:<1054-1068>
1690  * @cliexend
1691 ?*/
1692 VLIB_CLI_COMMAND (snat_det_forward_command, static) = {
1693     .path = "nat44 deterministic forward",
1694     .short_help = "nat44 deterministic forward <addr>",
1695     .function = snat_det_forward_command_fn,
1696 };
1697
1698 /*?
1699  * @cliexpar
1700  * @cliexstart{nat44 deterministic reverse}
1701  * Return inside address from outside address and port for deterministic NAT.
1702  * To obtain inside host address from outside address and port use:
1703  *  #vpp nat44 deterministic reverse 1.1.1.1:1276
1704  *  10.0.16.16
1705  * @cliexend
1706 ?*/
1707 VLIB_CLI_COMMAND (snat_det_reverse_command, static) = {
1708     .path = "nat44 deterministic reverse",
1709     .short_help = "nat44 deterministic reverse <addr>:<port>",
1710     .function = snat_det_reverse_command_fn,
1711 };
1712
1713 /*?
1714  * @cliexpar
1715  * @cliexstart{set nat44 deterministic timeout}
1716  * Set values of timeouts for deterministic NAT (in seconds), use:
1717  *  vpp# set nat44 deterministic timeout udp 120 tcp-established 7500
1718  *  tcp-transitory 250 icmp 90
1719  * To reset default values use:
1720  *  vpp# set nat44 deterministic timeout reset
1721  * @cliexend
1722 ?*/
1723 VLIB_CLI_COMMAND (set_timeout_command, static) = {
1724   .path = "set nat44 deterministic timeout",
1725   .function = set_timeout_command_fn,
1726   .short_help =
1727     "set nat44 deterministic timeout [udp <sec> | tcp-established <sec> "
1728     "tcp-transitory <sec> | icmp <sec> | reset]",
1729 };
1730
1731 /*?
1732  * @cliexpar
1733  * @cliexstart{show nat44 deterministic timeouts}
1734  * Show values of timeouts for deterministic NAT.
1735  * vpp# show nat44 deterministic timeouts
1736  * udp timeout: 300sec
1737  * tcp-established timeout: 7440sec
1738  * tcp-transitory timeout: 240sec
1739  * icmp timeout: 60sec
1740  * @cliexend
1741 ?*/
1742 VLIB_CLI_COMMAND (nat44_det_show_timeouts_command, static) = {
1743   .path = "show nat44 deterministic timeouts",
1744   .short_help = "show nat44 deterministic timeouts",
1745   .function = nat44_det_show_timeouts_command_fn,
1746 };
1747
1748 /*?
1749  * @cliexpar
1750  * @cliexstart{show nat44 deterministic sessions}
1751  * Show NAT44 deterministic sessions.
1752  * vpp# show nat44 deterministic sessions
1753  * NAT44 deterministic sessions:
1754  *   in 10.0.0.3:3005 out 1.1.1.2:1146 external host 172.16.1.2:3006 state: udp-active expire: 306
1755  *   in 10.0.0.3:3000 out 1.1.1.2:1141 external host 172.16.1.2:3001 state: udp-active expire: 306
1756  *   in 10.0.0.4:3005 out 1.1.1.2:1177 external host 172.16.1.2:3006 state: udp-active expire: 306
1757  * @cliexend
1758 ?*/
1759 VLIB_CLI_COMMAND (nat44_det_show_sessions_command, static) = {
1760   .path = "show nat44 deterministic sessions",
1761   .short_help = "show nat44 deterministic sessions",
1762   .function = nat44_det_show_sessions_command_fn,
1763 };
1764
1765 /*?
1766  * @cliexpar
1767  * @cliexstart{nat44 deterministic close session out}
1768  * Close session using outside ip address and port
1769  * and external ip address and port, use:
1770  *  vpp# nat44 deterministic close session out 1.1.1.1:1276 2.2.2.2:2387
1771  * @cliexend
1772 ?*/
1773 VLIB_CLI_COMMAND (snat_det_close_sesion_out_command, static) = {
1774   .path = "nat44 deterministic close session out",
1775   .short_help = "nat44 deterministic close session out "
1776                 "<out_addr>:<out_port> <ext_addr>:<ext_port>",
1777   .function = snat_det_close_session_out_fn,
1778 };
1779
1780 /*?
1781  * @cliexpar
1782  * @cliexstart{nat44 deterministic close session in}
1783  * Close session using inside ip address and port
1784  * and external ip address and port, use:
1785  *  vpp# nat44 deterministic close session in 3.3.3.3:3487 2.2.2.2:2387
1786  * @cliexend
1787 ?*/
1788 VLIB_CLI_COMMAND (snat_det_close_session_in_command, static) = {
1789   .path = "nat44 deterministic close session in",
1790   .short_help = "nat44 deterministic close session in "
1791                 "<in_addr>:<in_port> <ext_addr>:<ext_port>",
1792   .function = snat_det_close_session_in_fn,
1793 };
1794
1795 /* *INDENT-ON* */
1796
1797 /*
1798  * fd.io coding-style-patch-verification: ON
1799  *
1800  * Local Variables:
1801  * eval: (c-set-style "gnu")
1802  * End:
1803  */