NAT44: nat44_add_del_lb_static_mapping enhancements (VPP-1514)
[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 <nat/nat64.h>
24 #include <nat/nat_inlines.h>
25 #include <nat/nat_affinity.h>
26 #include <vnet/fib/fib_table.h>
27
28 #define UNSUPPORTED_IN_DET_MODE_STR \
29   "This command is unsupported in deterministic mode"
30 #define SUPPORTED_ONLY_IN_DET_MODE_STR \
31   "This command is supported only in deterministic mode"
32
33 static clib_error_t *
34 set_workers_command_fn (vlib_main_t * vm,
35                         unformat_input_t * input, vlib_cli_command_t * cmd)
36 {
37   unformat_input_t _line_input, *line_input = &_line_input;
38   snat_main_t *sm = &snat_main;
39   uword *bitmap = 0;
40   int rv = 0;
41   clib_error_t *error = 0;
42
43   if (sm->deterministic)
44     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
45
46   /* Get a line of input. */
47   if (!unformat_user (input, unformat_line_input, line_input))
48     return 0;
49
50   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
51     {
52       if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap))
53         ;
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   if (bitmap == 0)
63     {
64       error = clib_error_return (0, "List of workers must be specified.");
65       goto done;
66     }
67
68   rv = snat_set_workers (bitmap);
69
70   clib_bitmap_free (bitmap);
71
72   switch (rv)
73     {
74     case VNET_API_ERROR_INVALID_WORKER:
75       error = clib_error_return (0, "Invalid worker(s).");
76       goto done;
77     case VNET_API_ERROR_FEATURE_DISABLED:
78       error = clib_error_return (0,
79                                  "Supported only if 2 or more workes available.");
80       goto done;
81     default:
82       break;
83     }
84
85 done:
86   unformat_free (line_input);
87
88   return error;
89 }
90
91 static clib_error_t *
92 nat_show_workers_commnad_fn (vlib_main_t * vm, unformat_input_t * input,
93                              vlib_cli_command_t * cmd)
94 {
95   snat_main_t *sm = &snat_main;
96   u32 *worker;
97
98   if (sm->deterministic)
99     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
100
101   if (sm->num_workers > 1)
102     {
103       vlib_cli_output (vm, "%d workers", vec_len (sm->workers));
104       /* *INDENT-OFF* */
105       vec_foreach (worker, sm->workers)
106         {
107           vlib_worker_thread_t *w =
108             vlib_worker_threads + *worker + sm->first_worker_index;
109           vlib_cli_output (vm, "  %s", w->name);
110         }
111       /* *INDENT-ON* */
112     }
113
114   return 0;
115 }
116
117 static clib_error_t *
118 snat_ipfix_logging_enable_disable_command_fn (vlib_main_t * vm,
119                                               unformat_input_t * input,
120                                               vlib_cli_command_t * cmd)
121 {
122   unformat_input_t _line_input, *line_input = &_line_input;
123   u32 domain_id = 0;
124   u32 src_port = 0;
125   u8 enable = 1;
126   int rv = 0;
127   clib_error_t *error = 0;
128
129   /* Get a line of input. */
130   if (!unformat_user (input, unformat_line_input, line_input))
131     return 0;
132
133   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
134     {
135       if (unformat (line_input, "domain %d", &domain_id))
136         ;
137       else if (unformat (line_input, "src-port %d", &src_port))
138         ;
139       else if (unformat (line_input, "disable"))
140         enable = 0;
141       else
142         {
143           error = clib_error_return (0, "unknown input '%U'",
144                                      format_unformat_error, line_input);
145           goto done;
146         }
147     }
148
149   rv = snat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port);
150
151   if (rv)
152     {
153       error = clib_error_return (0, "ipfix logging enable failed");
154       goto done;
155     }
156
157 done:
158   unformat_free (line_input);
159
160   return error;
161 }
162
163 static clib_error_t *
164 nat44_show_hash_commnad_fn (vlib_main_t * vm, unformat_input_t * input,
165                             vlib_cli_command_t * cmd)
166 {
167   snat_main_t *sm = &snat_main;
168   snat_main_per_thread_data_t *tsm;
169   nat_affinity_main_t *nam = &nat_affinity_main;
170   int i;
171   int verbose = 0;
172
173   if (unformat (input, "detail"))
174     verbose = 1;
175   else if (unformat (input, "verbose"))
176     verbose = 2;
177
178   vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->static_mapping_by_local,
179                    verbose);
180   vlib_cli_output (vm, "%U",
181                    format_bihash_8_8, &sm->static_mapping_by_external,
182                    verbose);
183   vec_foreach_index (i, sm->per_thread_data)
184   {
185     tsm = vec_elt_at_index (sm->per_thread_data, i);
186     vlib_cli_output (vm, "-------- thread %d %s --------\n",
187                      i, vlib_worker_threads[i].name);
188     if (sm->endpoint_dependent)
189       {
190         vlib_cli_output (vm, "%U", format_bihash_16_8, &tsm->in2out_ed,
191                          verbose);
192         vlib_cli_output (vm, "%U", format_bihash_16_8, &tsm->out2in_ed,
193                          verbose);
194       }
195     else
196       {
197         vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->in2out, verbose);
198         vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->out2in, verbose);
199       }
200     vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->user_hash, verbose);
201   }
202
203   if (sm->endpoint_dependent)
204     vlib_cli_output (vm, "%U", format_bihash_16_8, &nam->affinity_hash,
205                      verbose);
206   return 0;
207 }
208
209 static clib_error_t *
210 nat44_set_alloc_addr_and_port_alg_command_fn (vlib_main_t * vm,
211                                               unformat_input_t * input,
212                                               vlib_cli_command_t * cmd)
213 {
214   unformat_input_t _line_input, *line_input = &_line_input;
215   snat_main_t *sm = &snat_main;
216   clib_error_t *error = 0;
217   u32 psid, psid_offset, psid_length, port_start, port_end;
218
219   if (sm->deterministic)
220     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
221
222   /* Get a line of input. */
223   if (!unformat_user (input, unformat_line_input, line_input))
224     return 0;
225
226   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
227     {
228       if (unformat (line_input, "default"))
229         nat_set_alloc_addr_and_port_default ();
230       else
231         if (unformat
232             (line_input, "map-e psid %d psid-offset %d psid-len %d", &psid,
233              &psid_offset, &psid_length))
234         nat_set_alloc_addr_and_port_mape ((u16) psid, (u16) psid_offset,
235                                           (u16) psid_length);
236       else
237         if (unformat
238             (line_input, "port-range %d - %d", &port_start, &port_end))
239         {
240           if (port_end <= port_start)
241             {
242               error =
243                 clib_error_return (0,
244                                    "The end-port must be greater than start-port");
245               goto done;
246             }
247           nat_set_alloc_addr_and_port_range ((u16) port_start,
248                                              (u16) port_end);
249         }
250       else
251         {
252           error = clib_error_return (0, "unknown input '%U'",
253                                      format_unformat_error, line_input);
254           goto done;
255         }
256     }
257
258 done:
259   unformat_free (line_input);
260
261   return error;
262 };
263
264 static clib_error_t *
265 nat44_show_alloc_addr_and_port_alg_command_fn (vlib_main_t * vm,
266                                                unformat_input_t * input,
267                                                vlib_cli_command_t * cmd)
268 {
269   snat_main_t *sm = &snat_main;
270
271   if (sm->deterministic)
272     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
273
274   vlib_cli_output (vm, "NAT address and port: %U",
275                    format_nat_addr_and_port_alloc_alg,
276                    sm->addr_and_port_alloc_alg);
277   switch (sm->addr_and_port_alloc_alg)
278     {
279     case NAT_ADDR_AND_PORT_ALLOC_ALG_MAPE:
280       vlib_cli_output (vm, "  psid %d psid-offset %d psid-len %d", sm->psid,
281                        sm->psid_offset, sm->psid_length);
282       break;
283     case NAT_ADDR_AND_PORT_ALLOC_ALG_RANGE:
284       vlib_cli_output (vm, "  start-port %d end-port %d", sm->start_port,
285                        sm->end_port);
286       break;
287     default:
288       break;
289     }
290
291   return 0;
292 }
293
294 static clib_error_t *
295 nat_set_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input,
296                                  vlib_cli_command_t * cmd)
297 {
298   unformat_input_t _line_input, *line_input = &_line_input;
299   snat_main_t *sm = &snat_main;
300   clib_error_t *error = 0;
301   u32 mss;
302
303   /* Get a line of input. */
304   if (!unformat_user (input, unformat_line_input, line_input))
305     return 0;
306
307   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
308     {
309       if (unformat (line_input, "disable"))
310         sm->mss_clamping = 0;
311       else if (unformat (line_input, "%d", &mss))
312         {
313           sm->mss_clamping = (u16) mss;
314           sm->mss_value_net = clib_host_to_net_u16 (sm->mss_clamping);
315         }
316       else
317         {
318           error = clib_error_return (0, "unknown input '%U'",
319                                      format_unformat_error, line_input);
320           goto done;
321         }
322     }
323
324 done:
325   unformat_free (line_input);
326
327   return error;
328 }
329
330 static clib_error_t *
331 nat_show_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input,
332                                   vlib_cli_command_t * cmd)
333 {
334   snat_main_t *sm = &snat_main;
335
336   if (sm->mss_clamping)
337     vlib_cli_output (vm, "mss-clamping %d", sm->mss_clamping);
338   else
339     vlib_cli_output (vm, "mss-clamping disabled");
340
341   return 0;
342 }
343
344 static clib_error_t *
345 add_address_command_fn (vlib_main_t * vm,
346                         unformat_input_t * input, vlib_cli_command_t * cmd)
347 {
348   unformat_input_t _line_input, *line_input = &_line_input;
349   snat_main_t *sm = &snat_main;
350   ip4_address_t start_addr, end_addr, this_addr;
351   u32 start_host_order, end_host_order;
352   u32 vrf_id = ~0;
353   int i, count;
354   int is_add = 1;
355   int rv = 0;
356   clib_error_t *error = 0;
357   u8 twice_nat = 0;
358
359   if (sm->deterministic)
360     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
361
362   /* Get a line of input. */
363   if (!unformat_user (input, unformat_line_input, line_input))
364     return 0;
365
366   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
367     {
368       if (unformat (line_input, "%U - %U",
369                     unformat_ip4_address, &start_addr,
370                     unformat_ip4_address, &end_addr))
371         ;
372       else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
373         ;
374       else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
375         end_addr = start_addr;
376       else if (unformat (line_input, "twice-nat"))
377         twice_nat = 1;
378       else if (unformat (line_input, "del"))
379         is_add = 0;
380       else
381         {
382           error = clib_error_return (0, "unknown input '%U'",
383                                      format_unformat_error, line_input);
384           goto done;
385         }
386     }
387
388   if (sm->static_mapping_only)
389     {
390       error = clib_error_return (0, "static mapping only mode");
391       goto done;
392     }
393
394   start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
395   end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
396
397   if (end_host_order < start_host_order)
398     {
399       error = clib_error_return (0, "end address less than start address");
400       goto done;
401     }
402
403   count = (end_host_order - start_host_order) + 1;
404
405   if (count > 1024)
406     nat_log_info ("%U - %U, %d addresses...",
407                   format_ip4_address, &start_addr,
408                   format_ip4_address, &end_addr, count);
409
410   this_addr = start_addr;
411
412   for (i = 0; i < count; i++)
413     {
414       if (is_add)
415         rv = snat_add_address (sm, &this_addr, vrf_id, twice_nat);
416       else
417         rv = snat_del_address (sm, this_addr, 0, twice_nat);
418
419       switch (rv)
420         {
421         case VNET_API_ERROR_VALUE_EXIST:
422           error = clib_error_return (0, "NAT address already in use.");
423           goto done;
424         case VNET_API_ERROR_NO_SUCH_ENTRY:
425           error = clib_error_return (0, "NAT address not exist.");
426           goto done;
427         case VNET_API_ERROR_UNSPECIFIED:
428           error =
429             clib_error_return (0, "NAT address used in static mapping.");
430           goto done;
431         case VNET_API_ERROR_FEATURE_DISABLED:
432           error =
433             clib_error_return (0,
434                                "twice NAT available only for endpoint-dependent mode.");
435           goto done;
436         default:
437           break;
438         }
439
440       if (sm->out2in_dpo)
441         nat44_add_del_address_dpo (this_addr, is_add);
442
443       increment_v4_address (&this_addr);
444     }
445
446 done:
447   unformat_free (line_input);
448
449   return error;
450 }
451
452 static clib_error_t *
453 nat44_show_addresses_command_fn (vlib_main_t * vm, unformat_input_t * input,
454                                  vlib_cli_command_t * cmd)
455 {
456   snat_main_t *sm = &snat_main;
457   snat_address_t *ap;
458
459   if (sm->deterministic)
460     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
461
462   vlib_cli_output (vm, "NAT44 pool addresses:");
463   /* *INDENT-OFF* */
464   vec_foreach (ap, sm->addresses)
465     {
466       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
467       if (ap->fib_index != ~0)
468           vlib_cli_output (vm, "  tenant VRF: %u",
469             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
470       else
471         vlib_cli_output (vm, "  tenant VRF independent");
472     #define _(N, i, n, s) \
473       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
474       foreach_snat_protocol
475     #undef _
476     }
477   vlib_cli_output (vm, "NAT44 twice-nat pool addresses:");
478   vec_foreach (ap, sm->twice_nat_addresses)
479     {
480       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
481       if (ap->fib_index != ~0)
482           vlib_cli_output (vm, "  tenant VRF: %u",
483             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
484       else
485         vlib_cli_output (vm, "  tenant VRF independent");
486     #define _(N, i, n, s) \
487       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
488       foreach_snat_protocol
489     #undef _
490     }
491   /* *INDENT-ON* */
492   return 0;
493 }
494
495 static clib_error_t *
496 snat_feature_command_fn (vlib_main_t * vm,
497                          unformat_input_t * input, vlib_cli_command_t * cmd)
498 {
499   unformat_input_t _line_input, *line_input = &_line_input;
500   vnet_main_t *vnm = vnet_get_main ();
501   clib_error_t *error = 0;
502   u32 sw_if_index;
503   u32 *inside_sw_if_indices = 0;
504   u32 *outside_sw_if_indices = 0;
505   u8 is_output_feature = 0;
506   int is_del = 0;
507   int i;
508
509   sw_if_index = ~0;
510
511   /* Get a line of input. */
512   if (!unformat_user (input, unformat_line_input, line_input))
513     return 0;
514
515   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
516     {
517       if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
518                     vnm, &sw_if_index))
519         vec_add1 (inside_sw_if_indices, sw_if_index);
520       else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
521                          vnm, &sw_if_index))
522         vec_add1 (outside_sw_if_indices, sw_if_index);
523       else if (unformat (line_input, "output-feature"))
524         is_output_feature = 1;
525       else if (unformat (line_input, "del"))
526         is_del = 1;
527       else
528         {
529           error = clib_error_return (0, "unknown input '%U'",
530                                      format_unformat_error, line_input);
531           goto done;
532         }
533     }
534
535   if (vec_len (inside_sw_if_indices))
536     {
537       for (i = 0; i < vec_len (inside_sw_if_indices); i++)
538         {
539           sw_if_index = inside_sw_if_indices[i];
540           if (is_output_feature)
541             {
542               if (snat_interface_add_del_output_feature
543                   (sw_if_index, 1, is_del))
544                 {
545                   error = clib_error_return (0, "%s %U failed",
546                                              is_del ? "del" : "add",
547                                              format_vnet_sw_if_index_name,
548                                              vnm, sw_if_index);
549                   goto done;
550                 }
551             }
552           else
553             {
554               if (snat_interface_add_del (sw_if_index, 1, is_del))
555                 {
556                   error = clib_error_return (0, "%s %U failed",
557                                              is_del ? "del" : "add",
558                                              format_vnet_sw_if_index_name,
559                                              vnm, sw_if_index);
560                   goto done;
561                 }
562             }
563         }
564     }
565
566   if (vec_len (outside_sw_if_indices))
567     {
568       for (i = 0; i < vec_len (outside_sw_if_indices); i++)
569         {
570           sw_if_index = outside_sw_if_indices[i];
571           if (is_output_feature)
572             {
573               if (snat_interface_add_del_output_feature
574                   (sw_if_index, 0, is_del))
575                 {
576                   error = clib_error_return (0, "%s %U failed",
577                                              is_del ? "del" : "add",
578                                              format_vnet_sw_if_index_name,
579                                              vnm, sw_if_index);
580                   goto done;
581                 }
582             }
583           else
584             {
585               if (snat_interface_add_del (sw_if_index, 0, is_del))
586                 {
587                   error = clib_error_return (0, "%s %U failed",
588                                              is_del ? "del" : "add",
589                                              format_vnet_sw_if_index_name,
590                                              vnm, sw_if_index);
591                   goto done;
592                 }
593             }
594         }
595     }
596
597 done:
598   unformat_free (line_input);
599   vec_free (inside_sw_if_indices);
600   vec_free (outside_sw_if_indices);
601
602   return error;
603 }
604
605 static clib_error_t *
606 nat44_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
607                                   vlib_cli_command_t * cmd)
608 {
609   snat_main_t *sm = &snat_main;
610   snat_interface_t *i;
611   vnet_main_t *vnm = vnet_get_main ();
612
613   vlib_cli_output (vm, "NAT44 interfaces:");
614   /* *INDENT-OFF* */
615   pool_foreach (i, sm->interfaces,
616   ({
617     vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
618                      i->sw_if_index,
619                      (nat_interface_is_inside(i) &&
620                       nat_interface_is_outside(i)) ? "in out" :
621                      (nat_interface_is_inside(i) ? "in" : "out"));
622   }));
623
624   pool_foreach (i, sm->output_feature_interfaces,
625   ({
626     vlib_cli_output (vm, " %U output-feature %s",
627                      format_vnet_sw_if_index_name, vnm,
628                      i->sw_if_index,
629                      (nat_interface_is_inside(i) &&
630                       nat_interface_is_outside(i)) ? "in out" :
631                      (nat_interface_is_inside(i) ? "in" : "out"));
632   }));
633   /* *INDENT-ON* */
634
635   return 0;
636 }
637
638 static clib_error_t *
639 add_static_mapping_command_fn (vlib_main_t * vm,
640                                unformat_input_t * input,
641                                vlib_cli_command_t * cmd)
642 {
643   unformat_input_t _line_input, *line_input = &_line_input;
644   snat_main_t *sm = &snat_main;
645   clib_error_t *error = 0;
646   ip4_address_t l_addr, e_addr;
647   u32 l_port = 0, e_port = 0, vrf_id = ~0;
648   int is_add = 1;
649   int addr_only = 1;
650   u32 sw_if_index = ~0;
651   vnet_main_t *vnm = vnet_get_main ();
652   int rv;
653   snat_protocol_t proto = ~0;
654   u8 proto_set = 0;
655   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
656   u8 out2in_only = 0;
657
658   if (sm->deterministic)
659     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
660
661   /* Get a line of input. */
662   if (!unformat_user (input, unformat_line_input, line_input))
663     return 0;
664
665   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
666     {
667       if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
668                     &l_port))
669         addr_only = 0;
670       else
671         if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr))
672         ;
673       else if (unformat (line_input, "external %U %u", unformat_ip4_address,
674                          &e_addr, &e_port))
675         addr_only = 0;
676       else if (unformat (line_input, "external %U", unformat_ip4_address,
677                          &e_addr))
678         ;
679       else if (unformat (line_input, "external %U %u",
680                          unformat_vnet_sw_interface, vnm, &sw_if_index,
681                          &e_port))
682         addr_only = 0;
683
684       else if (unformat (line_input, "external %U",
685                          unformat_vnet_sw_interface, vnm, &sw_if_index))
686         ;
687       else if (unformat (line_input, "vrf %u", &vrf_id))
688         ;
689       else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
690         proto_set = 1;
691       else if (unformat (line_input, "twice-nat"))
692         twice_nat = TWICE_NAT;
693       else if (unformat (line_input, "self-twice-nat"))
694         twice_nat = TWICE_NAT_SELF;
695       else if (unformat (line_input, "out2in-only"))
696         out2in_only = 1;
697       else if (unformat (line_input, "del"))
698         is_add = 0;
699       else
700         {
701           error = clib_error_return (0, "unknown input: '%U'",
702                                      format_unformat_error, line_input);
703           goto done;
704         }
705     }
706
707   if (twice_nat && addr_only)
708     {
709       error = clib_error_return (0, "twice NAT only for 1:1 NAPT");
710       goto done;
711     }
712
713   if (!addr_only && !proto_set)
714     {
715       error = clib_error_return (0, "missing protocol");
716       goto done;
717     }
718
719   rv = snat_add_static_mapping (l_addr, e_addr, (u16) l_port, (u16) e_port,
720                                 vrf_id, addr_only, sw_if_index, proto, is_add,
721                                 twice_nat, out2in_only, 0, 0);
722
723   switch (rv)
724     {
725     case VNET_API_ERROR_INVALID_VALUE:
726       error = clib_error_return (0, "External port already in use.");
727       goto done;
728     case VNET_API_ERROR_NO_SUCH_ENTRY:
729       if (is_add)
730         error = clib_error_return (0, "External address must be allocated.");
731       else
732         error = clib_error_return (0, "Mapping not exist.");
733       goto done;
734     case VNET_API_ERROR_NO_SUCH_FIB:
735       error = clib_error_return (0, "No such VRF id.");
736       goto done;
737     case VNET_API_ERROR_VALUE_EXIST:
738       error = clib_error_return (0, "Mapping already exist.");
739       goto done;
740     case VNET_API_ERROR_FEATURE_DISABLED:
741       error =
742         clib_error_return (0,
743                            "twice-nat/out2in-only available only for endpoint-dependent mode.");
744       goto done;
745     default:
746       break;
747     }
748
749 done:
750   unformat_free (line_input);
751
752   return error;
753 }
754
755 static clib_error_t *
756 add_identity_mapping_command_fn (vlib_main_t * vm,
757                                  unformat_input_t * input,
758                                  vlib_cli_command_t * cmd)
759 {
760   unformat_input_t _line_input, *line_input = &_line_input;
761   snat_main_t *sm = &snat_main;
762   clib_error_t *error = 0;
763   ip4_address_t addr;
764   u32 port = 0, vrf_id = ~0;
765   int is_add = 1;
766   int addr_only = 1;
767   u32 sw_if_index = ~0;
768   vnet_main_t *vnm = vnet_get_main ();
769   int rv;
770   snat_protocol_t proto;
771
772   if (sm->deterministic)
773     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
774
775   addr.as_u32 = 0;
776
777   /* Get a line of input. */
778   if (!unformat_user (input, unformat_line_input, line_input))
779     return 0;
780
781   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
782     {
783       if (unformat (line_input, "%U", unformat_ip4_address, &addr))
784         ;
785       else if (unformat (line_input, "external %U",
786                          unformat_vnet_sw_interface, vnm, &sw_if_index))
787         ;
788       else if (unformat (line_input, "vrf %u", &vrf_id))
789         ;
790       else if (unformat (line_input, "%U %u", unformat_snat_protocol, &proto,
791                          &port))
792         addr_only = 0;
793       else if (unformat (line_input, "del"))
794         is_add = 0;
795       else
796         {
797           error = clib_error_return (0, "unknown input: '%U'",
798                                      format_unformat_error, line_input);
799           goto done;
800         }
801     }
802
803   rv = snat_add_static_mapping (addr, addr, (u16) port, (u16) port,
804                                 vrf_id, addr_only, sw_if_index, proto, is_add,
805                                 0, 0, 0, 1);
806
807   switch (rv)
808     {
809     case VNET_API_ERROR_INVALID_VALUE:
810       error = clib_error_return (0, "External port already in use.");
811       goto done;
812     case VNET_API_ERROR_NO_SUCH_ENTRY:
813       if (is_add)
814         error = clib_error_return (0, "External address must be allocated.");
815       else
816         error = clib_error_return (0, "Mapping not exist.");
817       goto done;
818     case VNET_API_ERROR_NO_SUCH_FIB:
819       error = clib_error_return (0, "No such VRF id.");
820       goto done;
821     case VNET_API_ERROR_VALUE_EXIST:
822       error = clib_error_return (0, "Mapping already exist.");
823       goto done;
824     default:
825       break;
826     }
827
828 done:
829   unformat_free (line_input);
830
831   return error;
832 }
833
834 static clib_error_t *
835 add_lb_static_mapping_command_fn (vlib_main_t * vm,
836                                   unformat_input_t * input,
837                                   vlib_cli_command_t * cmd)
838 {
839   unformat_input_t _line_input, *line_input = &_line_input;
840   snat_main_t *sm = &snat_main;
841   clib_error_t *error = 0;
842   ip4_address_t l_addr, e_addr;
843   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0, affinity = 0;
844   int is_add = 1;
845   int rv;
846   snat_protocol_t proto;
847   u8 proto_set = 0;
848   nat44_lb_addr_port_t *locals = 0, local;
849   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
850   u8 out2in_only = 0;
851
852   if (sm->deterministic)
853     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
854
855   /* Get a line of input. */
856   if (!unformat_user (input, unformat_line_input, line_input))
857     return 0;
858
859   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
860     {
861       if (unformat (line_input, "local %U:%u probability %u",
862                     unformat_ip4_address, &l_addr, &l_port, &probability))
863         {
864           clib_memset (&local, 0, sizeof (local));
865           local.addr = l_addr;
866           local.port = (u16) l_port;
867           local.probability = (u8) probability;
868           vec_add1 (locals, local);
869         }
870       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
871                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
872                          &probability))
873         {
874           clib_memset (&local, 0, sizeof (local));
875           local.addr = l_addr;
876           local.port = (u16) l_port;
877           local.probability = (u8) probability;
878           local.vrf_id = vrf_id;
879           vec_add1 (locals, local);
880         }
881       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
882                          &e_addr, &e_port))
883         ;
884       else if (unformat (line_input, "protocol %U", unformat_snat_protocol,
885                          &proto))
886         proto_set = 1;
887       else if (unformat (line_input, "twice-nat"))
888         twice_nat = TWICE_NAT;
889       else if (unformat (line_input, "self-twice-nat"))
890         twice_nat = TWICE_NAT_SELF;
891       else if (unformat (line_input, "out2in-only"))
892         out2in_only = 1;
893       else if (unformat (line_input, "del"))
894         is_add = 0;
895       else if (unformat (line_input, "affinity %u", &affinity))
896         ;
897       else
898         {
899           error = clib_error_return (0, "unknown input: '%U'",
900                                      format_unformat_error, line_input);
901           goto done;
902         }
903     }
904
905   if (vec_len (locals) < 2)
906     {
907       error = clib_error_return (0, "at least two local must be set");
908       goto done;
909     }
910
911   if (!proto_set)
912     {
913       error = clib_error_return (0, "missing protocol");
914       goto done;
915     }
916
917   rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, locals,
918                                         is_add, twice_nat, out2in_only, 0,
919                                         affinity);
920
921   switch (rv)
922     {
923     case VNET_API_ERROR_INVALID_VALUE:
924       error = clib_error_return (0, "External port already in use.");
925       goto done;
926     case VNET_API_ERROR_NO_SUCH_ENTRY:
927       if (is_add)
928         error = clib_error_return (0, "External address must be allocated.");
929       else
930         error = clib_error_return (0, "Mapping not exist.");
931       goto done;
932     case VNET_API_ERROR_VALUE_EXIST:
933       error = clib_error_return (0, "Mapping already exist.");
934       goto done;
935     case VNET_API_ERROR_FEATURE_DISABLED:
936       error =
937         clib_error_return (0, "Available only for endpoint-dependent mode.");
938       goto done;
939     default:
940       break;
941     }
942
943 done:
944   unformat_free (line_input);
945   vec_free (locals);
946
947   return error;
948 }
949
950 static clib_error_t *
951 add_lb_backend_command_fn (vlib_main_t * vm,
952                            unformat_input_t * input, vlib_cli_command_t * cmd)
953 {
954   unformat_input_t _line_input, *line_input = &_line_input;
955   snat_main_t *sm = &snat_main;
956   clib_error_t *error = 0;
957   ip4_address_t l_addr, e_addr;
958   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0;
959   int is_add = 1;
960   int rv;
961   snat_protocol_t proto;
962   u8 proto_set = 0;
963
964   if (sm->deterministic)
965     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
966
967   /* Get a line of input. */
968   if (!unformat_user (input, unformat_line_input, line_input))
969     return 0;
970
971   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
972     {
973       if (unformat (line_input, "local %U:%u probability %u",
974                     unformat_ip4_address, &l_addr, &l_port, &probability))
975         ;
976       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
977                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
978                          &probability))
979         ;
980       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
981                          &e_addr, &e_port))
982         ;
983       else if (unformat (line_input, "protocol %U", unformat_snat_protocol,
984                          &proto))
985         proto_set = 1;
986       else if (unformat (line_input, "del"))
987         is_add = 0;
988       else
989         {
990           error = clib_error_return (0, "unknown input: '%U'",
991                                      format_unformat_error, line_input);
992           goto done;
993         }
994     }
995
996   if (!l_port || !e_port)
997     {
998       error = clib_error_return (0, "local or external must be set");
999       goto done;
1000     }
1001
1002   if (!proto_set)
1003     {
1004       error = clib_error_return (0, "missing protocol");
1005       goto done;
1006     }
1007
1008   rv =
1009     nat44_lb_static_mapping_add_del_local (e_addr, (u16) e_port, l_addr,
1010                                            l_port, proto, vrf_id, probability,
1011                                            is_add);
1012
1013   switch (rv)
1014     {
1015     case VNET_API_ERROR_INVALID_VALUE:
1016       error = clib_error_return (0, "External is not load-balancing static "
1017                                  "mapping.");
1018       goto done;
1019     case VNET_API_ERROR_NO_SUCH_ENTRY:
1020       error = clib_error_return (0, "Mapping or back-end not exist.");
1021       goto done;
1022     case VNET_API_ERROR_VALUE_EXIST:
1023       error = clib_error_return (0, "Back-end already exist.");
1024       goto done;
1025     case VNET_API_ERROR_FEATURE_DISABLED:
1026       error =
1027         clib_error_return (0, "Available only for endpoint-dependent mode.");
1028       goto done;
1029     case VNET_API_ERROR_UNSPECIFIED:
1030       error = clib_error_return (0, "At least two back-ends must remain");
1031       goto done;
1032     default:
1033       break;
1034     }
1035
1036 done:
1037   unformat_free (line_input);
1038
1039   return error;
1040 }
1041
1042 static clib_error_t *
1043 nat44_show_static_mappings_command_fn (vlib_main_t * vm,
1044                                        unformat_input_t * input,
1045                                        vlib_cli_command_t * cmd)
1046 {
1047   snat_main_t *sm = &snat_main;
1048   snat_static_mapping_t *m;
1049   snat_static_map_resolve_t *rp;
1050
1051   if (sm->deterministic)
1052     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1053
1054   vlib_cli_output (vm, "NAT44 static mappings:");
1055   /* *INDENT-OFF* */
1056   pool_foreach (m, sm->static_mappings,
1057   ({
1058     vlib_cli_output (vm, " %U", format_snat_static_mapping, m);
1059   }));
1060   vec_foreach (rp, sm->to_resolve)
1061     vlib_cli_output (vm, " %U", format_snat_static_map_to_resolve, rp);
1062   /* *INDENT-ON* */
1063
1064   return 0;
1065 }
1066
1067 static clib_error_t *
1068 snat_add_interface_address_command_fn (vlib_main_t * vm,
1069                                        unformat_input_t * input,
1070                                        vlib_cli_command_t * cmd)
1071 {
1072   snat_main_t *sm = &snat_main;
1073   unformat_input_t _line_input, *line_input = &_line_input;
1074   u32 sw_if_index;
1075   int rv;
1076   int is_del = 0;
1077   clib_error_t *error = 0;
1078   u8 twice_nat = 0;
1079
1080   if (sm->deterministic)
1081     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1082
1083   /* Get a line of input. */
1084   if (!unformat_user (input, unformat_line_input, line_input))
1085     return 0;
1086
1087   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1088     {
1089       if (unformat (line_input, "%U", unformat_vnet_sw_interface,
1090                     sm->vnet_main, &sw_if_index))
1091         ;
1092       else if (unformat (line_input, "twice-nat"))
1093         twice_nat = 1;
1094       else if (unformat (line_input, "del"))
1095         is_del = 1;
1096       else
1097         {
1098           error = clib_error_return (0, "unknown input '%U'",
1099                                      format_unformat_error, line_input);
1100           goto done;
1101         }
1102     }
1103
1104   rv = snat_add_interface_address (sm, sw_if_index, is_del, twice_nat);
1105
1106   switch (rv)
1107     {
1108     case 0:
1109       break;
1110
1111     default:
1112       error = clib_error_return (0, "snat_add_interface_address returned %d",
1113                                  rv);
1114       goto done;
1115     }
1116
1117 done:
1118   unformat_free (line_input);
1119
1120   return error;
1121 }
1122
1123 static clib_error_t *
1124 nat44_show_interface_address_command_fn (vlib_main_t * vm,
1125                                          unformat_input_t * input,
1126                                          vlib_cli_command_t * cmd)
1127 {
1128   snat_main_t *sm = &snat_main;
1129   vnet_main_t *vnm = vnet_get_main ();
1130   u32 *sw_if_index;
1131
1132   if (sm->deterministic)
1133     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1134
1135   /* *INDENT-OFF* */
1136   vlib_cli_output (vm, "NAT44 pool address interfaces:");
1137   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
1138     {
1139       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
1140                        *sw_if_index);
1141     }
1142   vlib_cli_output (vm, "NAT44 twice-nat pool address interfaces:");
1143   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices_twice_nat)
1144     {
1145       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
1146                        *sw_if_index);
1147     }
1148   /* *INDENT-ON* */
1149
1150   return 0;
1151 }
1152
1153 static clib_error_t *
1154 nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
1155                                 vlib_cli_command_t * cmd)
1156 {
1157   int verbose = 0;
1158   snat_main_t *sm = &snat_main;
1159   snat_main_per_thread_data_t *tsm;
1160   snat_user_t *u;
1161   int i = 0;
1162
1163   if (sm->deterministic)
1164     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1165
1166   if (unformat (input, "detail"))
1167     verbose = 1;
1168
1169   vlib_cli_output (vm, "NAT44 sessions:");
1170
1171   /* *INDENT-OFF* */
1172   vec_foreach_index (i, sm->per_thread_data)
1173     {
1174       tsm = vec_elt_at_index (sm->per_thread_data, i);
1175
1176       vlib_cli_output (vm, "-------- thread %d %s: %d sessions --------\n",
1177                        i, vlib_worker_threads[i].name,
1178                        pool_elts (tsm->sessions));
1179       pool_foreach (u, tsm->users,
1180       ({
1181         vlib_cli_output (vm, "  %U", format_snat_user, tsm, u, verbose);
1182       }));
1183     }
1184   /* *INDENT-ON* */
1185
1186   return 0;
1187 }
1188
1189 static clib_error_t *
1190 nat44_del_session_command_fn (vlib_main_t * vm,
1191                               unformat_input_t * input,
1192                               vlib_cli_command_t * cmd)
1193 {
1194   snat_main_t *sm = &snat_main;
1195   unformat_input_t _line_input, *line_input = &_line_input;
1196   int is_in = 0, is_ed = 0;
1197   clib_error_t *error = 0;
1198   ip4_address_t addr, eh_addr;
1199   u32 port = 0, eh_port = 0, vrf_id = sm->outside_vrf_id;
1200   snat_protocol_t proto;
1201   int rv;
1202
1203   if (sm->deterministic)
1204     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1205
1206   /* Get a line of input. */
1207   if (!unformat_user (input, unformat_line_input, line_input))
1208     return 0;
1209
1210   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1211     {
1212       if (unformat
1213           (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port,
1214            unformat_snat_protocol, &proto))
1215         ;
1216       else if (unformat (line_input, "in"))
1217         {
1218           is_in = 1;
1219           vrf_id = sm->inside_vrf_id;
1220         }
1221       else if (unformat (line_input, "out"))
1222         {
1223           is_in = 0;
1224           vrf_id = sm->outside_vrf_id;
1225         }
1226       else if (unformat (line_input, "vrf %u", &vrf_id))
1227         ;
1228       else
1229         if (unformat
1230             (line_input, "external-host %U:%u", unformat_ip4_address,
1231              &eh_addr, &eh_port))
1232         is_ed = 1;
1233       else
1234         {
1235           error = clib_error_return (0, "unknown input '%U'",
1236                                      format_unformat_error, line_input);
1237           goto done;
1238         }
1239     }
1240
1241   if (is_ed)
1242     rv =
1243       nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port,
1244                             snat_proto_to_ip_proto (proto), vrf_id, is_in);
1245   else
1246     rv = nat44_del_session (sm, &addr, port, proto, vrf_id, is_in);
1247
1248   switch (rv)
1249     {
1250     case 0:
1251       break;
1252
1253     default:
1254       error = clib_error_return (0, "nat44_del_session returned %d", rv);
1255       goto done;
1256     }
1257
1258 done:
1259   unformat_free (line_input);
1260
1261   return error;
1262 }
1263
1264 static clib_error_t *
1265 snat_forwarding_set_command_fn (vlib_main_t * vm,
1266                                 unformat_input_t * input,
1267                                 vlib_cli_command_t * cmd)
1268 {
1269   snat_main_t *sm = &snat_main;
1270   unformat_input_t _line_input, *line_input = &_line_input;
1271   u8 forwarding_enable;
1272   u8 forwarding_enable_set = 0;
1273   clib_error_t *error = 0;
1274
1275   if (sm->deterministic)
1276     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1277
1278   /* Get a line of input. */
1279   if (!unformat_user (input, unformat_line_input, line_input))
1280     return clib_error_return (0, "'enable' or 'disable' expected");
1281
1282   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1283     {
1284       if (!forwarding_enable_set && unformat (line_input, "enable"))
1285         {
1286           forwarding_enable = 1;
1287           forwarding_enable_set = 1;
1288         }
1289       else if (!forwarding_enable_set && unformat (line_input, "disable"))
1290         {
1291           forwarding_enable = 0;
1292           forwarding_enable_set = 1;
1293         }
1294       else
1295         {
1296           error = clib_error_return (0, "unknown input '%U'",
1297                                      format_unformat_error, line_input);
1298           goto done;
1299         }
1300     }
1301
1302   if (!forwarding_enable_set)
1303     {
1304       error = clib_error_return (0, "'enable' or 'disable' expected");
1305       goto done;
1306     }
1307
1308   sm->forwarding_enabled = forwarding_enable;
1309
1310 done:
1311   unformat_free (line_input);
1312
1313   return error;
1314 }
1315
1316 static clib_error_t *
1317 snat_det_map_command_fn (vlib_main_t * vm,
1318                          unformat_input_t * input, vlib_cli_command_t * cmd)
1319 {
1320   snat_main_t *sm = &snat_main;
1321   unformat_input_t _line_input, *line_input = &_line_input;
1322   ip4_address_t in_addr, out_addr;
1323   u32 in_plen, out_plen;
1324   int is_add = 1, rv;
1325   clib_error_t *error = 0;
1326
1327   if (!sm->deterministic)
1328     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1329
1330   /* Get a line of input. */
1331   if (!unformat_user (input, unformat_line_input, line_input))
1332     return 0;
1333
1334   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1335     {
1336       if (unformat
1337           (line_input, "in %U/%u", unformat_ip4_address, &in_addr, &in_plen))
1338         ;
1339       else
1340         if (unformat
1341             (line_input, "out %U/%u", unformat_ip4_address, &out_addr,
1342              &out_plen))
1343         ;
1344       else if (unformat (line_input, "del"))
1345         is_add = 0;
1346       else
1347         {
1348           error = clib_error_return (0, "unknown input '%U'",
1349                                      format_unformat_error, line_input);
1350           goto done;
1351         }
1352     }
1353
1354   rv = snat_det_add_map (sm, &in_addr, (u8) in_plen, &out_addr, (u8) out_plen,
1355                          is_add);
1356
1357   if (rv)
1358     {
1359       error = clib_error_return (0, "snat_det_add_map return %d", rv);
1360       goto done;
1361     }
1362
1363 done:
1364   unformat_free (line_input);
1365
1366   return error;
1367 }
1368
1369 static clib_error_t *
1370 nat44_det_show_mappings_command_fn (vlib_main_t * vm,
1371                                     unformat_input_t * input,
1372                                     vlib_cli_command_t * cmd)
1373 {
1374   snat_main_t *sm = &snat_main;
1375   snat_det_map_t *dm;
1376
1377   if (!sm->deterministic)
1378     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1379
1380   vlib_cli_output (vm, "NAT44 deterministic mappings:");
1381   /* *INDENT-OFF* */
1382   pool_foreach (dm, sm->det_maps,
1383   ({
1384     vlib_cli_output (vm, " in %U/%d out %U/%d\n",
1385                      format_ip4_address, &dm->in_addr, dm->in_plen,
1386                      format_ip4_address, &dm->out_addr, dm->out_plen);
1387     vlib_cli_output (vm, "  outside address sharing ratio: %d\n",
1388                      dm->sharing_ratio);
1389     vlib_cli_output (vm, "  number of ports per inside host: %d\n",
1390                      dm->ports_per_host);
1391     vlib_cli_output (vm, "  sessions number: %d\n", dm->ses_num);
1392   }));
1393   /* *INDENT-ON* */
1394
1395   return 0;
1396 }
1397
1398 static clib_error_t *
1399 snat_det_forward_command_fn (vlib_main_t * vm,
1400                              unformat_input_t * input,
1401                              vlib_cli_command_t * cmd)
1402 {
1403   snat_main_t *sm = &snat_main;
1404   unformat_input_t _line_input, *line_input = &_line_input;
1405   ip4_address_t in_addr, out_addr;
1406   u16 lo_port;
1407   snat_det_map_t *dm;
1408   clib_error_t *error = 0;
1409
1410   if (!sm->deterministic)
1411     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1412
1413   /* Get a line of input. */
1414   if (!unformat_user (input, unformat_line_input, line_input))
1415     return 0;
1416
1417   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1418     {
1419       if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
1420         ;
1421       else
1422         {
1423           error = clib_error_return (0, "unknown input '%U'",
1424                                      format_unformat_error, line_input);
1425           goto done;
1426         }
1427     }
1428
1429   dm = snat_det_map_by_user (sm, &in_addr);
1430   if (!dm)
1431     vlib_cli_output (vm, "no match");
1432   else
1433     {
1434       snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1435       vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
1436                        lo_port, lo_port + dm->ports_per_host - 1);
1437     }
1438
1439 done:
1440   unformat_free (line_input);
1441
1442   return error;
1443 }
1444
1445 static clib_error_t *
1446 snat_det_reverse_command_fn (vlib_main_t * vm,
1447                              unformat_input_t * input,
1448                              vlib_cli_command_t * cmd)
1449 {
1450   snat_main_t *sm = &snat_main;
1451   unformat_input_t _line_input, *line_input = &_line_input;
1452   ip4_address_t in_addr, out_addr;
1453   u32 out_port;
1454   snat_det_map_t *dm;
1455   clib_error_t *error = 0;
1456
1457   if (!sm->deterministic)
1458     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1459
1460   /* Get a line of input. */
1461   if (!unformat_user (input, unformat_line_input, line_input))
1462     return 0;
1463
1464   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1465     {
1466       if (unformat
1467           (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
1468         ;
1469       else
1470         {
1471           error = clib_error_return (0, "unknown input '%U'",
1472                                      format_unformat_error, line_input);
1473           goto done;
1474         }
1475     }
1476
1477   if (out_port < 1024 || out_port > 65535)
1478     {
1479       error = clib_error_return (0, "wrong port, must be <1024-65535>");
1480       goto done;
1481     }
1482
1483   dm = snat_det_map_by_out (sm, &out_addr);
1484   if (!dm)
1485     vlib_cli_output (vm, "no match");
1486   else
1487     {
1488       snat_det_reverse (dm, &out_addr, (u16) out_port, &in_addr);
1489       vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
1490     }
1491
1492 done:
1493   unformat_free (line_input);
1494
1495   return error;
1496 }
1497
1498 static clib_error_t *
1499 set_timeout_command_fn (vlib_main_t * vm,
1500                         unformat_input_t * input, vlib_cli_command_t * cmd)
1501 {
1502   snat_main_t *sm = &snat_main;
1503   unformat_input_t _line_input, *line_input = &_line_input;
1504   clib_error_t *error = 0;
1505
1506   /* Get a line of input. */
1507   if (!unformat_user (input, unformat_line_input, line_input))
1508     return 0;
1509
1510   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1511     {
1512       if (unformat (line_input, "udp %u", &sm->udp_timeout))
1513         {
1514           if (nat64_set_udp_timeout (sm->udp_timeout))
1515             {
1516               error = clib_error_return (0, "Invalid UDP timeout value");
1517               goto done;
1518             }
1519         }
1520       else if (unformat (line_input, "tcp-established %u",
1521                          &sm->tcp_established_timeout))
1522         {
1523           if (nat64_set_tcp_timeouts
1524               (sm->tcp_transitory_timeout, sm->tcp_established_timeout))
1525             {
1526               error =
1527                 clib_error_return (0,
1528                                    "Invalid TCP established timeouts value");
1529               goto done;
1530             }
1531         }
1532       else if (unformat (line_input, "tcp-transitory %u",
1533                          &sm->tcp_transitory_timeout))
1534         {
1535           if (nat64_set_tcp_timeouts
1536               (sm->tcp_transitory_timeout, sm->tcp_established_timeout))
1537             {
1538               error =
1539                 clib_error_return (0,
1540                                    "Invalid TCP transitory timeouts value");
1541               goto done;
1542             }
1543         }
1544       else if (unformat (line_input, "icmp %u", &sm->icmp_timeout))
1545         {
1546           if (nat64_set_icmp_timeout (sm->icmp_timeout))
1547             {
1548               error = clib_error_return (0, "Invalid ICMP timeout value");
1549               goto done;
1550             }
1551         }
1552       else if (unformat (line_input, "reset"))
1553         {
1554           sm->udp_timeout = SNAT_UDP_TIMEOUT;
1555           sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
1556           sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
1557           sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
1558           nat64_set_udp_timeout (0);
1559           nat64_set_icmp_timeout (0);
1560           nat64_set_tcp_timeouts (0, 0);
1561         }
1562       else
1563         {
1564           error = clib_error_return (0, "unknown input '%U'",
1565                                      format_unformat_error, line_input);
1566           goto done;
1567         }
1568     }
1569
1570 done:
1571   unformat_free (line_input);
1572
1573   return error;
1574 }
1575
1576 static clib_error_t *
1577 nat_show_timeouts_command_fn (vlib_main_t * vm,
1578                               unformat_input_t * input,
1579                               vlib_cli_command_t * cmd)
1580 {
1581   snat_main_t *sm = &snat_main;
1582
1583   vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
1584   vlib_cli_output (vm, "tcp-established timeout: %dsec",
1585                    sm->tcp_established_timeout);
1586   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
1587                    sm->tcp_transitory_timeout);
1588   vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
1589
1590   return 0;
1591 }
1592
1593 static clib_error_t *
1594 nat44_det_show_sessions_command_fn (vlib_main_t * vm,
1595                                     unformat_input_t * input,
1596                                     vlib_cli_command_t * cmd)
1597 {
1598   snat_main_t *sm = &snat_main;
1599   snat_det_map_t *dm;
1600   snat_det_session_t *ses;
1601   int i;
1602
1603   if (!sm->deterministic)
1604     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1605
1606   vlib_cli_output (vm, "NAT44 deterministic sessions:");
1607   /* *INDENT-OFF* */
1608   pool_foreach (dm, sm->det_maps,
1609   ({
1610     vec_foreach_index (i, dm->sessions)
1611       {
1612         ses = vec_elt_at_index (dm->sessions, i);
1613         if (ses->in_port)
1614           vlib_cli_output (vm, "  %U", format_det_map_ses, dm, ses, &i);
1615       }
1616   }));
1617   /* *INDENT-ON* */
1618   return 0;
1619 }
1620
1621 static clib_error_t *
1622 snat_det_close_session_out_fn (vlib_main_t * vm,
1623                                unformat_input_t * input,
1624                                vlib_cli_command_t * cmd)
1625 {
1626   snat_main_t *sm = &snat_main;
1627   unformat_input_t _line_input, *line_input = &_line_input;
1628   ip4_address_t out_addr, ext_addr, in_addr;
1629   u32 out_port, ext_port;
1630   snat_det_map_t *dm;
1631   snat_det_session_t *ses;
1632   snat_det_out_key_t key;
1633   clib_error_t *error = 0;
1634
1635   if (!sm->deterministic)
1636     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1637
1638   /* Get a line of input. */
1639   if (!unformat_user (input, unformat_line_input, line_input))
1640     return 0;
1641
1642   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1643     {
1644       if (unformat (line_input, "%U:%d %U:%d",
1645                     unformat_ip4_address, &out_addr, &out_port,
1646                     unformat_ip4_address, &ext_addr, &ext_port))
1647         ;
1648       else
1649         {
1650           error = clib_error_return (0, "unknown input '%U'",
1651                                      format_unformat_error, line_input);
1652           goto done;
1653         }
1654     }
1655
1656   unformat_free (line_input);
1657
1658   dm = snat_det_map_by_out (sm, &out_addr);
1659   if (!dm)
1660     vlib_cli_output (vm, "no match");
1661   else
1662     {
1663       snat_det_reverse (dm, &ext_addr, (u16) out_port, &in_addr);
1664       key.ext_host_addr = out_addr;
1665       key.ext_host_port = ntohs ((u16) ext_port);
1666       key.out_port = ntohs ((u16) out_port);
1667       ses = snat_det_get_ses_by_out (dm, &out_addr, key.as_u64);
1668       if (!ses)
1669         vlib_cli_output (vm, "no match");
1670       else
1671         snat_det_ses_close (dm, ses);
1672     }
1673
1674 done:
1675   unformat_free (line_input);
1676
1677   return error;
1678 }
1679
1680 static clib_error_t *
1681 snat_det_close_session_in_fn (vlib_main_t * vm,
1682                               unformat_input_t * input,
1683                               vlib_cli_command_t * cmd)
1684 {
1685   snat_main_t *sm = &snat_main;
1686   unformat_input_t _line_input, *line_input = &_line_input;
1687   ip4_address_t in_addr, ext_addr;
1688   u32 in_port, ext_port;
1689   snat_det_map_t *dm;
1690   snat_det_session_t *ses;
1691   snat_det_out_key_t key;
1692   clib_error_t *error = 0;
1693
1694   if (!sm->deterministic)
1695     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1696
1697   /* Get a line of input. */
1698   if (!unformat_user (input, unformat_line_input, line_input))
1699     return 0;
1700
1701   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1702     {
1703       if (unformat (line_input, "%U:%d %U:%d",
1704                     unformat_ip4_address, &in_addr, &in_port,
1705                     unformat_ip4_address, &ext_addr, &ext_port))
1706         ;
1707       else
1708         {
1709           error = clib_error_return (0, "unknown input '%U'",
1710                                      format_unformat_error, line_input);
1711           goto done;
1712         }
1713     }
1714
1715   unformat_free (line_input);
1716
1717   dm = snat_det_map_by_user (sm, &in_addr);
1718   if (!dm)
1719     vlib_cli_output (vm, "no match");
1720   else
1721     {
1722       key.ext_host_addr = ext_addr;
1723       key.ext_host_port = ntohs ((u16) ext_port);
1724       ses =
1725         snat_det_find_ses_by_in (dm, &in_addr, ntohs ((u16) in_port), key);
1726       if (!ses)
1727         vlib_cli_output (vm, "no match");
1728       else
1729         snat_det_ses_close (dm, ses);
1730     }
1731
1732 done:
1733   unformat_free (line_input);
1734
1735   return error;
1736 }
1737 /* *INDENT-OFF* */
1738
1739 /*?
1740  * @cliexpar
1741  * @cliexstart{set snat workers}
1742  * Set NAT workers if 2 or more workers available, use:
1743  *  vpp# set snat workers 0-2,5
1744  * @cliexend
1745 ?*/
1746 VLIB_CLI_COMMAND (set_workers_command, static) = {
1747   .path = "set nat workers",
1748   .function = set_workers_command_fn,
1749   .short_help = "set nat workers <workers-list>",
1750 };
1751
1752 /*?
1753  * @cliexpar
1754  * @cliexstart{show nat workers}
1755  * Show NAT workers.
1756  *  vpp# show nat workers:
1757  *  2 workers
1758  *    vpp_wk_0
1759  *    vpp_wk_1
1760  * @cliexend
1761 ?*/
1762 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
1763   .path = "show nat workers",
1764   .short_help = "show nat workers",
1765   .function = nat_show_workers_commnad_fn,
1766 };
1767
1768 /*?
1769  * @cliexpar
1770  * @cliexstart{set nat timeout}
1771  * Set values of timeouts for NAT sessions (in seconds), use:
1772  *  vpp# set nat timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90
1773  * To reset default values use:
1774  *  vpp# set nat44 deterministic timeout reset
1775  * @cliexend
1776 ?*/
1777 VLIB_CLI_COMMAND (set_timeout_command, static) = {
1778   .path = "set nat timeout",
1779   .function = set_timeout_command_fn,
1780   .short_help =
1781     "set nat timeout [udp <sec> | tcp-established <sec> "
1782     "tcp-transitory <sec> | icmp <sec> | reset]",
1783 };
1784
1785 /*?
1786  * @cliexpar
1787  * @cliexstart{show nat timeouts}
1788  * Show values of timeouts for NAT sessions.
1789  * vpp# show nat timeouts
1790  * udp timeout: 300sec
1791  * tcp-established timeout: 7440sec
1792  * tcp-transitory timeout: 240sec
1793  * icmp timeout: 60sec
1794  * @cliexend
1795 ?*/
1796 VLIB_CLI_COMMAND (nat_show_timeouts_command, static) = {
1797   .path = "show nat timeouts",
1798   .short_help = "show nat timeouts",
1799   .function = nat_show_timeouts_command_fn,
1800 };
1801
1802 /*?
1803  * @cliexpar
1804  * @cliexstart{snat ipfix logging}
1805  * To enable NAT IPFIX logging use:
1806  *  vpp# nat ipfix logging
1807  * To set IPFIX exporter use:
1808  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
1809  * @cliexend
1810 ?*/
1811 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
1812   .path = "nat ipfix logging",
1813   .function = snat_ipfix_logging_enable_disable_command_fn,
1814   .short_help = "nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
1815 };
1816
1817 /*?
1818  * @cliexpar
1819  * @cliexstart{nat addr-port-assignment-alg}
1820  * Set address and port assignment algorithm
1821  * For the MAP-E CE limit port choice based on PSID use:
1822  *  vpp# nat addr-port-assignment-alg map-e psid 10 psid-offset 6 psid-len 6
1823  * For port range use:
1824  *  vpp# nat addr-port-assignment-alg port-range <start-port> - <end-port>
1825  * To set standard (default) address and port assignment algorithm use:
1826  *  vpp# nat addr-port-assignment-alg default
1827  * @cliexend
1828 ?*/
1829 VLIB_CLI_COMMAND (nat44_set_alloc_addr_and_port_alg_command, static) = {
1830     .path = "nat addr-port-assignment-alg",
1831     .short_help = "nat addr-port-assignment-alg <alg-name> [<alg-params>]",
1832     .function = nat44_set_alloc_addr_and_port_alg_command_fn,
1833 };
1834
1835 /*?
1836  * @cliexpar
1837  * @cliexstart{show nat addr-port-assignment-alg}
1838  * Show address and port assignment algorithm
1839  * @cliexend
1840 ?*/
1841 VLIB_CLI_COMMAND (nat44_show_alloc_addr_and_port_alg_command, static) = {
1842     .path = "show nat addr-port-assignment-alg",
1843     .short_help = "show nat addr-port-assignment-alg",
1844     .function = nat44_show_alloc_addr_and_port_alg_command_fn,
1845 };
1846
1847 /*?
1848  * @cliexpar
1849  * @cliexstart{nat mss-clamping}
1850  * Set TCP MSS rewriting configuration
1851  * To enable TCP MSS rewriting use:
1852  *  vpp# nat mss-clamping 1452
1853  * To disbale TCP MSS rewriting use:
1854  *  vpp# nat mss-clamping disable
1855 ?*/
1856 VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = {
1857     .path = "nat mss-clamping",
1858     .short_help = "nat mss-clamping <mss-value>|disable",
1859     .function = nat_set_mss_clamping_command_fn,
1860 };
1861
1862 /*?
1863  * @cliexpar
1864  * @cliexstart{nat mss-clamping}
1865  * Show TCP MSS rewriting configuration
1866 ?*/
1867 VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = {
1868     .path = "show nat mss-clamping",
1869     .short_help = "show nat mss-clamping",
1870     .function = nat_show_mss_clamping_command_fn,
1871 };
1872
1873 /*?
1874  * @cliexpar
1875  * @cliexstart{show nat44 hash tables}
1876  * Show NAT44 hash tables
1877  * @cliexend
1878 ?*/
1879 VLIB_CLI_COMMAND (nat44_show_hash, static) = {
1880   .path = "show nat44 hash tables",
1881   .short_help = "show nat44 hash tables [detail|verbose]",
1882   .function = nat44_show_hash_commnad_fn,
1883 };
1884
1885 /*?
1886  * @cliexpar
1887  * @cliexstart{nat44 add address}
1888  * Add/delete NAT44 pool address.
1889  * To add NAT44 pool address use:
1890  *  vpp# nat44 add address 172.16.1.3
1891  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
1892  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
1893  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
1894  * @cliexend
1895 ?*/
1896 VLIB_CLI_COMMAND (add_address_command, static) = {
1897   .path = "nat44 add address",
1898   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
1899                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
1900   .function = add_address_command_fn,
1901 };
1902
1903 /*?
1904  * @cliexpar
1905  * @cliexstart{show nat44 addresses}
1906  * Show NAT44 pool addresses.
1907  * vpp# show nat44 addresses
1908  * NAT44 pool addresses:
1909  * 172.16.2.2
1910  *   tenant VRF independent
1911  *   10 busy udp ports
1912  *   0 busy tcp ports
1913  *   0 busy icmp ports
1914  * 172.16.1.3
1915  *   tenant VRF: 10
1916  *   0 busy udp ports
1917  *   2 busy tcp ports
1918  *   0 busy icmp ports
1919  * NAT44 twice-nat pool addresses:
1920  * 10.20.30.72
1921  *   tenant VRF independent
1922  *   0 busy udp ports
1923  *   0 busy tcp ports
1924  *   0 busy icmp ports
1925  * @cliexend
1926 ?*/
1927 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
1928   .path = "show nat44 addresses",
1929   .short_help = "show nat44 addresses",
1930   .function = nat44_show_addresses_command_fn,
1931 };
1932
1933 /*?
1934  * @cliexpar
1935  * @cliexstart{set interface nat44}
1936  * Enable/disable NAT44 feature on the interface.
1937  * To enable NAT44 feature with local network interface use:
1938  *  vpp# set interface nat44 in GigabitEthernet0/8/0
1939  * To enable NAT44 feature with external network interface use:
1940  *  vpp# set interface nat44 out GigabitEthernet0/a/0
1941  * @cliexend
1942 ?*/
1943 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
1944   .path = "set interface nat44",
1945   .function = snat_feature_command_fn,
1946   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
1947                 "[del]",
1948 };
1949
1950 /*?
1951  * @cliexpar
1952  * @cliexstart{show nat44 interfaces}
1953  * Show interfaces with NAT44 feature.
1954  * vpp# show nat44 interfaces
1955  * NAT44 interfaces:
1956  *  GigabitEthernet0/8/0 in
1957  *  GigabitEthernet0/a/0 out
1958  * @cliexend
1959 ?*/
1960 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
1961   .path = "show nat44 interfaces",
1962   .short_help = "show nat44 interfaces",
1963   .function = nat44_show_interfaces_command_fn,
1964 };
1965
1966 /*?
1967  * @cliexpar
1968  * @cliexstart{nat44 add static mapping}
1969  * Static mapping allows hosts on the external network to initiate connection
1970  * to to the local network host.
1971  * To create static mapping between local host address 10.0.0.3 port 6303 and
1972  * external address 4.4.4.4 port 3606 for TCP protocol use:
1973  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
1974  * If not runnig "static mapping only" NAT plugin mode use before:
1975  *  vpp# nat44 add address 4.4.4.4
1976  * To create static mapping between local and external address use:
1977  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
1978  * @cliexend
1979 ?*/
1980 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
1981   .path = "nat44 add static mapping",
1982   .function = add_static_mapping_command_fn,
1983   .short_help =
1984     "nat44 add static mapping tcp|udp|icmp local <addr> [<port>] "
1985     "external <addr> [<port>] [vrf <table-id>] [twice-nat|self-twice-nat] "
1986     "[out2in-only] [del]",
1987 };
1988
1989 /*?
1990  * @cliexpar
1991  * @cliexstart{nat44 add identity mapping}
1992  * Identity mapping translate an IP address to itself.
1993  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
1994  * use:
1995  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
1996  * To create identity mapping for address 10.0.0.3 use:
1997  *  vpp# nat44 add identity mapping 10.0.0.3
1998  * To create identity mapping for DHCP addressed interface use:
1999  *  vpp# nat44 add identity mapping GigabitEthernet0/a/0 tcp 3606
2000  * @cliexend
2001 ?*/
2002 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
2003   .path = "nat44 add identity mapping",
2004   .function = add_identity_mapping_command_fn,
2005   .short_help = "nat44 add identity mapping <interface>|<ip4-addr> "
2006     "[<protocol> <port>] [vrf <table-id>] [del]",
2007 };
2008
2009 /*?
2010  * @cliexpar
2011  * @cliexstart{nat44 add load-balancing static mapping}
2012  * Service load balancing using NAT44
2013  * To add static mapping with load balancing for service with external IP
2014  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
2015  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
2016  *  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
2017  * @cliexend
2018 ?*/
2019 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
2020   .path = "nat44 add load-balancing static mapping",
2021   .function = add_lb_static_mapping_command_fn,
2022   .short_help =
2023     "nat44 add load-balancing static mapping protocol tcp|udp "
2024     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2025     "probability <n> [twice-nat|self-twice-nat] [out2in-only] "
2026     "[affinity <timeout-seconds>] [del]",
2027 };
2028
2029 /*?
2030  * @cliexpar
2031  * @cliexstart{nat44 add load-balancing static mapping}
2032  * Modify service load balancing using NAT44
2033  * To add new back-end server 10.100.10.30:8080 for service load balancing
2034  * static mapping with external IP address 1.2.3.4 and TCP port 80 use:
2035  *  vpp# nat44 add load-balancing back-end protocol tcp external 1.2.3.4:80 local 10.100.10.30:8080 probability 25
2036  * @cliexend
2037 ?*/
2038 VLIB_CLI_COMMAND (add_lb_backend_command, static) = {
2039   .path = "nat44 add load-balancing back-end",
2040   .function = add_lb_backend_command_fn,
2041   .short_help =
2042     "nat44 add load-balancing back-end protocol tcp|udp "
2043     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2044     "probability <n> [del]",
2045 };
2046
2047 /*?
2048  * @cliexpar
2049  * @cliexstart{show nat44 static mappings}
2050  * Show NAT44 static mappings.
2051  * vpp# show nat44 static mappings
2052  * NAT44 static mappings:
2053  *  local 10.0.0.3 external 4.4.4.4 vrf 0
2054  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
2055  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
2056  *   local 10.100.10.10:8080 probability 80
2057  *   local 10.100.10.20:8080 probability 20
2058  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
2059  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
2060  * @cliexend
2061 ?*/
2062 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
2063   .path = "show nat44 static mappings",
2064   .short_help = "show nat44 static mappings",
2065   .function = nat44_show_static_mappings_command_fn,
2066 };
2067
2068 /*?
2069  * @cliexpar
2070  * @cliexstart{nat44 add interface address}
2071  * Use NAT44 pool address from specific interfce
2072  * To add NAT44 pool address from specific interface use:
2073  *  vpp# nat44 add interface address GigabitEthernet0/8/0
2074  * @cliexend
2075 ?*/
2076 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
2077     .path = "nat44 add interface address",
2078     .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
2079     .function = snat_add_interface_address_command_fn,
2080 };
2081
2082 /*?
2083  * @cliexpar
2084  * @cliexstart{show nat44 interface address}
2085  * Show NAT44 pool address interfaces
2086  * vpp# show nat44 interface address
2087  * NAT44 pool address interfaces:
2088  *  GigabitEthernet0/a/0
2089  * NAT44 twice-nat pool address interfaces:
2090  *  GigabitEthernet0/8/0
2091  * @cliexend
2092 ?*/
2093 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
2094   .path = "show nat44 interface address",
2095   .short_help = "show nat44 interface address",
2096   .function = nat44_show_interface_address_command_fn,
2097 };
2098
2099 /*?
2100  * @cliexpar
2101  * @cliexstart{show nat44 sessions}
2102  * Show NAT44 sessions.
2103  * @cliexend
2104 ?*/
2105 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
2106   .path = "show nat44 sessions",
2107   .short_help = "show nat44 sessions [detail]",
2108   .function = nat44_show_sessions_command_fn,
2109 };
2110
2111 /*?
2112  * @cliexpar
2113  * @cliexstart{nat44 del session}
2114  * To administratively delete NAT44 session by inside address and port use:
2115  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
2116  * To administratively delete NAT44 session by outside address and port use:
2117  *  vpp# nat44 del session out 1.0.0.3:6033 udp
2118  * @cliexend
2119 ?*/
2120 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
2121     .path = "nat44 del session",
2122     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>] [external-host <addr>:<port>]",
2123     .function = nat44_del_session_command_fn,
2124 };
2125
2126 /*?
2127  * @cliexpar
2128  * @cliexstart{nat44 forwarding}
2129  * Enable or disable forwarding
2130  * Forward packets which don't match existing translation
2131  * or static mapping instead of dropping them.
2132  * To enable forwarding, use:
2133  *  vpp# nat44 forwarding enable
2134  * To disable forwarding, use:
2135  *  vpp# nat44 forwarding disable
2136  * @cliexend
2137 ?*/
2138 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
2139   .path = "nat44 forwarding",
2140   .short_help = "nat44 forwarding enable|disable",
2141   .function = snat_forwarding_set_command_fn,
2142 };
2143
2144 /*?
2145  * @cliexpar
2146  * @cliexstart{nat44 deterministic add}
2147  * Create bijective mapping of inside address to outside address and port range
2148  * pairs, with the purpose of enabling deterministic NAT to reduce logging in
2149  * CGN deployments.
2150  * To create deterministic mapping between inside network 10.0.0.0/18 and
2151  * outside network 1.1.1.0/30 use:
2152  * # vpp# nat44 deterministic add in 10.0.0.0/18 out 1.1.1.0/30
2153  * @cliexend
2154 ?*/
2155 VLIB_CLI_COMMAND (snat_det_map_command, static) = {
2156     .path = "nat44 deterministic add",
2157     .short_help = "nat44 deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
2158     .function = snat_det_map_command_fn,
2159 };
2160
2161 /*?
2162  * @cliexpar
2163  * @cliexpstart{show nat44 deterministic mappings}
2164  * Show NAT44 deterministic mappings
2165  * vpp# show nat44 deterministic mappings
2166  * NAT44 deterministic mappings:
2167  *  in 10.0.0.0/24 out 1.1.1.1/32
2168  *   outside address sharing ratio: 256
2169  *   number of ports per inside host: 252
2170  *   sessions number: 0
2171  * @cliexend
2172 ?*/
2173 VLIB_CLI_COMMAND (nat44_det_show_mappings_command, static) = {
2174     .path = "show nat44 deterministic mappings",
2175     .short_help = "show nat44 deterministic mappings",
2176     .function = nat44_det_show_mappings_command_fn,
2177 };
2178
2179 /*?
2180  * @cliexpar
2181  * @cliexstart{nat44 deterministic forward}
2182  * Return outside address and port range from inside address for deterministic
2183  * NAT.
2184  * To obtain outside address and port of inside host use:
2185  *  vpp# nat44 deterministic forward 10.0.0.2
2186  *  1.1.1.0:<1054-1068>
2187  * @cliexend
2188 ?*/
2189 VLIB_CLI_COMMAND (snat_det_forward_command, static) = {
2190     .path = "nat44 deterministic forward",
2191     .short_help = "nat44 deterministic forward <addr>",
2192     .function = snat_det_forward_command_fn,
2193 };
2194
2195 /*?
2196  * @cliexpar
2197  * @cliexstart{nat44 deterministic reverse}
2198  * Return inside address from outside address and port for deterministic NAT.
2199  * To obtain inside host address from outside address and port use:
2200  *  #vpp nat44 deterministic reverse 1.1.1.1:1276
2201  *  10.0.16.16
2202  * @cliexend
2203 ?*/
2204 VLIB_CLI_COMMAND (snat_det_reverse_command, static) = {
2205     .path = "nat44 deterministic reverse",
2206     .short_help = "nat44 deterministic reverse <addr>:<port>",
2207     .function = snat_det_reverse_command_fn,
2208 };
2209
2210 /*?
2211  * @cliexpar
2212  * @cliexstart{show nat44 deterministic sessions}
2213  * Show NAT44 deterministic sessions.
2214  * vpp# show nat44 deterministic sessions
2215  * NAT44 deterministic sessions:
2216  *   in 10.0.0.3:3005 out 1.1.1.2:1146 external host 172.16.1.2:3006 state: udp-active expire: 306
2217  *   in 10.0.0.3:3000 out 1.1.1.2:1141 external host 172.16.1.2:3001 state: udp-active expire: 306
2218  *   in 10.0.0.4:3005 out 1.1.1.2:1177 external host 172.16.1.2:3006 state: udp-active expire: 306
2219  * @cliexend
2220 ?*/
2221 VLIB_CLI_COMMAND (nat44_det_show_sessions_command, static) = {
2222   .path = "show nat44 deterministic sessions",
2223   .short_help = "show nat44 deterministic sessions",
2224   .function = nat44_det_show_sessions_command_fn,
2225 };
2226
2227 /*?
2228  * @cliexpar
2229  * @cliexstart{nat44 deterministic close session out}
2230  * Close session using outside ip address and port
2231  * and external ip address and port, use:
2232  *  vpp# nat44 deterministic close session out 1.1.1.1:1276 2.2.2.2:2387
2233  * @cliexend
2234 ?*/
2235 VLIB_CLI_COMMAND (snat_det_close_sesion_out_command, static) = {
2236   .path = "nat44 deterministic close session out",
2237   .short_help = "nat44 deterministic close session out "
2238                 "<out_addr>:<out_port> <ext_addr>:<ext_port>",
2239   .function = snat_det_close_session_out_fn,
2240 };
2241
2242 /*?
2243  * @cliexpar
2244  * @cliexstart{nat44 deterministic close session in}
2245  * Close session using inside ip address and port
2246  * and external ip address and port, use:
2247  *  vpp# nat44 deterministic close session in 3.3.3.3:3487 2.2.2.2:2387
2248  * @cliexend
2249 ?*/
2250 VLIB_CLI_COMMAND (snat_det_close_session_in_command, static) = {
2251   .path = "nat44 deterministic close session in",
2252   .short_help = "nat44 deterministic close session in "
2253                 "<in_addr>:<in_port> <ext_addr>:<ext_port>",
2254   .function = snat_det_close_session_in_fn,
2255 };
2256
2257 /* *INDENT-ON* */
2258
2259 /*
2260  * fd.io coding-style-patch-verification: ON
2261  *
2262  * Local Variables:
2263  * eval: (c-set-style "gnu")
2264  * End:
2265  */