Trivial: Clean up some typos.
[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);
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);
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           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           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 nat44_show_static_mappings_command_fn (vlib_main_t * vm,
952                                        unformat_input_t * input,
953                                        vlib_cli_command_t * cmd)
954 {
955   snat_main_t *sm = &snat_main;
956   snat_static_mapping_t *m;
957   snat_static_map_resolve_t *rp;
958
959   if (sm->deterministic)
960     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
961
962   vlib_cli_output (vm, "NAT44 static mappings:");
963   /* *INDENT-OFF* */
964   pool_foreach (m, sm->static_mappings,
965   ({
966     vlib_cli_output (vm, " %U", format_snat_static_mapping, m);
967   }));
968   vec_foreach (rp, sm->to_resolve)
969     vlib_cli_output (vm, " %U", format_snat_static_map_to_resolve, rp);
970   /* *INDENT-ON* */
971
972   return 0;
973 }
974
975 static clib_error_t *
976 snat_add_interface_address_command_fn (vlib_main_t * vm,
977                                        unformat_input_t * input,
978                                        vlib_cli_command_t * cmd)
979 {
980   snat_main_t *sm = &snat_main;
981   unformat_input_t _line_input, *line_input = &_line_input;
982   u32 sw_if_index;
983   int rv;
984   int is_del = 0;
985   clib_error_t *error = 0;
986   u8 twice_nat = 0;
987
988   if (sm->deterministic)
989     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
990
991   /* Get a line of input. */
992   if (!unformat_user (input, unformat_line_input, line_input))
993     return 0;
994
995   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
996     {
997       if (unformat (line_input, "%U", unformat_vnet_sw_interface,
998                     sm->vnet_main, &sw_if_index))
999         ;
1000       else if (unformat (line_input, "twice-nat"))
1001         twice_nat = 1;
1002       else if (unformat (line_input, "del"))
1003         is_del = 1;
1004       else
1005         {
1006           error = clib_error_return (0, "unknown input '%U'",
1007                                      format_unformat_error, line_input);
1008           goto done;
1009         }
1010     }
1011
1012   rv = snat_add_interface_address (sm, sw_if_index, is_del, twice_nat);
1013
1014   switch (rv)
1015     {
1016     case 0:
1017       break;
1018
1019     default:
1020       error = clib_error_return (0, "snat_add_interface_address returned %d",
1021                                  rv);
1022       goto done;
1023     }
1024
1025 done:
1026   unformat_free (line_input);
1027
1028   return error;
1029 }
1030
1031 static clib_error_t *
1032 nat44_show_interface_address_command_fn (vlib_main_t * vm,
1033                                          unformat_input_t * input,
1034                                          vlib_cli_command_t * cmd)
1035 {
1036   snat_main_t *sm = &snat_main;
1037   vnet_main_t *vnm = vnet_get_main ();
1038   u32 *sw_if_index;
1039
1040   if (sm->deterministic)
1041     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1042
1043   /* *INDENT-OFF* */
1044   vlib_cli_output (vm, "NAT44 pool address interfaces:");
1045   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
1046     {
1047       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
1048                        *sw_if_index);
1049     }
1050   vlib_cli_output (vm, "NAT44 twice-nat pool address interfaces:");
1051   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices_twice_nat)
1052     {
1053       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
1054                        *sw_if_index);
1055     }
1056   /* *INDENT-ON* */
1057
1058   return 0;
1059 }
1060
1061 static clib_error_t *
1062 nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
1063                                 vlib_cli_command_t * cmd)
1064 {
1065   int verbose = 0;
1066   snat_main_t *sm = &snat_main;
1067   snat_main_per_thread_data_t *tsm;
1068   snat_user_t *u;
1069   int i = 0;
1070
1071   if (sm->deterministic)
1072     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1073
1074   if (unformat (input, "detail"))
1075     verbose = 1;
1076
1077   vlib_cli_output (vm, "NAT44 sessions:");
1078
1079   /* *INDENT-OFF* */
1080   vec_foreach_index (i, sm->per_thread_data)
1081     {
1082       tsm = vec_elt_at_index (sm->per_thread_data, i);
1083
1084       vlib_cli_output (vm, "-------- thread %d %s: %d sessions --------\n",
1085                        i, vlib_worker_threads[i].name,
1086                        pool_elts (tsm->sessions));
1087       pool_foreach (u, tsm->users,
1088       ({
1089         vlib_cli_output (vm, "  %U", format_snat_user, tsm, u, verbose);
1090       }));
1091     }
1092   /* *INDENT-ON* */
1093
1094   return 0;
1095 }
1096
1097 static clib_error_t *
1098 nat44_del_session_command_fn (vlib_main_t * vm,
1099                               unformat_input_t * input,
1100                               vlib_cli_command_t * cmd)
1101 {
1102   snat_main_t *sm = &snat_main;
1103   unformat_input_t _line_input, *line_input = &_line_input;
1104   int is_in = 0, is_ed = 0;
1105   clib_error_t *error = 0;
1106   ip4_address_t addr, eh_addr;
1107   u32 port = 0, eh_port = 0, vrf_id = sm->outside_vrf_id;
1108   snat_protocol_t proto;
1109   int rv;
1110
1111   if (sm->deterministic)
1112     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1113
1114   /* Get a line of input. */
1115   if (!unformat_user (input, unformat_line_input, line_input))
1116     return 0;
1117
1118   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1119     {
1120       if (unformat
1121           (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port,
1122            unformat_snat_protocol, &proto))
1123         ;
1124       else if (unformat (line_input, "in"))
1125         {
1126           is_in = 1;
1127           vrf_id = sm->inside_vrf_id;
1128         }
1129       else if (unformat (line_input, "out"))
1130         {
1131           is_in = 0;
1132           vrf_id = sm->outside_vrf_id;
1133         }
1134       else if (unformat (line_input, "vrf %u", &vrf_id))
1135         ;
1136       else
1137         if (unformat
1138             (line_input, "external-host %U:%u", unformat_ip4_address,
1139              &eh_addr, &eh_port))
1140         is_ed = 1;
1141       else
1142         {
1143           error = clib_error_return (0, "unknown input '%U'",
1144                                      format_unformat_error, line_input);
1145           goto done;
1146         }
1147     }
1148
1149   if (is_ed)
1150     rv =
1151       nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port,
1152                             snat_proto_to_ip_proto (proto), vrf_id, is_in);
1153   else
1154     rv = nat44_del_session (sm, &addr, port, proto, vrf_id, is_in);
1155
1156   switch (rv)
1157     {
1158     case 0:
1159       break;
1160
1161     default:
1162       error = clib_error_return (0, "nat44_del_session returned %d", rv);
1163       goto done;
1164     }
1165
1166 done:
1167   unformat_free (line_input);
1168
1169   return error;
1170 }
1171
1172 static clib_error_t *
1173 snat_forwarding_set_command_fn (vlib_main_t * vm,
1174                                 unformat_input_t * input,
1175                                 vlib_cli_command_t * cmd)
1176 {
1177   snat_main_t *sm = &snat_main;
1178   unformat_input_t _line_input, *line_input = &_line_input;
1179   u8 forwarding_enable;
1180   u8 forwarding_enable_set = 0;
1181   clib_error_t *error = 0;
1182
1183   if (sm->deterministic)
1184     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1185
1186   /* Get a line of input. */
1187   if (!unformat_user (input, unformat_line_input, line_input))
1188     return clib_error_return (0, "'enable' or 'disable' expected");
1189
1190   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1191     {
1192       if (!forwarding_enable_set && unformat (line_input, "enable"))
1193         {
1194           forwarding_enable = 1;
1195           forwarding_enable_set = 1;
1196         }
1197       else if (!forwarding_enable_set && unformat (line_input, "disable"))
1198         {
1199           forwarding_enable = 0;
1200           forwarding_enable_set = 1;
1201         }
1202       else
1203         {
1204           error = clib_error_return (0, "unknown input '%U'",
1205                                      format_unformat_error, line_input);
1206           goto done;
1207         }
1208     }
1209
1210   if (!forwarding_enable_set)
1211     {
1212       error = clib_error_return (0, "'enable' or 'disable' expected");
1213       goto done;
1214     }
1215
1216   sm->forwarding_enabled = forwarding_enable;
1217
1218 done:
1219   unformat_free (line_input);
1220
1221   return error;
1222 }
1223
1224 static clib_error_t *
1225 snat_det_map_command_fn (vlib_main_t * vm,
1226                          unformat_input_t * input, vlib_cli_command_t * cmd)
1227 {
1228   snat_main_t *sm = &snat_main;
1229   unformat_input_t _line_input, *line_input = &_line_input;
1230   ip4_address_t in_addr, out_addr;
1231   u32 in_plen, out_plen;
1232   int is_add = 1, rv;
1233   clib_error_t *error = 0;
1234
1235   if (!sm->deterministic)
1236     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1237
1238   /* Get a line of input. */
1239   if (!unformat_user (input, unformat_line_input, line_input))
1240     return 0;
1241
1242   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1243     {
1244       if (unformat
1245           (line_input, "in %U/%u", unformat_ip4_address, &in_addr, &in_plen))
1246         ;
1247       else
1248         if (unformat
1249             (line_input, "out %U/%u", unformat_ip4_address, &out_addr,
1250              &out_plen))
1251         ;
1252       else if (unformat (line_input, "del"))
1253         is_add = 0;
1254       else
1255         {
1256           error = clib_error_return (0, "unknown input '%U'",
1257                                      format_unformat_error, line_input);
1258           goto done;
1259         }
1260     }
1261
1262   rv = snat_det_add_map (sm, &in_addr, (u8) in_plen, &out_addr, (u8) out_plen,
1263                          is_add);
1264
1265   if (rv)
1266     {
1267       error = clib_error_return (0, "snat_det_add_map return %d", rv);
1268       goto done;
1269     }
1270
1271 done:
1272   unformat_free (line_input);
1273
1274   return error;
1275 }
1276
1277 static clib_error_t *
1278 nat44_det_show_mappings_command_fn (vlib_main_t * vm,
1279                                     unformat_input_t * input,
1280                                     vlib_cli_command_t * cmd)
1281 {
1282   snat_main_t *sm = &snat_main;
1283   snat_det_map_t *dm;
1284
1285   if (!sm->deterministic)
1286     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1287
1288   vlib_cli_output (vm, "NAT44 deterministic mappings:");
1289   /* *INDENT-OFF* */
1290   pool_foreach (dm, sm->det_maps,
1291   ({
1292     vlib_cli_output (vm, " in %U/%d out %U/%d\n",
1293                      format_ip4_address, &dm->in_addr, dm->in_plen,
1294                      format_ip4_address, &dm->out_addr, dm->out_plen);
1295     vlib_cli_output (vm, "  outside address sharing ratio: %d\n",
1296                      dm->sharing_ratio);
1297     vlib_cli_output (vm, "  number of ports per inside host: %d\n",
1298                      dm->ports_per_host);
1299     vlib_cli_output (vm, "  sessions number: %d\n", dm->ses_num);
1300   }));
1301   /* *INDENT-ON* */
1302
1303   return 0;
1304 }
1305
1306 static clib_error_t *
1307 snat_det_forward_command_fn (vlib_main_t * vm,
1308                              unformat_input_t * input,
1309                              vlib_cli_command_t * cmd)
1310 {
1311   snat_main_t *sm = &snat_main;
1312   unformat_input_t _line_input, *line_input = &_line_input;
1313   ip4_address_t in_addr, out_addr;
1314   u16 lo_port;
1315   snat_det_map_t *dm;
1316   clib_error_t *error = 0;
1317
1318   if (!sm->deterministic)
1319     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1320
1321   /* Get a line of input. */
1322   if (!unformat_user (input, unformat_line_input, line_input))
1323     return 0;
1324
1325   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1326     {
1327       if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
1328         ;
1329       else
1330         {
1331           error = clib_error_return (0, "unknown input '%U'",
1332                                      format_unformat_error, line_input);
1333           goto done;
1334         }
1335     }
1336
1337   dm = snat_det_map_by_user (sm, &in_addr);
1338   if (!dm)
1339     vlib_cli_output (vm, "no match");
1340   else
1341     {
1342       snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1343       vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
1344                        lo_port, lo_port + dm->ports_per_host - 1);
1345     }
1346
1347 done:
1348   unformat_free (line_input);
1349
1350   return error;
1351 }
1352
1353 static clib_error_t *
1354 snat_det_reverse_command_fn (vlib_main_t * vm,
1355                              unformat_input_t * input,
1356                              vlib_cli_command_t * cmd)
1357 {
1358   snat_main_t *sm = &snat_main;
1359   unformat_input_t _line_input, *line_input = &_line_input;
1360   ip4_address_t in_addr, out_addr;
1361   u32 out_port;
1362   snat_det_map_t *dm;
1363   clib_error_t *error = 0;
1364
1365   if (!sm->deterministic)
1366     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1367
1368   /* Get a line of input. */
1369   if (!unformat_user (input, unformat_line_input, line_input))
1370     return 0;
1371
1372   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1373     {
1374       if (unformat
1375           (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
1376         ;
1377       else
1378         {
1379           error = clib_error_return (0, "unknown input '%U'",
1380                                      format_unformat_error, line_input);
1381           goto done;
1382         }
1383     }
1384
1385   if (out_port < 1024 || out_port > 65535)
1386     {
1387       error = clib_error_return (0, "wrong port, must be <1024-65535>");
1388       goto done;
1389     }
1390
1391   dm = snat_det_map_by_out (sm, &out_addr);
1392   if (!dm)
1393     vlib_cli_output (vm, "no match");
1394   else
1395     {
1396       snat_det_reverse (dm, &out_addr, (u16) out_port, &in_addr);
1397       vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
1398     }
1399
1400 done:
1401   unformat_free (line_input);
1402
1403   return error;
1404 }
1405
1406 static clib_error_t *
1407 set_timeout_command_fn (vlib_main_t * vm,
1408                         unformat_input_t * input, vlib_cli_command_t * cmd)
1409 {
1410   snat_main_t *sm = &snat_main;
1411   unformat_input_t _line_input, *line_input = &_line_input;
1412   clib_error_t *error = 0;
1413
1414   /* Get a line of input. */
1415   if (!unformat_user (input, unformat_line_input, line_input))
1416     return 0;
1417
1418   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1419     {
1420       if (unformat (line_input, "udp %u", &sm->udp_timeout))
1421         {
1422           if (nat64_set_udp_timeout (sm->udp_timeout))
1423             {
1424               error = clib_error_return (0, "Invalid UDP timeout value");
1425               goto done;
1426             }
1427         }
1428       else if (unformat (line_input, "tcp-established %u",
1429                          &sm->tcp_established_timeout))
1430         {
1431           if (nat64_set_tcp_timeouts
1432               (sm->tcp_transitory_timeout, sm->tcp_established_timeout))
1433             {
1434               error =
1435                 clib_error_return (0,
1436                                    "Invalid TCP established timeouts value");
1437               goto done;
1438             }
1439         }
1440       else if (unformat (line_input, "tcp-transitory %u",
1441                          &sm->tcp_transitory_timeout))
1442         {
1443           if (nat64_set_tcp_timeouts
1444               (sm->tcp_transitory_timeout, sm->tcp_established_timeout))
1445             {
1446               error =
1447                 clib_error_return (0,
1448                                    "Invalid TCP transitory timeouts value");
1449               goto done;
1450             }
1451         }
1452       else if (unformat (line_input, "icmp %u", &sm->icmp_timeout))
1453         {
1454           if (nat64_set_icmp_timeout (sm->icmp_timeout))
1455             {
1456               error = clib_error_return (0, "Invalid ICMP timeout value");
1457               goto done;
1458             }
1459         }
1460       else if (unformat (line_input, "reset"))
1461         {
1462           sm->udp_timeout = SNAT_UDP_TIMEOUT;
1463           sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
1464           sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
1465           sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
1466           nat64_set_udp_timeout (0);
1467           nat64_set_icmp_timeout (0);
1468           nat64_set_tcp_timeouts (0, 0);
1469         }
1470       else
1471         {
1472           error = clib_error_return (0, "unknown input '%U'",
1473                                      format_unformat_error, line_input);
1474           goto done;
1475         }
1476     }
1477
1478 done:
1479   unformat_free (line_input);
1480
1481   return error;
1482 }
1483
1484 static clib_error_t *
1485 nat_show_timeouts_command_fn (vlib_main_t * vm,
1486                               unformat_input_t * input,
1487                               vlib_cli_command_t * cmd)
1488 {
1489   snat_main_t *sm = &snat_main;
1490
1491   vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
1492   vlib_cli_output (vm, "tcp-established timeout: %dsec",
1493                    sm->tcp_established_timeout);
1494   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
1495                    sm->tcp_transitory_timeout);
1496   vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
1497
1498   return 0;
1499 }
1500
1501 static clib_error_t *
1502 nat44_det_show_sessions_command_fn (vlib_main_t * vm,
1503                                     unformat_input_t * input,
1504                                     vlib_cli_command_t * cmd)
1505 {
1506   snat_main_t *sm = &snat_main;
1507   snat_det_map_t *dm;
1508   snat_det_session_t *ses;
1509   int i;
1510
1511   if (!sm->deterministic)
1512     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1513
1514   vlib_cli_output (vm, "NAT44 deterministic sessions:");
1515   /* *INDENT-OFF* */
1516   pool_foreach (dm, sm->det_maps,
1517   ({
1518     vec_foreach_index (i, dm->sessions)
1519       {
1520         ses = vec_elt_at_index (dm->sessions, i);
1521         if (ses->in_port)
1522           vlib_cli_output (vm, "  %U", format_det_map_ses, dm, ses, &i);
1523       }
1524   }));
1525   /* *INDENT-ON* */
1526   return 0;
1527 }
1528
1529 static clib_error_t *
1530 snat_det_close_session_out_fn (vlib_main_t * vm,
1531                                unformat_input_t * input,
1532                                vlib_cli_command_t * cmd)
1533 {
1534   snat_main_t *sm = &snat_main;
1535   unformat_input_t _line_input, *line_input = &_line_input;
1536   ip4_address_t out_addr, ext_addr, in_addr;
1537   u32 out_port, ext_port;
1538   snat_det_map_t *dm;
1539   snat_det_session_t *ses;
1540   snat_det_out_key_t key;
1541   clib_error_t *error = 0;
1542
1543   if (!sm->deterministic)
1544     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1545
1546   /* Get a line of input. */
1547   if (!unformat_user (input, unformat_line_input, line_input))
1548     return 0;
1549
1550   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1551     {
1552       if (unformat (line_input, "%U:%d %U:%d",
1553                     unformat_ip4_address, &out_addr, &out_port,
1554                     unformat_ip4_address, &ext_addr, &ext_port))
1555         ;
1556       else
1557         {
1558           error = clib_error_return (0, "unknown input '%U'",
1559                                      format_unformat_error, line_input);
1560           goto done;
1561         }
1562     }
1563
1564   unformat_free (line_input);
1565
1566   dm = snat_det_map_by_out (sm, &out_addr);
1567   if (!dm)
1568     vlib_cli_output (vm, "no match");
1569   else
1570     {
1571       snat_det_reverse (dm, &ext_addr, (u16) out_port, &in_addr);
1572       key.ext_host_addr = out_addr;
1573       key.ext_host_port = ntohs ((u16) ext_port);
1574       key.out_port = ntohs ((u16) out_port);
1575       ses = snat_det_get_ses_by_out (dm, &out_addr, key.as_u64);
1576       if (!ses)
1577         vlib_cli_output (vm, "no match");
1578       else
1579         snat_det_ses_close (dm, ses);
1580     }
1581
1582 done:
1583   unformat_free (line_input);
1584
1585   return error;
1586 }
1587
1588 static clib_error_t *
1589 snat_det_close_session_in_fn (vlib_main_t * vm,
1590                               unformat_input_t * input,
1591                               vlib_cli_command_t * cmd)
1592 {
1593   snat_main_t *sm = &snat_main;
1594   unformat_input_t _line_input, *line_input = &_line_input;
1595   ip4_address_t in_addr, ext_addr;
1596   u32 in_port, ext_port;
1597   snat_det_map_t *dm;
1598   snat_det_session_t *ses;
1599   snat_det_out_key_t key;
1600   clib_error_t *error = 0;
1601
1602   if (!sm->deterministic)
1603     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1604
1605   /* Get a line of input. */
1606   if (!unformat_user (input, unformat_line_input, line_input))
1607     return 0;
1608
1609   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1610     {
1611       if (unformat (line_input, "%U:%d %U:%d",
1612                     unformat_ip4_address, &in_addr, &in_port,
1613                     unformat_ip4_address, &ext_addr, &ext_port))
1614         ;
1615       else
1616         {
1617           error = clib_error_return (0, "unknown input '%U'",
1618                                      format_unformat_error, line_input);
1619           goto done;
1620         }
1621     }
1622
1623   unformat_free (line_input);
1624
1625   dm = snat_det_map_by_user (sm, &in_addr);
1626   if (!dm)
1627     vlib_cli_output (vm, "no match");
1628   else
1629     {
1630       key.ext_host_addr = ext_addr;
1631       key.ext_host_port = ntohs ((u16) ext_port);
1632       ses =
1633         snat_det_find_ses_by_in (dm, &in_addr, ntohs ((u16) in_port), key);
1634       if (!ses)
1635         vlib_cli_output (vm, "no match");
1636       else
1637         snat_det_ses_close (dm, ses);
1638     }
1639
1640 done:
1641   unformat_free (line_input);
1642
1643   return error;
1644 }
1645 /* *INDENT-OFF* */
1646
1647 /*?
1648  * @cliexpar
1649  * @cliexstart{set snat workers}
1650  * Set NAT workers if 2 or more workers available, use:
1651  *  vpp# set snat workers 0-2,5
1652  * @cliexend
1653 ?*/
1654 VLIB_CLI_COMMAND (set_workers_command, static) = {
1655   .path = "set nat workers",
1656   .function = set_workers_command_fn,
1657   .short_help = "set nat workers <workers-list>",
1658 };
1659
1660 /*?
1661  * @cliexpar
1662  * @cliexstart{show nat workers}
1663  * Show NAT workers.
1664  *  vpp# show nat workers:
1665  *  2 workers
1666  *    vpp_wk_0
1667  *    vpp_wk_1
1668  * @cliexend
1669 ?*/
1670 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
1671   .path = "show nat workers",
1672   .short_help = "show nat workers",
1673   .function = nat_show_workers_commnad_fn,
1674 };
1675
1676 /*?
1677  * @cliexpar
1678  * @cliexstart{set nat timeout}
1679  * Set values of timeouts for NAT sessions (in seconds), use:
1680  *  vpp# set nat timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90
1681  * To reset default values use:
1682  *  vpp# set nat44 deterministic timeout reset
1683  * @cliexend
1684 ?*/
1685 VLIB_CLI_COMMAND (set_timeout_command, static) = {
1686   .path = "set nat timeout",
1687   .function = set_timeout_command_fn,
1688   .short_help =
1689     "set nat timeout [udp <sec> | tcp-established <sec> "
1690     "tcp-transitory <sec> | icmp <sec> | reset]",
1691 };
1692
1693 /*?
1694  * @cliexpar
1695  * @cliexstart{show nat timeouts}
1696  * Show values of timeouts for NAT sessions.
1697  * vpp# show nat timeouts
1698  * udp timeout: 300sec
1699  * tcp-established timeout: 7440sec
1700  * tcp-transitory timeout: 240sec
1701  * icmp timeout: 60sec
1702  * @cliexend
1703 ?*/
1704 VLIB_CLI_COMMAND (nat_show_timeouts_command, static) = {
1705   .path = "show nat timeouts",
1706   .short_help = "show nat timeouts",
1707   .function = nat_show_timeouts_command_fn,
1708 };
1709
1710 /*?
1711  * @cliexpar
1712  * @cliexstart{snat ipfix logging}
1713  * To enable NAT IPFIX logging use:
1714  *  vpp# nat ipfix logging
1715  * To set IPFIX exporter use:
1716  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
1717  * @cliexend
1718 ?*/
1719 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
1720   .path = "nat ipfix logging",
1721   .function = snat_ipfix_logging_enable_disable_command_fn,
1722   .short_help = "nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
1723 };
1724
1725 /*?
1726  * @cliexpar
1727  * @cliexstart{nat addr-port-assignment-alg}
1728  * Set address and port assignment algorithm
1729  * For the MAP-E CE limit port choice based on PSID use:
1730  *  vpp# nat addr-port-assignment-alg map-e psid 10 psid-offset 6 psid-len 6
1731  * For port range use:
1732  *  vpp# nat addr-port-assignment-alg port-range <start-port> - <end-port>
1733  * To set standard (default) address and port assignment algorithm use:
1734  *  vpp# nat addr-port-assignment-alg default
1735  * @cliexend
1736 ?*/
1737 VLIB_CLI_COMMAND (nat44_set_alloc_addr_and_port_alg_command, static) = {
1738     .path = "nat addr-port-assignment-alg",
1739     .short_help = "nat addr-port-assignment-alg <alg-name> [<alg-params>]",
1740     .function = nat44_set_alloc_addr_and_port_alg_command_fn,
1741 };
1742
1743 /*?
1744  * @cliexpar
1745  * @cliexstart{show nat addr-port-assignment-alg}
1746  * Show address and port assignment algorithm
1747  * @cliexend
1748 ?*/
1749 VLIB_CLI_COMMAND (nat44_show_alloc_addr_and_port_alg_command, static) = {
1750     .path = "show nat addr-port-assignment-alg",
1751     .short_help = "show nat addr-port-assignment-alg",
1752     .function = nat44_show_alloc_addr_and_port_alg_command_fn,
1753 };
1754
1755 /*?
1756  * @cliexpar
1757  * @cliexstart{nat mss-clamping}
1758  * Set TCP MSS rewriting configuration
1759  * To enable TCP MSS rewriting use:
1760  *  vpp# nat mss-clamping 1452
1761  * To disbale TCP MSS rewriting use:
1762  *  vpp# nat mss-clamping disable
1763 ?*/
1764 VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = {
1765     .path = "nat mss-clamping",
1766     .short_help = "nat mss-clamping <mss-value>|disable",
1767     .function = nat_set_mss_clamping_command_fn,
1768 };
1769
1770 /*?
1771  * @cliexpar
1772  * @cliexstart{nat mss-clamping}
1773  * Show TCP MSS rewriting configuration
1774 ?*/
1775 VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = {
1776     .path = "show nat mss-clamping",
1777     .short_help = "show nat mss-clamping",
1778     .function = nat_show_mss_clamping_command_fn,
1779 };
1780
1781 /*?
1782  * @cliexpar
1783  * @cliexstart{show nat44 hash tables}
1784  * Show NAT44 hash tables
1785  * @cliexend
1786 ?*/
1787 VLIB_CLI_COMMAND (nat44_show_hash, static) = {
1788   .path = "show nat44 hash tables",
1789   .short_help = "show nat44 hash tables [detail|verbose]",
1790   .function = nat44_show_hash_commnad_fn,
1791 };
1792
1793 /*?
1794  * @cliexpar
1795  * @cliexstart{nat44 add address}
1796  * Add/delete NAT44 pool address.
1797  * To add NAT44 pool address use:
1798  *  vpp# nat44 add address 172.16.1.3
1799  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
1800  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
1801  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
1802  * @cliexend
1803 ?*/
1804 VLIB_CLI_COMMAND (add_address_command, static) = {
1805   .path = "nat44 add address",
1806   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
1807                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
1808   .function = add_address_command_fn,
1809 };
1810
1811 /*?
1812  * @cliexpar
1813  * @cliexstart{show nat44 addresses}
1814  * Show NAT44 pool addresses.
1815  * vpp# show nat44 addresses
1816  * NAT44 pool addresses:
1817  * 172.16.2.2
1818  *   tenant VRF independent
1819  *   10 busy udp ports
1820  *   0 busy tcp ports
1821  *   0 busy icmp ports
1822  * 172.16.1.3
1823  *   tenant VRF: 10
1824  *   0 busy udp ports
1825  *   2 busy tcp ports
1826  *   0 busy icmp ports
1827  * NAT44 twice-nat pool addresses:
1828  * 10.20.30.72
1829  *   tenant VRF independent
1830  *   0 busy udp ports
1831  *   0 busy tcp ports
1832  *   0 busy icmp ports
1833  * @cliexend
1834 ?*/
1835 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
1836   .path = "show nat44 addresses",
1837   .short_help = "show nat44 addresses",
1838   .function = nat44_show_addresses_command_fn,
1839 };
1840
1841 /*?
1842  * @cliexpar
1843  * @cliexstart{set interface nat44}
1844  * Enable/disable NAT44 feature on the interface.
1845  * To enable NAT44 feature with local network interface use:
1846  *  vpp# set interface nat44 in GigabitEthernet0/8/0
1847  * To enable NAT44 feature with external network interface use:
1848  *  vpp# set interface nat44 out GigabitEthernet0/a/0
1849  * @cliexend
1850 ?*/
1851 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
1852   .path = "set interface nat44",
1853   .function = snat_feature_command_fn,
1854   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
1855                 "[del]",
1856 };
1857
1858 /*?
1859  * @cliexpar
1860  * @cliexstart{show nat44 interfaces}
1861  * Show interfaces with NAT44 feature.
1862  * vpp# show nat44 interfaces
1863  * NAT44 interfaces:
1864  *  GigabitEthernet0/8/0 in
1865  *  GigabitEthernet0/a/0 out
1866  * @cliexend
1867 ?*/
1868 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
1869   .path = "show nat44 interfaces",
1870   .short_help = "show nat44 interfaces",
1871   .function = nat44_show_interfaces_command_fn,
1872 };
1873
1874 /*?
1875  * @cliexpar
1876  * @cliexstart{nat44 add static mapping}
1877  * Static mapping allows hosts on the external network to initiate connection
1878  * to to the local network host.
1879  * To create static mapping between local host address 10.0.0.3 port 6303 and
1880  * external address 4.4.4.4 port 3606 for TCP protocol use:
1881  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
1882  * If not runnig "static mapping only" NAT plugin mode use before:
1883  *  vpp# nat44 add address 4.4.4.4
1884  * To create static mapping between local and external address use:
1885  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
1886  * @cliexend
1887 ?*/
1888 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
1889   .path = "nat44 add static mapping",
1890   .function = add_static_mapping_command_fn,
1891   .short_help =
1892     "nat44 add static mapping tcp|udp|icmp local <addr> [<port>] "
1893     "external <addr> [<port>] [vrf <table-id>] [twice-nat|self-twice-nat] "
1894     "[out2in-only] [del]",
1895 };
1896
1897 /*?
1898  * @cliexpar
1899  * @cliexstart{nat44 add identity mapping}
1900  * Identity mapping translate an IP address to itself.
1901  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
1902  * use:
1903  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
1904  * To create identity mapping for address 10.0.0.3 use:
1905  *  vpp# nat44 add identity mapping 10.0.0.3
1906  * To create identity mapping for DHCP addressed interface use:
1907  *  vpp# nat44 add identity mapping GigabitEthernet0/a/0 tcp 3606
1908  * @cliexend
1909 ?*/
1910 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
1911   .path = "nat44 add identity mapping",
1912   .function = add_identity_mapping_command_fn,
1913   .short_help = "nat44 add identity mapping <interface>|<ip4-addr> "
1914     "[<protocol> <port>] [vrf <table-id>] [del]",
1915 };
1916
1917 /*?
1918  * @cliexpar
1919  * @cliexstart{nat44 add load-balancing static mapping}
1920  * Service load balancing using NAT44
1921  * To add static mapping with load balancing for service with external IP
1922  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
1923  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
1924  *  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
1925  * @cliexend
1926 ?*/
1927 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
1928   .path = "nat44 add load-balancing static mapping",
1929   .function = add_lb_static_mapping_command_fn,
1930   .short_help =
1931     "nat44 add load-balancing static mapping protocol tcp|udp "
1932     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
1933     "probability <n> [twice-nat|self-twice-nat] [out2in-only] "
1934     "[affinity <timeout-seconds>] [del]",
1935 };
1936
1937 /*?
1938  * @cliexpar
1939  * @cliexstart{show nat44 static mappings}
1940  * Show NAT44 static mappings.
1941  * vpp# show nat44 static mappings
1942  * NAT44 static mappings:
1943  *  local 10.0.0.3 external 4.4.4.4 vrf 0
1944  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
1945  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
1946  *   local 10.100.10.10:8080 probability 80
1947  *   local 10.100.10.20:8080 probability 20
1948  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
1949  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
1950  * @cliexend
1951 ?*/
1952 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
1953   .path = "show nat44 static mappings",
1954   .short_help = "show nat44 static mappings",
1955   .function = nat44_show_static_mappings_command_fn,
1956 };
1957
1958 /*?
1959  * @cliexpar
1960  * @cliexstart{nat44 add interface address}
1961  * Use NAT44 pool address from specific interfce
1962  * To add NAT44 pool address from specific interface use:
1963  *  vpp# nat44 add interface address GigabitEthernet0/8/0
1964  * @cliexend
1965 ?*/
1966 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
1967     .path = "nat44 add interface address",
1968     .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
1969     .function = snat_add_interface_address_command_fn,
1970 };
1971
1972 /*?
1973  * @cliexpar
1974  * @cliexstart{show nat44 interface address}
1975  * Show NAT44 pool address interfaces
1976  * vpp# show nat44 interface address
1977  * NAT44 pool address interfaces:
1978  *  GigabitEthernet0/a/0
1979  * NAT44 twice-nat pool address interfaces:
1980  *  GigabitEthernet0/8/0
1981  * @cliexend
1982 ?*/
1983 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
1984   .path = "show nat44 interface address",
1985   .short_help = "show nat44 interface address",
1986   .function = nat44_show_interface_address_command_fn,
1987 };
1988
1989 /*?
1990  * @cliexpar
1991  * @cliexstart{show nat44 sessions}
1992  * Show NAT44 sessions.
1993  * @cliexend
1994 ?*/
1995 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
1996   .path = "show nat44 sessions",
1997   .short_help = "show nat44 sessions [detail]",
1998   .function = nat44_show_sessions_command_fn,
1999 };
2000
2001 /*?
2002  * @cliexpar
2003  * @cliexstart{nat44 del session}
2004  * To administratively delete NAT44 session by inside address and port use:
2005  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
2006  * To administratively delete NAT44 session by outside address and port use:
2007  *  vpp# nat44 del session out 1.0.0.3:6033 udp
2008  * @cliexend
2009 ?*/
2010 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
2011     .path = "nat44 del session",
2012     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>] [external-host <addr>:<port>]",
2013     .function = nat44_del_session_command_fn,
2014 };
2015
2016 /*?
2017  * @cliexpar
2018  * @cliexstart{nat44 forwarding}
2019  * Enable or disable forwarding
2020  * Forward packets which don't match existing translation
2021  * or static mapping instead of dropping them.
2022  * To enable forwarding, use:
2023  *  vpp# nat44 forwarding enable
2024  * To disable forwarding, use:
2025  *  vpp# nat44 forwarding disable
2026  * @cliexend
2027 ?*/
2028 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
2029   .path = "nat44 forwarding",
2030   .short_help = "nat44 forwarding enable|disable",
2031   .function = snat_forwarding_set_command_fn,
2032 };
2033
2034 /*?
2035  * @cliexpar
2036  * @cliexstart{nat44 deterministic add}
2037  * Create bijective mapping of inside address to outside address and port range
2038  * pairs, with the purpose of enabling deterministic NAT to reduce logging in
2039  * CGN deployments.
2040  * To create deterministic mapping between inside network 10.0.0.0/18 and
2041  * outside network 1.1.1.0/30 use:
2042  * # vpp# nat44 deterministic add in 10.0.0.0/18 out 1.1.1.0/30
2043  * @cliexend
2044 ?*/
2045 VLIB_CLI_COMMAND (snat_det_map_command, static) = {
2046     .path = "nat44 deterministic add",
2047     .short_help = "nat44 deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
2048     .function = snat_det_map_command_fn,
2049 };
2050
2051 /*?
2052  * @cliexpar
2053  * @cliexpstart{show nat44 deterministic mappings}
2054  * Show NAT44 deterministic mappings
2055  * vpp# show nat44 deterministic mappings
2056  * NAT44 deterministic mappings:
2057  *  in 10.0.0.0/24 out 1.1.1.1/32
2058  *   outside address sharing ratio: 256
2059  *   number of ports per inside host: 252
2060  *   sessions number: 0
2061  * @cliexend
2062 ?*/
2063 VLIB_CLI_COMMAND (nat44_det_show_mappings_command, static) = {
2064     .path = "show nat44 deterministic mappings",
2065     .short_help = "show nat44 deterministic mappings",
2066     .function = nat44_det_show_mappings_command_fn,
2067 };
2068
2069 /*?
2070  * @cliexpar
2071  * @cliexstart{nat44 deterministic forward}
2072  * Return outside address and port range from inside address for deterministic
2073  * NAT.
2074  * To obtain outside address and port of inside host use:
2075  *  vpp# nat44 deterministic forward 10.0.0.2
2076  *  1.1.1.0:<1054-1068>
2077  * @cliexend
2078 ?*/
2079 VLIB_CLI_COMMAND (snat_det_forward_command, static) = {
2080     .path = "nat44 deterministic forward",
2081     .short_help = "nat44 deterministic forward <addr>",
2082     .function = snat_det_forward_command_fn,
2083 };
2084
2085 /*?
2086  * @cliexpar
2087  * @cliexstart{nat44 deterministic reverse}
2088  * Return inside address from outside address and port for deterministic NAT.
2089  * To obtain inside host address from outside address and port use:
2090  *  #vpp nat44 deterministic reverse 1.1.1.1:1276
2091  *  10.0.16.16
2092  * @cliexend
2093 ?*/
2094 VLIB_CLI_COMMAND (snat_det_reverse_command, static) = {
2095     .path = "nat44 deterministic reverse",
2096     .short_help = "nat44 deterministic reverse <addr>:<port>",
2097     .function = snat_det_reverse_command_fn,
2098 };
2099
2100 /*?
2101  * @cliexpar
2102  * @cliexstart{show nat44 deterministic sessions}
2103  * Show NAT44 deterministic sessions.
2104  * vpp# show nat44 deterministic sessions
2105  * NAT44 deterministic sessions:
2106  *   in 10.0.0.3:3005 out 1.1.1.2:1146 external host 172.16.1.2:3006 state: udp-active expire: 306
2107  *   in 10.0.0.3:3000 out 1.1.1.2:1141 external host 172.16.1.2:3001 state: udp-active expire: 306
2108  *   in 10.0.0.4:3005 out 1.1.1.2:1177 external host 172.16.1.2:3006 state: udp-active expire: 306
2109  * @cliexend
2110 ?*/
2111 VLIB_CLI_COMMAND (nat44_det_show_sessions_command, static) = {
2112   .path = "show nat44 deterministic sessions",
2113   .short_help = "show nat44 deterministic sessions",
2114   .function = nat44_det_show_sessions_command_fn,
2115 };
2116
2117 /*?
2118  * @cliexpar
2119  * @cliexstart{nat44 deterministic close session out}
2120  * Close session using outside ip address and port
2121  * and external ip address and port, use:
2122  *  vpp# nat44 deterministic close session out 1.1.1.1:1276 2.2.2.2:2387
2123  * @cliexend
2124 ?*/
2125 VLIB_CLI_COMMAND (snat_det_close_sesion_out_command, static) = {
2126   .path = "nat44 deterministic close session out",
2127   .short_help = "nat44 deterministic close session out "
2128                 "<out_addr>:<out_port> <ext_addr>:<ext_port>",
2129   .function = snat_det_close_session_out_fn,
2130 };
2131
2132 /*?
2133  * @cliexpar
2134  * @cliexstart{nat44 deterministic close session in}
2135  * Close session using inside ip address and port
2136  * and external ip address and port, use:
2137  *  vpp# nat44 deterministic close session in 3.3.3.3:3487 2.2.2.2:2387
2138  * @cliexend
2139 ?*/
2140 VLIB_CLI_COMMAND (snat_det_close_session_in_command, static) = {
2141   .path = "nat44 deterministic close session in",
2142   .short_help = "nat44 deterministic close session in "
2143                 "<in_addr>:<in_port> <ext_addr>:<ext_port>",
2144   .function = snat_det_close_session_in_fn,
2145 };
2146
2147 /* *INDENT-ON* */
2148
2149 /*
2150  * fd.io coding-style-patch-verification: ON
2151  *
2152  * Local Variables:
2153  * eval: (c-set-style "gnu")
2154  * End:
2155  */