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