c73cffa85b25e8d06cb4a63cb105c357a23e8ad4
[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/nat44/inlines.h>
26 #include <nat/nat_affinity.h>
27 #include <vnet/fib/fib_table.h>
28 #include <nat/nat_ha.h>
29
30
31 #define UNSUPPORTED_IN_DET_OR_ED_MODE_STR \
32   "This command is unsupported in deterministic or endpoint dependent mode"
33 #define UNSUPPORTED_IN_DET_OR_NON_ED_MODE_STR \
34   "This command is unsupported in deterministic or non endpoint dependent mode"
35 #define UNSUPPORTED_IN_DET_MODE_STR \
36   "This command is unsupported in deterministic mode"
37 #define SUPPORTED_ONLY_IN_ED_MODE_STR \
38   "This command is supported only in endpoint dependent mode"
39 #define SUPPORTED_ONLY_IN_DET_MODE_STR \
40   "This command is supported only in deterministic mode"
41
42 static clib_error_t *
43 set_workers_command_fn (vlib_main_t * vm,
44                         unformat_input_t * input, vlib_cli_command_t * cmd)
45 {
46   unformat_input_t _line_input, *line_input = &_line_input;
47   snat_main_t *sm = &snat_main;
48   uword *bitmap = 0;
49   int rv = 0;
50   clib_error_t *error = 0;
51
52   if (sm->deterministic)
53     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
54
55   /* Get a line of input. */
56   if (!unformat_user (input, unformat_line_input, line_input))
57     return 0;
58
59   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
60     {
61       if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap))
62         ;
63       else
64         {
65           error = clib_error_return (0, "unknown input '%U'",
66                                      format_unformat_error, line_input);
67           goto done;
68         }
69     }
70
71   if (bitmap == 0)
72     {
73       error = clib_error_return (0, "List of workers must be specified.");
74       goto done;
75     }
76
77   rv = snat_set_workers (bitmap);
78
79   clib_bitmap_free (bitmap);
80
81   switch (rv)
82     {
83     case VNET_API_ERROR_INVALID_WORKER:
84       error = clib_error_return (0, "Invalid worker(s).");
85       goto done;
86     case VNET_API_ERROR_FEATURE_DISABLED:
87       error = clib_error_return (0,
88                                  "Supported only if 2 or more workes available.");
89       goto done;
90     default:
91       break;
92     }
93
94 done:
95   unformat_free (line_input);
96
97   return error;
98 }
99
100 static clib_error_t *
101 nat_show_workers_commnad_fn (vlib_main_t * vm, unformat_input_t * input,
102                              vlib_cli_command_t * cmd)
103 {
104   snat_main_t *sm = &snat_main;
105   u32 *worker;
106
107   if (sm->deterministic)
108     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
109
110   if (sm->num_workers > 1)
111     {
112       vlib_cli_output (vm, "%d workers", vec_len (sm->workers));
113       /* *INDENT-OFF* */
114       vec_foreach (worker, sm->workers)
115         {
116           vlib_worker_thread_t *w =
117             vlib_worker_threads + *worker + sm->first_worker_index;
118           vlib_cli_output (vm, "  %s", w->name);
119         }
120       /* *INDENT-ON* */
121     }
122
123   return 0;
124 }
125
126 static clib_error_t *
127 snat_set_log_level_command_fn (vlib_main_t * vm,
128                                unformat_input_t * input,
129                                vlib_cli_command_t * cmd)
130 {
131   unformat_input_t _line_input, *line_input = &_line_input;
132   snat_main_t *sm = &snat_main;
133   u8 log_level = SNAT_LOG_NONE;
134   clib_error_t *error = 0;
135
136   /* Get a line of input. */
137   if (!unformat_user (input, unformat_line_input, line_input))
138     return 0;
139
140   if (!unformat (line_input, "%d", &log_level))
141     {
142       error = clib_error_return (0, "unknown input '%U'",
143                                  format_unformat_error, line_input);
144       goto done;
145     }
146   if (log_level > SNAT_LOG_DEBUG)
147     {
148       error = clib_error_return (0, "unknown logging level '%d'", log_level);
149       goto done;
150     }
151   sm->log_level = log_level;
152
153 done:
154   unformat_free (line_input);
155
156   return error;
157 }
158
159 static clib_error_t *
160 snat_ipfix_logging_enable_disable_command_fn (vlib_main_t * vm,
161                                               unformat_input_t * input,
162                                               vlib_cli_command_t * cmd)
163 {
164   unformat_input_t _line_input, *line_input = &_line_input;
165   u32 domain_id = 0;
166   u32 src_port = 0;
167   u8 enable = 1;
168   int rv = 0;
169   clib_error_t *error = 0;
170
171   /* Get a line of input. */
172   if (!unformat_user (input, unformat_line_input, line_input))
173     {
174       rv = snat_ipfix_logging_enable_disable (enable, domain_id,
175                                               (u16) src_port);
176       if (rv)
177         return clib_error_return (0, "ipfix logging enable failed");
178       return 0;
179     }
180
181   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
182     {
183       if (unformat (line_input, "domain %d", &domain_id))
184         ;
185       else if (unformat (line_input, "src-port %d", &src_port))
186         ;
187       else if (unformat (line_input, "disable"))
188         enable = 0;
189       else
190         {
191           error = clib_error_return (0, "unknown input '%U'",
192                                      format_unformat_error, line_input);
193           goto done;
194         }
195     }
196
197   rv = snat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port);
198
199   if (rv)
200     {
201       error = clib_error_return (0, "ipfix logging enable failed");
202       goto done;
203     }
204
205 done:
206   unformat_free (line_input);
207
208   return error;
209 }
210
211 static clib_error_t *
212 nat44_show_hash_command_fn (vlib_main_t * vm, unformat_input_t * input,
213                             vlib_cli_command_t * cmd)
214 {
215   snat_main_t *sm = &snat_main;
216   snat_main_per_thread_data_t *tsm;
217   nat_affinity_main_t *nam = &nat_affinity_main;
218   int i;
219   int verbose = 0;
220
221   if (unformat (input, "detail"))
222     verbose = 1;
223   else if (unformat (input, "verbose"))
224     verbose = 2;
225
226   vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->static_mapping_by_local,
227                    verbose);
228   vlib_cli_output (vm, "%U",
229                    format_bihash_8_8, &sm->static_mapping_by_external,
230                    verbose);
231   vlib_cli_output (vm, "%U", format_bihash_16_8, &sm->out2in_ed, verbose);
232   vec_foreach_index (i, sm->per_thread_data)
233   {
234     tsm = vec_elt_at_index (sm->per_thread_data, i);
235     vlib_cli_output (vm, "-------- thread %d %s --------\n",
236                      i, vlib_worker_threads[i].name);
237     if (sm->endpoint_dependent)
238       {
239         vlib_cli_output (vm, "%U", format_bihash_16_8, &tsm->in2out_ed,
240                          verbose);
241       }
242     else
243       {
244         vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->in2out, verbose);
245         vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->out2in, verbose);
246       }
247     vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->user_hash, verbose);
248   }
249
250   if (sm->endpoint_dependent)
251     {
252       vlib_cli_output (vm, "%U", format_bihash_16_8, &nam->affinity_hash,
253                        verbose);
254     }
255
256   vlib_cli_output (vm, "-------- hash table parameters --------\n");
257   vlib_cli_output (vm, "translation buckets: %u", sm->translation_buckets);
258   vlib_cli_output (vm, "translation memory size: %U",
259                    format_memory_size, sm->translation_memory_size);
260   if (!sm->endpoint_dependent)
261     {
262       vlib_cli_output (vm, "user buckets: %u", sm->user_buckets);
263       vlib_cli_output (vm, "user memory size: %U",
264                        format_memory_size, sm->user_memory_size);
265     }
266   return 0;
267 }
268
269 static clib_error_t *
270 nat44_set_alloc_addr_and_port_alg_command_fn (vlib_main_t * vm,
271                                               unformat_input_t * input,
272                                               vlib_cli_command_t * cmd)
273 {
274   unformat_input_t _line_input, *line_input = &_line_input;
275   snat_main_t *sm = &snat_main;
276   clib_error_t *error = 0;
277   u32 psid, psid_offset, psid_length, port_start, port_end;
278
279   if (sm->deterministic)
280     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
281
282   /* Get a line of input. */
283   if (!unformat_user (input, unformat_line_input, line_input))
284     return 0;
285
286   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
287     {
288       if (unformat (line_input, "default"))
289         nat_set_alloc_addr_and_port_default ();
290       else
291         if (unformat
292             (line_input, "map-e psid %d psid-offset %d psid-len %d", &psid,
293              &psid_offset, &psid_length))
294         nat_set_alloc_addr_and_port_mape ((u16) psid, (u16) psid_offset,
295                                           (u16) psid_length);
296       else
297         if (unformat
298             (line_input, "port-range %d - %d", &port_start, &port_end))
299         {
300           if (port_end <= port_start)
301             {
302               error =
303                 clib_error_return (0,
304                                    "The end-port must be greater than start-port");
305               goto done;
306             }
307           nat_set_alloc_addr_and_port_range ((u16) port_start,
308                                              (u16) port_end);
309         }
310       else
311         {
312           error = clib_error_return (0, "unknown input '%U'",
313                                      format_unformat_error, line_input);
314           goto done;
315         }
316     }
317
318 done:
319   unformat_free (line_input);
320
321   return error;
322 };
323
324 static clib_error_t *
325 nat44_show_alloc_addr_and_port_alg_command_fn (vlib_main_t * vm,
326                                                unformat_input_t * input,
327                                                vlib_cli_command_t * cmd)
328 {
329   snat_main_t *sm = &snat_main;
330
331   if (sm->deterministic)
332     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
333
334   vlib_cli_output (vm, "NAT address and port: %U",
335                    format_nat_addr_and_port_alloc_alg,
336                    sm->addr_and_port_alloc_alg);
337   switch (sm->addr_and_port_alloc_alg)
338     {
339     case NAT_ADDR_AND_PORT_ALLOC_ALG_MAPE:
340       vlib_cli_output (vm, "  psid %d psid-offset %d psid-len %d", sm->psid,
341                        sm->psid_offset, sm->psid_length);
342       break;
343     case NAT_ADDR_AND_PORT_ALLOC_ALG_RANGE:
344       vlib_cli_output (vm, "  start-port %d end-port %d", sm->start_port,
345                        sm->end_port);
346       break;
347     default:
348       break;
349     }
350
351   return 0;
352 }
353
354 static clib_error_t *
355 nat_set_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input,
356                                  vlib_cli_command_t * cmd)
357 {
358   unformat_input_t _line_input, *line_input = &_line_input;
359   snat_main_t *sm = &snat_main;
360   clib_error_t *error = 0;
361   u32 mss;
362
363   /* Get a line of input. */
364   if (!unformat_user (input, unformat_line_input, line_input))
365     return 0;
366
367   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
368     {
369       if (unformat (line_input, "disable"))
370         sm->mss_clamping = 0;
371       else if (unformat (line_input, "%d", &mss))
372         sm->mss_clamping = (u16) mss;
373       else
374         {
375           error = clib_error_return (0, "unknown input '%U'",
376                                      format_unformat_error, line_input);
377           goto done;
378         }
379     }
380
381 done:
382   unformat_free (line_input);
383
384   return error;
385 }
386
387 static clib_error_t *
388 nat_show_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input,
389                                   vlib_cli_command_t * cmd)
390 {
391   snat_main_t *sm = &snat_main;
392
393   if (sm->mss_clamping)
394     vlib_cli_output (vm, "mss-clamping %d", sm->mss_clamping);
395   else
396     vlib_cli_output (vm, "mss-clamping disabled");
397
398   return 0;
399 }
400
401 static clib_error_t *
402 nat_ha_failover_command_fn (vlib_main_t * vm, unformat_input_t * input,
403                             vlib_cli_command_t * cmd)
404 {
405   unformat_input_t _line_input, *line_input = &_line_input;
406   ip4_address_t addr;
407   u32 port, session_refresh_interval = 10;
408   int rv;
409   clib_error_t *error = 0;
410
411   /* Get a line of input. */
412   if (!unformat_user (input, unformat_line_input, line_input))
413     return 0;
414
415   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
416     {
417       if (unformat (line_input, "%U:%u", unformat_ip4_address, &addr, &port))
418         ;
419       else
420         if (unformat
421             (line_input, "refresh-interval %u", &session_refresh_interval))
422         ;
423       else
424         {
425           error = clib_error_return (0, "unknown input '%U'",
426                                      format_unformat_error, line_input);
427           goto done;
428         }
429     }
430
431   rv = nat_ha_set_failover (&addr, (u16) port, session_refresh_interval);
432   if (rv)
433     error = clib_error_return (0, "set HA failover failed");
434
435 done:
436   unformat_free (line_input);
437
438   return error;
439 }
440
441 static clib_error_t *
442 nat_ha_listener_command_fn (vlib_main_t * vm, unformat_input_t * input,
443                             vlib_cli_command_t * cmd)
444 {
445   unformat_input_t _line_input, *line_input = &_line_input;
446   ip4_address_t addr;
447   u32 port, path_mtu = 512;
448   int rv;
449   clib_error_t *error = 0;
450
451   /* Get a line of input. */
452   if (!unformat_user (input, unformat_line_input, line_input))
453     return 0;
454
455   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
456     {
457       if (unformat (line_input, "%U:%u", unformat_ip4_address, &addr, &port))
458         ;
459       else if (unformat (line_input, "path-mtu %u", &path_mtu))
460         ;
461       else
462         {
463           error = clib_error_return (0, "unknown input '%U'",
464                                      format_unformat_error, line_input);
465           goto done;
466         }
467     }
468
469   rv = nat_ha_set_listener (&addr, (u16) port, path_mtu);
470   if (rv)
471     error = clib_error_return (0, "set HA listener failed");
472
473 done:
474   unformat_free (line_input);
475
476   return error;
477 }
478
479 static clib_error_t *
480 nat_show_ha_command_fn (vlib_main_t * vm, unformat_input_t * input,
481                         vlib_cli_command_t * cmd)
482 {
483   ip4_address_t addr;
484   u16 port;
485   u32 path_mtu, session_refresh_interval, resync_ack_missed;
486   u8 in_resync;
487
488   nat_ha_get_listener (&addr, &port, &path_mtu);
489   if (!port)
490     {
491       vlib_cli_output (vm, "NAT HA disabled\n");
492       return 0;
493     }
494
495   vlib_cli_output (vm, "LISTENER:\n");
496   vlib_cli_output (vm, "  %U:%u path-mtu %u\n",
497                    format_ip4_address, &addr, port, path_mtu);
498
499   nat_ha_get_failover (&addr, &port, &session_refresh_interval);
500   vlib_cli_output (vm, "FAILOVER:\n");
501   if (port)
502     vlib_cli_output (vm, "  %U:%u refresh-interval %usec\n",
503                      format_ip4_address, &addr, port,
504                      session_refresh_interval);
505   else
506     vlib_cli_output (vm, "  NA\n");
507
508   nat_ha_get_resync_status (&in_resync, &resync_ack_missed);
509   vlib_cli_output (vm, "RESYNC:\n");
510   if (in_resync)
511     vlib_cli_output (vm, "  in progress\n");
512   else
513     vlib_cli_output (vm, "  completed (%d ACK missed)\n", resync_ack_missed);
514
515   return 0;
516 }
517
518 static clib_error_t *
519 nat_ha_flush_command_fn (vlib_main_t * vm, unformat_input_t * input,
520                          vlib_cli_command_t * cmd)
521 {
522   nat_ha_flush (0);
523   return 0;
524 }
525
526 static clib_error_t *
527 nat_ha_resync_command_fn (vlib_main_t * vm, unformat_input_t * input,
528                           vlib_cli_command_t * cmd)
529 {
530   clib_error_t *error = 0;
531
532   if (nat_ha_resync (0, 0, 0))
533     error = clib_error_return (0, "NAT HA resync already running");
534
535   return error;
536 }
537
538 static clib_error_t *
539 add_address_command_fn (vlib_main_t * vm,
540                         unformat_input_t * input, vlib_cli_command_t * cmd)
541 {
542   unformat_input_t _line_input, *line_input = &_line_input;
543   snat_main_t *sm = &snat_main;
544   ip4_address_t start_addr, end_addr, this_addr;
545   u32 start_host_order, end_host_order;
546   u32 vrf_id = ~0;
547   int i, count;
548   int is_add = 1;
549   int rv = 0;
550   clib_error_t *error = 0;
551   u8 twice_nat = 0;
552
553   if (sm->deterministic)
554     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
555
556   /* Get a line of input. */
557   if (!unformat_user (input, unformat_line_input, line_input))
558     return 0;
559
560   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
561     {
562       if (unformat (line_input, "%U - %U",
563                     unformat_ip4_address, &start_addr,
564                     unformat_ip4_address, &end_addr))
565         ;
566       else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
567         ;
568       else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
569         end_addr = start_addr;
570       else if (unformat (line_input, "twice-nat"))
571         twice_nat = 1;
572       else if (unformat (line_input, "del"))
573         is_add = 0;
574       else
575         {
576           error = clib_error_return (0, "unknown input '%U'",
577                                      format_unformat_error, line_input);
578           goto done;
579         }
580     }
581
582   if (sm->static_mapping_only)
583     {
584       error = clib_error_return (0, "static mapping only mode");
585       goto done;
586     }
587
588   start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
589   end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
590
591   if (end_host_order < start_host_order)
592     {
593       error = clib_error_return (0, "end address less than start address");
594       goto done;
595     }
596
597   count = (end_host_order - start_host_order) + 1;
598
599   if (count > 1024)
600     nat_log_info ("%U - %U, %d addresses...",
601                   format_ip4_address, &start_addr,
602                   format_ip4_address, &end_addr, count);
603
604   this_addr = start_addr;
605
606   for (i = 0; i < count; i++)
607     {
608       if (is_add)
609         rv = snat_add_address (sm, &this_addr, vrf_id, twice_nat);
610       else
611         rv = snat_del_address (sm, this_addr, 0, twice_nat);
612
613       switch (rv)
614         {
615         case VNET_API_ERROR_VALUE_EXIST:
616           error = clib_error_return (0, "NAT address already in use.");
617           goto done;
618         case VNET_API_ERROR_NO_SUCH_ENTRY:
619           error = clib_error_return (0, "NAT address not exist.");
620           goto done;
621         case VNET_API_ERROR_UNSPECIFIED:
622           error =
623             clib_error_return (0, "NAT address used in static mapping.");
624           goto done;
625         case VNET_API_ERROR_FEATURE_DISABLED:
626           error =
627             clib_error_return (0,
628                                "twice NAT available only for endpoint-dependent mode.");
629           goto done;
630         default:
631           break;
632         }
633
634       if (sm->out2in_dpo)
635         nat44_add_del_address_dpo (this_addr, is_add);
636
637       increment_v4_address (&this_addr);
638     }
639
640 done:
641   unformat_free (line_input);
642
643   return error;
644 }
645
646 static clib_error_t *
647 nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
648                                vlib_cli_command_t * cmd)
649 {
650   snat_main_per_thread_data_t *tsm;
651   snat_main_t *sm = &snat_main;
652   snat_session_t *s;
653
654   if (sm->deterministic || !sm->endpoint_dependent)
655     return clib_error_return (0, UNSUPPORTED_IN_DET_OR_NON_ED_MODE_STR);
656
657   vlib_cli_output (vm, "max translations per thread: %u",
658                    sm->max_translations_per_thread);
659   vlib_cli_output (vm, "max translations per user: %u",
660                    sm->max_translations_per_user);
661
662   u32 count = 0;
663
664   u64 now = vlib_time_now (vm);
665   u64 sess_timeout_time;
666
667   u32 udp_sessions = 0;
668   u32 tcp_sessions = 0;
669   u32 icmp_sessions = 0;
670
671   u32 timed_out = 0;
672   u32 transitory = 0;
673   u32 transitory_wait_closed = 0;
674   u32 transitory_closed = 0;
675   u32 established = 0;
676
677   if (sm->num_workers > 1)
678     {
679       /* *INDENT-OFF* */
680       vec_foreach (tsm, sm->per_thread_data)
681         {
682           pool_foreach (s, tsm->sessions,
683           ({
684             sess_timeout_time = s->last_heard +
685               (f64) nat44_session_get_timeout (sm, s);
686             if (now >= sess_timeout_time)
687               timed_out++;
688
689             switch (s->nat_proto)
690               {
691               case NAT_PROTOCOL_ICMP:
692                 icmp_sessions++;
693                 break;
694               case NAT_PROTOCOL_TCP:
695                 tcp_sessions++;
696                 if (s->state)
697                   {
698                     if (s->tcp_closed_timestamp)
699                       {
700                         if (now >= s->tcp_closed_timestamp)
701                           {
702                             ++transitory_closed;
703                           }
704                         else
705                           {
706                             ++transitory_wait_closed;
707                           }
708                       }
709                     transitory++;
710                   }
711                 else
712                   established++;
713                 break;
714               case NAT_PROTOCOL_UDP:
715               default:
716                 udp_sessions++;
717                 break;
718               }
719           }));
720           count += pool_elts (tsm->sessions);
721         }
722       /* *INDENT-ON* */
723     }
724   else
725     {
726       tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
727       /* *INDENT-OFF* */
728       pool_foreach (s, tsm->sessions,
729       ({
730         sess_timeout_time = s->last_heard +
731             (f64) nat44_session_get_timeout (sm, s);
732         if (now >= sess_timeout_time)
733           timed_out++;
734
735         switch (s->nat_proto)
736           {
737           case NAT_PROTOCOL_ICMP:
738             icmp_sessions++;
739             break;
740           case NAT_PROTOCOL_TCP:
741             tcp_sessions++;
742             if (s->state)
743               {
744                 if (s->tcp_closed_timestamp)
745                   {
746                     if (now >= s->tcp_closed_timestamp)
747                       {
748                         ++transitory_closed;
749                       }
750                     else
751                       {
752                         ++transitory_wait_closed;
753                       }
754                   }
755                 transitory++;
756               }
757             else
758               established++;
759             break;
760           case NAT_PROTOCOL_UDP:
761           default:
762             udp_sessions++;
763             break;
764           }
765       }));
766       /* *INDENT-ON* */
767       count = pool_elts (tsm->sessions);
768       if (sm->endpoint_dependent)
769         {
770           dlist_elt_t *oldest_elt;
771           u32 oldest_index;
772 #define _(n, d)                                                          \
773   oldest_index =                                                         \
774       clib_dlist_remove_head (tsm->lru_pool, tsm->n##_lru_head_index);   \
775   if (~0 != oldest_index)                                                \
776     {                                                                    \
777       oldest_elt = pool_elt_at_index (tsm->lru_pool, oldest_index);      \
778       s = pool_elt_at_index (tsm->sessions, oldest_elt->value);          \
779       sess_timeout_time =                                                \
780           s->last_heard + (f64)nat44_session_get_timeout (sm, s);        \
781       vlib_cli_output (vm, d " LRU min session timeout %llu (now %llu)", \
782                        sess_timeout_time, now);                          \
783       clib_dlist_addhead (tsm->lru_pool, tsm->n##_lru_head_index,        \
784                           oldest_index);                                 \
785     }
786           _(tcp_estab, "established tcp");
787           _(tcp_trans, "transitory tcp");
788           _(udp, "udp");
789           _(unk_proto, "unknown protocol");
790           _(icmp, "icmp");
791 #undef _
792         }
793     }
794
795   vlib_cli_output (vm, "total timed out sessions: %u", timed_out);
796   vlib_cli_output (vm, "total sessions: %u", count);
797   vlib_cli_output (vm, "total tcp sessions: %u", tcp_sessions);
798   vlib_cli_output (vm, "total tcp established sessions: %u", established);
799   vlib_cli_output (vm, "total tcp transitory sessions: %u", transitory);
800   vlib_cli_output (vm, "total tcp transitory (WAIT-CLOSED) sessions: %u",
801                    transitory_wait_closed);
802   vlib_cli_output (vm, "total tcp transitory (CLOSED) sessions: %u",
803                    transitory_closed);
804   vlib_cli_output (vm, "total udp sessions: %u", udp_sessions);
805   vlib_cli_output (vm, "total icmp sessions: %u", icmp_sessions);
806   return 0;
807 }
808
809 static clib_error_t *
810 nat44_show_addresses_command_fn (vlib_main_t * vm, unformat_input_t * input,
811                                  vlib_cli_command_t * cmd)
812 {
813   snat_main_t *sm = &snat_main;
814   snat_address_t *ap;
815
816   if (sm->deterministic)
817     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
818
819   vlib_cli_output (vm, "NAT44 pool addresses:");
820   /* *INDENT-OFF* */
821   vec_foreach (ap, sm->addresses)
822     {
823       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
824       if (ap->fib_index != ~0)
825           vlib_cli_output (vm, "  tenant VRF: %u",
826             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
827       else
828         vlib_cli_output (vm, "  tenant VRF independent");
829     #define _(N, i, n, s) \
830       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
831       foreach_nat_protocol
832     #undef _
833     }
834   vlib_cli_output (vm, "NAT44 twice-nat pool addresses:");
835   vec_foreach (ap, sm->twice_nat_addresses)
836     {
837       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
838       if (ap->fib_index != ~0)
839           vlib_cli_output (vm, "  tenant VRF: %u",
840             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
841       else
842         vlib_cli_output (vm, "  tenant VRF independent");
843     #define _(N, i, n, s) \
844       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
845       foreach_nat_protocol
846     #undef _
847     }
848   /* *INDENT-ON* */
849   return 0;
850 }
851
852 static clib_error_t *
853 snat_feature_command_fn (vlib_main_t * vm,
854                          unformat_input_t * input, vlib_cli_command_t * cmd)
855 {
856   unformat_input_t _line_input, *line_input = &_line_input;
857   vnet_main_t *vnm = vnet_get_main ();
858   clib_error_t *error = 0;
859   u32 sw_if_index;
860   u32 *inside_sw_if_indices = 0;
861   u32 *outside_sw_if_indices = 0;
862   u8 is_output_feature = 0;
863   int is_del = 0;
864   int i;
865
866   sw_if_index = ~0;
867
868   /* Get a line of input. */
869   if (!unformat_user (input, unformat_line_input, line_input))
870     return 0;
871
872   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
873     {
874       if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
875                     vnm, &sw_if_index))
876         vec_add1 (inside_sw_if_indices, sw_if_index);
877       else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
878                          vnm, &sw_if_index))
879         vec_add1 (outside_sw_if_indices, sw_if_index);
880       else if (unformat (line_input, "output-feature"))
881         is_output_feature = 1;
882       else if (unformat (line_input, "del"))
883         is_del = 1;
884       else
885         {
886           error = clib_error_return (0, "unknown input '%U'",
887                                      format_unformat_error, line_input);
888           goto done;
889         }
890     }
891
892   if (vec_len (inside_sw_if_indices))
893     {
894       for (i = 0; i < vec_len (inside_sw_if_indices); i++)
895         {
896           sw_if_index = inside_sw_if_indices[i];
897           if (is_output_feature)
898             {
899               if (snat_interface_add_del_output_feature
900                   (sw_if_index, 1, is_del))
901                 {
902                   error = clib_error_return (0, "%s %U failed",
903                                              is_del ? "del" : "add",
904                                              format_vnet_sw_if_index_name,
905                                              vnm, sw_if_index);
906                   goto done;
907                 }
908             }
909           else
910             {
911               if (snat_interface_add_del (sw_if_index, 1, is_del))
912                 {
913                   error = clib_error_return (0, "%s %U failed",
914                                              is_del ? "del" : "add",
915                                              format_vnet_sw_if_index_name,
916                                              vnm, sw_if_index);
917                   goto done;
918                 }
919             }
920         }
921     }
922
923   if (vec_len (outside_sw_if_indices))
924     {
925       for (i = 0; i < vec_len (outside_sw_if_indices); i++)
926         {
927           sw_if_index = outside_sw_if_indices[i];
928           if (is_output_feature)
929             {
930               if (snat_interface_add_del_output_feature
931                   (sw_if_index, 0, is_del))
932                 {
933                   error = clib_error_return (0, "%s %U failed",
934                                              is_del ? "del" : "add",
935                                              format_vnet_sw_if_index_name,
936                                              vnm, sw_if_index);
937                   goto done;
938                 }
939             }
940           else
941             {
942               if (snat_interface_add_del (sw_if_index, 0, is_del))
943                 {
944                   error = clib_error_return (0, "%s %U failed",
945                                              is_del ? "del" : "add",
946                                              format_vnet_sw_if_index_name,
947                                              vnm, sw_if_index);
948                   goto done;
949                 }
950             }
951         }
952     }
953
954 done:
955   unformat_free (line_input);
956   vec_free (inside_sw_if_indices);
957   vec_free (outside_sw_if_indices);
958
959   return error;
960 }
961
962 static clib_error_t *
963 nat44_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
964                                   vlib_cli_command_t * cmd)
965 {
966   snat_main_t *sm = &snat_main;
967   snat_interface_t *i;
968   vnet_main_t *vnm = vnet_get_main ();
969
970   vlib_cli_output (vm, "NAT44 interfaces:");
971   /* *INDENT-OFF* */
972   pool_foreach (i, sm->interfaces,
973   ({
974     vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
975                      i->sw_if_index,
976                      (nat_interface_is_inside(i) &&
977                       nat_interface_is_outside(i)) ? "in out" :
978                      (nat_interface_is_inside(i) ? "in" : "out"));
979   }));
980
981   pool_foreach (i, sm->output_feature_interfaces,
982   ({
983     vlib_cli_output (vm, " %U output-feature %s",
984                      format_vnet_sw_if_index_name, vnm,
985                      i->sw_if_index,
986                      (nat_interface_is_inside(i) &&
987                       nat_interface_is_outside(i)) ? "in out" :
988                      (nat_interface_is_inside(i) ? "in" : "out"));
989   }));
990   /* *INDENT-ON* */
991
992   return 0;
993 }
994
995 static clib_error_t *
996 add_static_mapping_command_fn (vlib_main_t * vm,
997                                unformat_input_t * input,
998                                vlib_cli_command_t * cmd)
999 {
1000   unformat_input_t _line_input, *line_input = &_line_input;
1001   snat_main_t *sm = &snat_main;
1002   clib_error_t *error = 0;
1003   ip4_address_t l_addr, e_addr;
1004   u32 l_port = 0, e_port = 0, vrf_id = ~0;
1005   int is_add = 1;
1006   int addr_only = 1;
1007   u32 sw_if_index = ~0;
1008   vnet_main_t *vnm = vnet_get_main ();
1009   int rv;
1010   nat_protocol_t proto = NAT_PROTOCOL_OTHER;
1011   u8 proto_set = 0;
1012   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1013   u8 out2in_only = 0;
1014
1015   if (sm->deterministic)
1016     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1017
1018   /* Get a line of input. */
1019   if (!unformat_user (input, unformat_line_input, line_input))
1020     return 0;
1021
1022   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1023     {
1024       if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
1025                     &l_port))
1026         addr_only = 0;
1027       else
1028         if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr))
1029         ;
1030       else if (unformat (line_input, "external %U %u", unformat_ip4_address,
1031                          &e_addr, &e_port))
1032         addr_only = 0;
1033       else if (unformat (line_input, "external %U", unformat_ip4_address,
1034                          &e_addr))
1035         ;
1036       else if (unformat (line_input, "external %U %u",
1037                          unformat_vnet_sw_interface, vnm, &sw_if_index,
1038                          &e_port))
1039         addr_only = 0;
1040
1041       else if (unformat (line_input, "external %U",
1042                          unformat_vnet_sw_interface, vnm, &sw_if_index))
1043         ;
1044       else if (unformat (line_input, "vrf %u", &vrf_id))
1045         ;
1046       else if (unformat (line_input, "%U", unformat_nat_protocol, &proto))
1047         proto_set = 1;
1048       else if (unformat (line_input, "twice-nat"))
1049         twice_nat = TWICE_NAT;
1050       else if (unformat (line_input, "self-twice-nat"))
1051         twice_nat = TWICE_NAT_SELF;
1052       else if (unformat (line_input, "out2in-only"))
1053         out2in_only = 1;
1054       else if (unformat (line_input, "del"))
1055         is_add = 0;
1056       else
1057         {
1058           error = clib_error_return (0, "unknown input: '%U'",
1059                                      format_unformat_error, line_input);
1060           goto done;
1061         }
1062     }
1063
1064   if (twice_nat && addr_only)
1065     {
1066       error = clib_error_return (0, "twice NAT only for 1:1 NAPT");
1067       goto done;
1068     }
1069
1070   if (addr_only)
1071     {
1072       if (proto_set)
1073         {
1074           error =
1075             clib_error_return (0,
1076                                "address only mapping doesn't support protocol");
1077           goto done;
1078         }
1079     }
1080   else if (!proto_set)
1081     {
1082       error = clib_error_return (0, "protocol is required");
1083       goto done;
1084     }
1085
1086   rv = snat_add_static_mapping (l_addr, e_addr, clib_host_to_net_u16 (l_port),
1087                                 clib_host_to_net_u16 (e_port),
1088                                 vrf_id, addr_only, sw_if_index, proto, is_add,
1089                                 twice_nat, out2in_only, 0, 0);
1090
1091   switch (rv)
1092     {
1093     case VNET_API_ERROR_INVALID_VALUE:
1094       error = clib_error_return (0, "External port already in use.");
1095       goto done;
1096     case VNET_API_ERROR_NO_SUCH_ENTRY:
1097       if (is_add)
1098         error = clib_error_return (0, "External address must be allocated.");
1099       else
1100         error = clib_error_return (0, "Mapping not exist.");
1101       goto done;
1102     case VNET_API_ERROR_NO_SUCH_FIB:
1103       error = clib_error_return (0, "No such VRF id.");
1104       goto done;
1105     case VNET_API_ERROR_VALUE_EXIST:
1106       error = clib_error_return (0, "Mapping already exist.");
1107       goto done;
1108     case VNET_API_ERROR_FEATURE_DISABLED:
1109       error =
1110         clib_error_return (0,
1111                            "twice-nat/out2in-only available only for endpoint-dependent mode.");
1112       goto done;
1113     default:
1114       break;
1115     }
1116
1117 done:
1118   unformat_free (line_input);
1119
1120   return error;
1121 }
1122
1123 static clib_error_t *
1124 add_identity_mapping_command_fn (vlib_main_t * vm,
1125                                  unformat_input_t * input,
1126                                  vlib_cli_command_t * cmd)
1127 {
1128   unformat_input_t _line_input, *line_input = &_line_input;
1129   snat_main_t *sm = &snat_main;
1130   clib_error_t *error = 0;
1131   ip4_address_t addr;
1132   u32 port = 0, vrf_id = ~0;
1133   int is_add = 1;
1134   int addr_only = 1;
1135   u32 sw_if_index = ~0;
1136   vnet_main_t *vnm = vnet_get_main ();
1137   int rv;
1138   nat_protocol_t proto;
1139
1140   if (sm->deterministic)
1141     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1142
1143   addr.as_u32 = 0;
1144
1145   /* Get a line of input. */
1146   if (!unformat_user (input, unformat_line_input, line_input))
1147     return 0;
1148
1149   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1150     {
1151       if (unformat (line_input, "%U", unformat_ip4_address, &addr))
1152         ;
1153       else if (unformat (line_input, "external %U",
1154                          unformat_vnet_sw_interface, vnm, &sw_if_index))
1155         ;
1156       else if (unformat (line_input, "vrf %u", &vrf_id))
1157         ;
1158       else if (unformat (line_input, "%U %u", unformat_nat_protocol, &proto,
1159                          &port))
1160         addr_only = 0;
1161       else if (unformat (line_input, "del"))
1162         is_add = 0;
1163       else
1164         {
1165           error = clib_error_return (0, "unknown input: '%U'",
1166                                      format_unformat_error, line_input);
1167           goto done;
1168         }
1169     }
1170
1171   rv =
1172     snat_add_static_mapping (addr, addr, clib_host_to_net_u16 (port),
1173                              clib_host_to_net_u16 (port), vrf_id, addr_only,
1174                              sw_if_index, proto, is_add, 0, 0, 0, 1);
1175
1176   switch (rv)
1177     {
1178     case VNET_API_ERROR_INVALID_VALUE:
1179       error = clib_error_return (0, "External port already in use.");
1180       goto done;
1181     case VNET_API_ERROR_NO_SUCH_ENTRY:
1182       if (is_add)
1183         error = clib_error_return (0, "External address must be allocated.");
1184       else
1185         error = clib_error_return (0, "Mapping not exist.");
1186       goto done;
1187     case VNET_API_ERROR_NO_SUCH_FIB:
1188       error = clib_error_return (0, "No such VRF id.");
1189       goto done;
1190     case VNET_API_ERROR_VALUE_EXIST:
1191       error = clib_error_return (0, "Mapping already exist.");
1192       goto done;
1193     default:
1194       break;
1195     }
1196
1197 done:
1198   unformat_free (line_input);
1199
1200   return error;
1201 }
1202
1203 static clib_error_t *
1204 add_lb_static_mapping_command_fn (vlib_main_t * vm,
1205                                   unformat_input_t * input,
1206                                   vlib_cli_command_t * cmd)
1207 {
1208   unformat_input_t _line_input, *line_input = &_line_input;
1209   snat_main_t *sm = &snat_main;
1210   clib_error_t *error = 0;
1211   ip4_address_t l_addr, e_addr;
1212   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0, affinity = 0;
1213   int is_add = 1;
1214   int rv;
1215   nat_protocol_t proto;
1216   u8 proto_set = 0;
1217   nat44_lb_addr_port_t *locals = 0, local;
1218   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1219   u8 out2in_only = 0;
1220
1221   if (sm->deterministic)
1222     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1223
1224   /* Get a line of input. */
1225   if (!unformat_user (input, unformat_line_input, line_input))
1226     return 0;
1227
1228   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1229     {
1230       if (unformat (line_input, "local %U:%u probability %u",
1231                     unformat_ip4_address, &l_addr, &l_port, &probability))
1232         {
1233           clib_memset (&local, 0, sizeof (local));
1234           local.addr = l_addr;
1235           local.port = (u16) l_port;
1236           local.probability = (u8) probability;
1237           vec_add1 (locals, local);
1238         }
1239       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
1240                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
1241                          &probability))
1242         {
1243           clib_memset (&local, 0, sizeof (local));
1244           local.addr = l_addr;
1245           local.port = (u16) l_port;
1246           local.probability = (u8) probability;
1247           local.vrf_id = vrf_id;
1248           vec_add1 (locals, local);
1249         }
1250       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
1251                          &e_addr, &e_port))
1252         ;
1253       else if (unformat (line_input, "protocol %U", unformat_nat_protocol,
1254                          &proto))
1255         proto_set = 1;
1256       else if (unformat (line_input, "twice-nat"))
1257         twice_nat = TWICE_NAT;
1258       else if (unformat (line_input, "self-twice-nat"))
1259         twice_nat = TWICE_NAT_SELF;
1260       else if (unformat (line_input, "out2in-only"))
1261         out2in_only = 1;
1262       else if (unformat (line_input, "del"))
1263         is_add = 0;
1264       else if (unformat (line_input, "affinity %u", &affinity))
1265         ;
1266       else
1267         {
1268           error = clib_error_return (0, "unknown input: '%U'",
1269                                      format_unformat_error, line_input);
1270           goto done;
1271         }
1272     }
1273
1274   if (vec_len (locals) < 2)
1275     {
1276       error = clib_error_return (0, "at least two local must be set");
1277       goto done;
1278     }
1279
1280   if (!proto_set)
1281     {
1282       error = clib_error_return (0, "missing protocol");
1283       goto done;
1284     }
1285
1286   rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, locals,
1287                                         is_add, twice_nat, out2in_only, 0,
1288                                         affinity);
1289
1290   switch (rv)
1291     {
1292     case VNET_API_ERROR_INVALID_VALUE:
1293       error = clib_error_return (0, "External port already in use.");
1294       goto done;
1295     case VNET_API_ERROR_NO_SUCH_ENTRY:
1296       if (is_add)
1297         error = clib_error_return (0, "External address must be allocated.");
1298       else
1299         error = clib_error_return (0, "Mapping not exist.");
1300       goto done;
1301     case VNET_API_ERROR_VALUE_EXIST:
1302       error = clib_error_return (0, "Mapping already exist.");
1303       goto done;
1304     case VNET_API_ERROR_FEATURE_DISABLED:
1305       error =
1306         clib_error_return (0, "Available only for endpoint-dependent mode.");
1307       goto done;
1308     default:
1309       break;
1310     }
1311
1312 done:
1313   unformat_free (line_input);
1314   vec_free (locals);
1315
1316   return error;
1317 }
1318
1319 static clib_error_t *
1320 add_lb_backend_command_fn (vlib_main_t * vm,
1321                            unformat_input_t * input, vlib_cli_command_t * cmd)
1322 {
1323   unformat_input_t _line_input, *line_input = &_line_input;
1324   snat_main_t *sm = &snat_main;
1325   clib_error_t *error = 0;
1326   ip4_address_t l_addr, e_addr;
1327   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0;
1328   int is_add = 1;
1329   int rv;
1330   nat_protocol_t proto;
1331   u8 proto_set = 0;
1332
1333   if (sm->deterministic)
1334     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1335
1336   /* Get a line of input. */
1337   if (!unformat_user (input, unformat_line_input, line_input))
1338     return 0;
1339
1340   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1341     {
1342       if (unformat (line_input, "local %U:%u probability %u",
1343                     unformat_ip4_address, &l_addr, &l_port, &probability))
1344         ;
1345       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
1346                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
1347                          &probability))
1348         ;
1349       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
1350                          &e_addr, &e_port))
1351         ;
1352       else if (unformat (line_input, "protocol %U", unformat_nat_protocol,
1353                          &proto))
1354         proto_set = 1;
1355       else if (unformat (line_input, "del"))
1356         is_add = 0;
1357       else
1358         {
1359           error = clib_error_return (0, "unknown input: '%U'",
1360                                      format_unformat_error, line_input);
1361           goto done;
1362         }
1363     }
1364
1365   if (!l_port || !e_port)
1366     {
1367       error = clib_error_return (0, "local or external must be set");
1368       goto done;
1369     }
1370
1371   if (!proto_set)
1372     {
1373       error = clib_error_return (0, "missing protocol");
1374       goto done;
1375     }
1376
1377   rv =
1378     nat44_lb_static_mapping_add_del_local (e_addr, (u16) e_port, l_addr,
1379                                            l_port, proto, vrf_id, probability,
1380                                            is_add);
1381
1382   switch (rv)
1383     {
1384     case VNET_API_ERROR_INVALID_VALUE:
1385       error = clib_error_return (0, "External is not load-balancing static "
1386                                  "mapping.");
1387       goto done;
1388     case VNET_API_ERROR_NO_SUCH_ENTRY:
1389       error = clib_error_return (0, "Mapping or back-end not exist.");
1390       goto done;
1391     case VNET_API_ERROR_VALUE_EXIST:
1392       error = clib_error_return (0, "Back-end already exist.");
1393       goto done;
1394     case VNET_API_ERROR_FEATURE_DISABLED:
1395       error =
1396         clib_error_return (0, "Available only for endpoint-dependent mode.");
1397       goto done;
1398     case VNET_API_ERROR_UNSPECIFIED:
1399       error = clib_error_return (0, "At least two back-ends must remain");
1400       goto done;
1401     default:
1402       break;
1403     }
1404
1405 done:
1406   unformat_free (line_input);
1407
1408   return error;
1409 }
1410
1411 static clib_error_t *
1412 nat44_show_static_mappings_command_fn (vlib_main_t * vm,
1413                                        unformat_input_t * input,
1414                                        vlib_cli_command_t * cmd)
1415 {
1416   snat_main_t *sm = &snat_main;
1417   snat_static_mapping_t *m;
1418   snat_static_map_resolve_t *rp;
1419
1420   if (sm->deterministic)
1421     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1422
1423   vlib_cli_output (vm, "NAT44 static mappings:");
1424   /* *INDENT-OFF* */
1425   pool_foreach (m, sm->static_mappings,
1426   ({
1427     vlib_cli_output (vm, " %U", format_snat_static_mapping, m);
1428   }));
1429   vec_foreach (rp, sm->to_resolve)
1430     vlib_cli_output (vm, " %U", format_snat_static_map_to_resolve, rp);
1431   /* *INDENT-ON* */
1432
1433   return 0;
1434 }
1435
1436 static clib_error_t *
1437 snat_add_interface_address_command_fn (vlib_main_t * vm,
1438                                        unformat_input_t * input,
1439                                        vlib_cli_command_t * cmd)
1440 {
1441   snat_main_t *sm = &snat_main;
1442   unformat_input_t _line_input, *line_input = &_line_input;
1443   u32 sw_if_index;
1444   int rv;
1445   int is_del = 0;
1446   clib_error_t *error = 0;
1447   u8 twice_nat = 0;
1448
1449   if (sm->deterministic)
1450     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1451
1452   /* Get a line of input. */
1453   if (!unformat_user (input, unformat_line_input, line_input))
1454     return 0;
1455
1456   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1457     {
1458       if (unformat (line_input, "%U", unformat_vnet_sw_interface,
1459                     sm->vnet_main, &sw_if_index))
1460         ;
1461       else if (unformat (line_input, "twice-nat"))
1462         twice_nat = 1;
1463       else if (unformat (line_input, "del"))
1464         is_del = 1;
1465       else
1466         {
1467           error = clib_error_return (0, "unknown input '%U'",
1468                                      format_unformat_error, line_input);
1469           goto done;
1470         }
1471     }
1472
1473   rv = snat_add_interface_address (sm, sw_if_index, is_del, twice_nat);
1474
1475   switch (rv)
1476     {
1477     case 0:
1478       break;
1479
1480     default:
1481       error = clib_error_return (0, "snat_add_interface_address returned %d",
1482                                  rv);
1483       goto done;
1484     }
1485
1486 done:
1487   unformat_free (line_input);
1488
1489   return error;
1490 }
1491
1492 static clib_error_t *
1493 nat44_show_interface_address_command_fn (vlib_main_t * vm,
1494                                          unformat_input_t * input,
1495                                          vlib_cli_command_t * cmd)
1496 {
1497   snat_main_t *sm = &snat_main;
1498   vnet_main_t *vnm = vnet_get_main ();
1499   u32 *sw_if_index;
1500
1501   if (sm->deterministic)
1502     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1503
1504   /* *INDENT-OFF* */
1505   vlib_cli_output (vm, "NAT44 pool address interfaces:");
1506   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
1507     {
1508       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
1509                        *sw_if_index);
1510     }
1511   vlib_cli_output (vm, "NAT44 twice-nat pool address interfaces:");
1512   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices_twice_nat)
1513     {
1514       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
1515                        *sw_if_index);
1516     }
1517   /* *INDENT-ON* */
1518
1519   return 0;
1520 }
1521
1522 static clib_error_t *
1523 nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
1524                                 vlib_cli_command_t * cmd)
1525 {
1526   unformat_input_t _line_input, *line_input = &_line_input;
1527   clib_error_t *error = 0;
1528
1529   snat_main_per_thread_data_t *tsm;
1530   snat_main_t *sm = &snat_main;
1531
1532   int detail = 0;
1533   int i = 0;
1534
1535   if (sm->deterministic)
1536     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1537
1538   if (!unformat_user (input, unformat_line_input, line_input))
1539     goto print;
1540
1541   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1542     {
1543       if (unformat (line_input, "detail"))
1544         detail = 1;
1545       else
1546         {
1547           error = clib_error_return (0, "unknown input '%U'",
1548                                      format_unformat_error, line_input);
1549           break;
1550         }
1551     }
1552   unformat_free (line_input);
1553
1554 print:
1555   if (!sm->endpoint_dependent)
1556     vlib_cli_output (vm, "NAT44 sessions:");
1557   else
1558     vlib_cli_output (vm, "NAT44 ED sessions:");
1559
1560   /* *INDENT-OFF* */
1561   vec_foreach_index (i, sm->per_thread_data)
1562     {
1563       tsm = vec_elt_at_index (sm->per_thread_data, i);
1564
1565       vlib_cli_output (vm, "-------- thread %d %s: %d sessions --------\n",
1566                        i, vlib_worker_threads[i].name,
1567                        pool_elts (tsm->sessions));
1568
1569       if (!sm->endpoint_dependent)
1570         {
1571           snat_user_t *u;
1572           pool_foreach (u, tsm->users,
1573           ({
1574             vlib_cli_output (vm, "  %U", format_snat_user, tsm, u, detail);
1575           }));
1576         }
1577       else
1578         {
1579           snat_session_t *s;
1580           pool_foreach (s, tsm->sessions,
1581           ({
1582             vlib_cli_output (vm, "  %U\n", format_snat_session, tsm, s);
1583           }));
1584         }
1585     }
1586   /* *INDENT-ON* */
1587   return error;
1588 }
1589
1590 static clib_error_t *
1591 nat44_set_session_limit_command_fn (vlib_main_t * vm,
1592                                     unformat_input_t * input,
1593                                     vlib_cli_command_t * cmd)
1594 {
1595   snat_main_t *sm = &snat_main;
1596   unformat_input_t _line_input, *line_input = &_line_input;
1597   clib_error_t *error = 0;
1598
1599   u32 session_limit = 0, vrf_id = 0;
1600
1601   if (sm->deterministic)
1602     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1603
1604   /* Get a line of input. */
1605   if (!unformat_user (input, unformat_line_input, line_input))
1606     return 0;
1607
1608   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1609     {
1610       if (unformat (line_input, "%u", &session_limit))
1611         ;
1612       else if (unformat (line_input, "vrf %u", &vrf_id))
1613         ;
1614       else
1615         {
1616           error = clib_error_return (0, "unknown input '%U'",
1617                                      format_unformat_error, line_input);
1618           goto done;
1619         }
1620     }
1621
1622   if (!session_limit)
1623     error = clib_error_return (0, "missing value of session limit");
1624   else if (nat44_set_session_limit (session_limit, vrf_id))
1625     error = clib_error_return (0, "nat44_set_session_limit failed");
1626
1627 done:
1628   unformat_free (line_input);
1629
1630   return error;
1631 }
1632
1633 static clib_error_t *
1634 nat44_del_user_command_fn (vlib_main_t * vm,
1635                            unformat_input_t * input, vlib_cli_command_t * cmd)
1636 {
1637   snat_main_t *sm = &snat_main;
1638   unformat_input_t _line_input, *line_input = &_line_input;
1639   clib_error_t *error = 0;
1640   ip4_address_t addr;
1641   u32 fib_index = 0;
1642   int rv;
1643
1644   if (sm->deterministic || sm->endpoint_dependent)
1645     return clib_error_return (0, UNSUPPORTED_IN_DET_OR_ED_MODE_STR);
1646
1647   /* Get a line of input. */
1648   if (!unformat_user (input, unformat_line_input, line_input))
1649     return 0;
1650
1651   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1652     {
1653       if (unformat (line_input, "%U", unformat_ip4_address, &addr))
1654         ;
1655       else if (unformat (line_input, "fib %u", &fib_index))
1656         ;
1657       else
1658         {
1659           error = clib_error_return (0, "unknown input '%U'",
1660                                      format_unformat_error, line_input);
1661           goto done;
1662         }
1663     }
1664
1665   rv = nat44_user_del (&addr, fib_index);
1666
1667   if (!rv)
1668     {
1669       error = clib_error_return (0, "nat44_user_del returned %d", rv);
1670     }
1671
1672 done:
1673   unformat_free (line_input);
1674
1675   return error;
1676 }
1677
1678 static clib_error_t *
1679 nat44_clear_sessions_command_fn (vlib_main_t * vm,
1680                                  unformat_input_t * input,
1681                                  vlib_cli_command_t * cmd)
1682 {
1683   snat_main_t *sm = &snat_main;
1684   clib_error_t *error = 0;
1685
1686   if (sm->deterministic)
1687     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1688
1689   nat44_sessions_clear ();
1690   return error;
1691 }
1692
1693 static clib_error_t *
1694 nat44_del_session_command_fn (vlib_main_t * vm,
1695                               unformat_input_t * input,
1696                               vlib_cli_command_t * cmd)
1697 {
1698   snat_main_t *sm = &snat_main;
1699   unformat_input_t _line_input, *line_input = &_line_input;
1700   int is_in = 0, is_ed = 0;
1701   clib_error_t *error = 0;
1702   ip4_address_t addr, eh_addr;
1703   u32 port = 0, eh_port = 0, vrf_id = sm->outside_vrf_id;
1704   nat_protocol_t proto;
1705   int rv;
1706
1707   if (sm->deterministic)
1708     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1709
1710   /* Get a line of input. */
1711   if (!unformat_user (input, unformat_line_input, line_input))
1712     return 0;
1713
1714   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1715     {
1716       if (unformat
1717           (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port,
1718            unformat_nat_protocol, &proto))
1719         ;
1720       else if (unformat (line_input, "in"))
1721         {
1722           is_in = 1;
1723           vrf_id = sm->inside_vrf_id;
1724         }
1725       else if (unformat (line_input, "out"))
1726         {
1727           is_in = 0;
1728           vrf_id = sm->outside_vrf_id;
1729         }
1730       else if (unformat (line_input, "vrf %u", &vrf_id))
1731         ;
1732       else
1733         if (unformat
1734             (line_input, "external-host %U:%u", unformat_ip4_address,
1735              &eh_addr, &eh_port))
1736         is_ed = 1;
1737       else
1738         {
1739           error = clib_error_return (0, "unknown input '%U'",
1740                                      format_unformat_error, line_input);
1741           goto done;
1742         }
1743     }
1744
1745   if (is_ed)
1746     rv =
1747       nat44_del_ed_session (sm, &addr, clib_host_to_net_u16 (port), &eh_addr,
1748                             clib_host_to_net_u16 (eh_port),
1749                             nat_proto_to_ip_proto (proto), vrf_id, is_in);
1750   else
1751     rv =
1752       nat44_del_session (sm, &addr, clib_host_to_net_u16 (port), proto,
1753                          vrf_id, is_in);
1754
1755   switch (rv)
1756     {
1757     case 0:
1758       break;
1759
1760     default:
1761       error = clib_error_return (0, "nat44_del_session returned %d", rv);
1762       goto done;
1763     }
1764
1765 done:
1766   unformat_free (line_input);
1767
1768   return error;
1769 }
1770
1771 static clib_error_t *
1772 snat_forwarding_set_command_fn (vlib_main_t * vm,
1773                                 unformat_input_t * input,
1774                                 vlib_cli_command_t * cmd)
1775 {
1776   snat_main_t *sm = &snat_main;
1777   unformat_input_t _line_input, *line_input = &_line_input;
1778   u8 forwarding_enable;
1779   u8 forwarding_enable_set = 0;
1780   clib_error_t *error = 0;
1781
1782   if (sm->deterministic)
1783     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1784
1785   /* Get a line of input. */
1786   if (!unformat_user (input, unformat_line_input, line_input))
1787     return clib_error_return (0, "'enable' or 'disable' expected");
1788
1789   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1790     {
1791       if (!forwarding_enable_set && unformat (line_input, "enable"))
1792         {
1793           forwarding_enable = 1;
1794           forwarding_enable_set = 1;
1795         }
1796       else if (!forwarding_enable_set && unformat (line_input, "disable"))
1797         {
1798           forwarding_enable = 0;
1799           forwarding_enable_set = 1;
1800         }
1801       else
1802         {
1803           error = clib_error_return (0, "unknown input '%U'",
1804                                      format_unformat_error, line_input);
1805           goto done;
1806         }
1807     }
1808
1809   if (!forwarding_enable_set)
1810     {
1811       error = clib_error_return (0, "'enable' or 'disable' expected");
1812       goto done;
1813     }
1814
1815   sm->forwarding_enabled = forwarding_enable;
1816
1817 done:
1818   unformat_free (line_input);
1819
1820   return error;
1821 }
1822
1823 static clib_error_t *
1824 snat_det_map_command_fn (vlib_main_t * vm,
1825                          unformat_input_t * input, vlib_cli_command_t * cmd)
1826 {
1827   snat_main_t *sm = &snat_main;
1828   unformat_input_t _line_input, *line_input = &_line_input;
1829   ip4_address_t in_addr, out_addr;
1830   u32 in_plen, out_plen;
1831   int is_add = 1, rv;
1832   clib_error_t *error = 0;
1833
1834   if (!sm->deterministic)
1835     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1836
1837   /* Get a line of input. */
1838   if (!unformat_user (input, unformat_line_input, line_input))
1839     return 0;
1840
1841   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1842     {
1843       if (unformat
1844           (line_input, "in %U/%u", unformat_ip4_address, &in_addr, &in_plen))
1845         ;
1846       else
1847         if (unformat
1848             (line_input, "out %U/%u", unformat_ip4_address, &out_addr,
1849              &out_plen))
1850         ;
1851       else if (unformat (line_input, "del"))
1852         is_add = 0;
1853       else
1854         {
1855           error = clib_error_return (0, "unknown input '%U'",
1856                                      format_unformat_error, line_input);
1857           goto done;
1858         }
1859     }
1860
1861   rv = snat_det_add_map (sm, &in_addr, (u8) in_plen, &out_addr, (u8) out_plen,
1862                          is_add);
1863
1864   if (rv)
1865     {
1866       error = clib_error_return (0, "snat_det_add_map return %d", rv);
1867       goto done;
1868     }
1869
1870 done:
1871   unformat_free (line_input);
1872
1873   return error;
1874 }
1875
1876 static clib_error_t *
1877 nat44_det_show_mappings_command_fn (vlib_main_t * vm,
1878                                     unformat_input_t * input,
1879                                     vlib_cli_command_t * cmd)
1880 {
1881   snat_main_t *sm = &snat_main;
1882   snat_det_map_t *dm;
1883
1884   if (!sm->deterministic)
1885     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1886
1887   vlib_cli_output (vm, "NAT44 deterministic mappings:");
1888   /* *INDENT-OFF* */
1889   pool_foreach (dm, sm->det_maps,
1890   ({
1891     vlib_cli_output (vm, " in %U/%d out %U/%d\n",
1892                      format_ip4_address, &dm->in_addr, dm->in_plen,
1893                      format_ip4_address, &dm->out_addr, dm->out_plen);
1894     vlib_cli_output (vm, "  outside address sharing ratio: %d\n",
1895                      dm->sharing_ratio);
1896     vlib_cli_output (vm, "  number of ports per inside host: %d\n",
1897                      dm->ports_per_host);
1898     vlib_cli_output (vm, "  sessions number: %d\n", dm->ses_num);
1899   }));
1900   /* *INDENT-ON* */
1901
1902   return 0;
1903 }
1904
1905 static clib_error_t *
1906 snat_det_forward_command_fn (vlib_main_t * vm,
1907                              unformat_input_t * input,
1908                              vlib_cli_command_t * cmd)
1909 {
1910   snat_main_t *sm = &snat_main;
1911   unformat_input_t _line_input, *line_input = &_line_input;
1912   ip4_address_t in_addr, out_addr;
1913   u16 lo_port;
1914   snat_det_map_t *dm;
1915   clib_error_t *error = 0;
1916
1917   if (!sm->deterministic)
1918     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1919
1920   /* Get a line of input. */
1921   if (!unformat_user (input, unformat_line_input, line_input))
1922     return 0;
1923
1924   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1925     {
1926       if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
1927         ;
1928       else
1929         {
1930           error = clib_error_return (0, "unknown input '%U'",
1931                                      format_unformat_error, line_input);
1932           goto done;
1933         }
1934     }
1935
1936   dm = snat_det_map_by_user (sm, &in_addr);
1937   if (!dm)
1938     vlib_cli_output (vm, "no match");
1939   else
1940     {
1941       snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1942       vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
1943                        lo_port, lo_port + dm->ports_per_host - 1);
1944     }
1945
1946 done:
1947   unformat_free (line_input);
1948
1949   return error;
1950 }
1951
1952 static clib_error_t *
1953 snat_det_reverse_command_fn (vlib_main_t * vm,
1954                              unformat_input_t * input,
1955                              vlib_cli_command_t * cmd)
1956 {
1957   snat_main_t *sm = &snat_main;
1958   unformat_input_t _line_input, *line_input = &_line_input;
1959   ip4_address_t in_addr, out_addr;
1960   u32 out_port;
1961   snat_det_map_t *dm;
1962   clib_error_t *error = 0;
1963
1964   if (!sm->deterministic)
1965     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1966
1967   /* Get a line of input. */
1968   if (!unformat_user (input, unformat_line_input, line_input))
1969     return 0;
1970
1971   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1972     {
1973       if (unformat
1974           (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
1975         ;
1976       else
1977         {
1978           error = clib_error_return (0, "unknown input '%U'",
1979                                      format_unformat_error, line_input);
1980           goto done;
1981         }
1982     }
1983
1984   if (out_port < 1024 || out_port > 65535)
1985     {
1986       error = clib_error_return (0, "wrong port, must be <1024-65535>");
1987       goto done;
1988     }
1989
1990   dm = snat_det_map_by_out (sm, &out_addr);
1991   if (!dm)
1992     vlib_cli_output (vm, "no match");
1993   else
1994     {
1995       snat_det_reverse (dm, &out_addr, (u16) out_port, &in_addr);
1996       vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
1997     }
1998
1999 done:
2000   unformat_free (line_input);
2001
2002   return error;
2003 }
2004
2005 static clib_error_t *
2006 set_timeout_command_fn (vlib_main_t * vm,
2007                         unformat_input_t * input, vlib_cli_command_t * cmd)
2008 {
2009   snat_main_t *sm = &snat_main;
2010   unformat_input_t _line_input, *line_input = &_line_input;
2011   clib_error_t *error = 0;
2012
2013   /* Get a line of input. */
2014   if (!unformat_user (input, unformat_line_input, line_input))
2015     return 0;
2016
2017   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2018     {
2019       if (unformat (line_input, "udp %u", &sm->udp_timeout))
2020         {
2021           if (nat64_set_udp_timeout (sm->udp_timeout))
2022             {
2023               error = clib_error_return (0, "Invalid UDP timeout value");
2024               goto done;
2025             }
2026         }
2027       else if (unformat (line_input, "tcp-established %u",
2028                          &sm->tcp_established_timeout))
2029         {
2030           if (nat64_set_tcp_timeouts
2031               (sm->tcp_transitory_timeout, sm->tcp_established_timeout))
2032             {
2033               error =
2034                 clib_error_return (0,
2035                                    "Invalid TCP established timeouts value");
2036               goto done;
2037             }
2038         }
2039       else if (unformat (line_input, "tcp-transitory %u",
2040                          &sm->tcp_transitory_timeout))
2041         {
2042           if (nat64_set_tcp_timeouts
2043               (sm->tcp_transitory_timeout, sm->tcp_established_timeout))
2044             {
2045               error =
2046                 clib_error_return (0,
2047                                    "Invalid TCP transitory timeouts value");
2048               goto done;
2049             }
2050         }
2051       else if (unformat (line_input, "icmp %u", &sm->icmp_timeout))
2052         {
2053           if (nat64_set_icmp_timeout (sm->icmp_timeout))
2054             {
2055               error = clib_error_return (0, "Invalid ICMP timeout value");
2056               goto done;
2057             }
2058         }
2059       else if (unformat (line_input, "reset"))
2060         {
2061           sm->udp_timeout = SNAT_UDP_TIMEOUT;
2062           sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
2063           sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
2064           sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
2065           nat64_set_udp_timeout (0);
2066           nat64_set_icmp_timeout (0);
2067           nat64_set_tcp_timeouts (0, 0);
2068         }
2069       else
2070         {
2071           error = clib_error_return (0, "unknown input '%U'",
2072                                      format_unformat_error, line_input);
2073           goto done;
2074         }
2075     }
2076 done:
2077   unformat_free (line_input);
2078   return error;
2079 }
2080
2081 static clib_error_t *
2082 nat_show_timeouts_command_fn (vlib_main_t * vm,
2083                               unformat_input_t * input,
2084                               vlib_cli_command_t * cmd)
2085 {
2086   snat_main_t *sm = &snat_main;
2087
2088   vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
2089   vlib_cli_output (vm, "tcp-established timeout: %dsec",
2090                    sm->tcp_established_timeout);
2091   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
2092                    sm->tcp_transitory_timeout);
2093   vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
2094
2095   return 0;
2096 }
2097
2098 static clib_error_t *
2099 nat44_det_show_sessions_command_fn (vlib_main_t * vm,
2100                                     unformat_input_t * input,
2101                                     vlib_cli_command_t * cmd)
2102 {
2103   snat_main_t *sm = &snat_main;
2104   snat_det_map_t *dm;
2105   snat_det_session_t *ses;
2106   int i;
2107
2108   if (!sm->deterministic)
2109     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
2110
2111   vlib_cli_output (vm, "NAT44 deterministic sessions:");
2112   /* *INDENT-OFF* */
2113   pool_foreach (dm, sm->det_maps,
2114   ({
2115     vec_foreach_index (i, dm->sessions)
2116       {
2117         ses = vec_elt_at_index (dm->sessions, i);
2118         if (ses->in_port)
2119           vlib_cli_output (vm, "  %U", format_det_map_ses, dm, ses, &i);
2120       }
2121   }));
2122   /* *INDENT-ON* */
2123   return 0;
2124 }
2125
2126 static clib_error_t *
2127 snat_det_close_session_out_fn (vlib_main_t * vm,
2128                                unformat_input_t * input,
2129                                vlib_cli_command_t * cmd)
2130 {
2131   snat_main_t *sm = &snat_main;
2132   unformat_input_t _line_input, *line_input = &_line_input;
2133   ip4_address_t out_addr, ext_addr, in_addr;
2134   u32 out_port, ext_port;
2135   snat_det_map_t *dm;
2136   snat_det_session_t *ses;
2137   snat_det_out_key_t key;
2138   clib_error_t *error = 0;
2139
2140   if (!sm->deterministic)
2141     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
2142
2143   /* Get a line of input. */
2144   if (!unformat_user (input, unformat_line_input, line_input))
2145     return 0;
2146
2147   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2148     {
2149       if (unformat (line_input, "%U:%d %U:%d",
2150                     unformat_ip4_address, &out_addr, &out_port,
2151                     unformat_ip4_address, &ext_addr, &ext_port))
2152         ;
2153       else
2154         {
2155           error = clib_error_return (0, "unknown input '%U'",
2156                                      format_unformat_error, line_input);
2157           goto done;
2158         }
2159     }
2160
2161   unformat_free (line_input);
2162
2163   dm = snat_det_map_by_out (sm, &out_addr);
2164   if (!dm)
2165     vlib_cli_output (vm, "no match");
2166   else
2167     {
2168       snat_det_reverse (dm, &ext_addr, (u16) out_port, &in_addr);
2169       key.ext_host_addr = out_addr;
2170       key.ext_host_port = ntohs ((u16) ext_port);
2171       key.out_port = ntohs ((u16) out_port);
2172       ses = snat_det_get_ses_by_out (dm, &out_addr, key.as_u64);
2173       if (!ses)
2174         vlib_cli_output (vm, "no match");
2175       else
2176         snat_det_ses_close (dm, ses);
2177     }
2178
2179 done:
2180   unformat_free (line_input);
2181
2182   return error;
2183 }
2184
2185 static clib_error_t *
2186 snat_det_close_session_in_fn (vlib_main_t * vm,
2187                               unformat_input_t * input,
2188                               vlib_cli_command_t * cmd)
2189 {
2190   snat_main_t *sm = &snat_main;
2191   unformat_input_t _line_input, *line_input = &_line_input;
2192   ip4_address_t in_addr, ext_addr;
2193   u32 in_port, ext_port;
2194   snat_det_map_t *dm;
2195   snat_det_session_t *ses;
2196   snat_det_out_key_t key;
2197   clib_error_t *error = 0;
2198
2199   if (!sm->deterministic)
2200     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
2201
2202   /* Get a line of input. */
2203   if (!unformat_user (input, unformat_line_input, line_input))
2204     return 0;
2205
2206   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2207     {
2208       if (unformat (line_input, "%U:%d %U:%d",
2209                     unformat_ip4_address, &in_addr, &in_port,
2210                     unformat_ip4_address, &ext_addr, &ext_port))
2211         ;
2212       else
2213         {
2214           error = clib_error_return (0, "unknown input '%U'",
2215                                      format_unformat_error, line_input);
2216           goto done;
2217         }
2218     }
2219
2220   unformat_free (line_input);
2221
2222   dm = snat_det_map_by_user (sm, &in_addr);
2223   if (!dm)
2224     vlib_cli_output (vm, "no match");
2225   else
2226     {
2227       key.ext_host_addr = ext_addr;
2228       key.ext_host_port = ntohs ((u16) ext_port);
2229       ses =
2230         snat_det_find_ses_by_in (dm, &in_addr, ntohs ((u16) in_port), key);
2231       if (!ses)
2232         vlib_cli_output (vm, "no match");
2233       else
2234         snat_det_ses_close (dm, ses);
2235     }
2236
2237 done:
2238   unformat_free (line_input);
2239
2240   return error;
2241 }
2242 /* *INDENT-OFF* */
2243
2244 /*?
2245  * @cliexpar
2246  * @cliexstart{set snat workers}
2247  * Set NAT workers if 2 or more workers available, use:
2248  *  vpp# set snat workers 0-2,5
2249  * @cliexend
2250 ?*/
2251 VLIB_CLI_COMMAND (set_workers_command, static) = {
2252   .path = "set nat workers",
2253   .function = set_workers_command_fn,
2254   .short_help = "set nat workers <workers-list>",
2255 };
2256
2257 /*?
2258  * @cliexpar
2259  * @cliexstart{show nat workers}
2260  * Show NAT workers.
2261  *  vpp# show nat workers:
2262  *  2 workers
2263  *    vpp_wk_0
2264  *    vpp_wk_1
2265  * @cliexend
2266 ?*/
2267 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
2268   .path = "show nat workers",
2269   .short_help = "show nat workers",
2270   .function = nat_show_workers_commnad_fn,
2271 };
2272
2273 /*?
2274  * @cliexpar
2275  * @cliexstart{set nat timeout}
2276  * Set values of timeouts for NAT sessions (in seconds), use:
2277  *  vpp# set nat timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90
2278  * To reset default values use:
2279  *  vpp# set nat44 deterministic timeout reset
2280  * @cliexend
2281 ?*/
2282 VLIB_CLI_COMMAND (set_timeout_command, static) = {
2283   .path = "set nat timeout",
2284   .function = set_timeout_command_fn,
2285   .short_help =
2286     "set nat timeout [udp <sec> | tcp-established <sec> "
2287     "tcp-transitory <sec> | icmp <sec> | reset]",
2288 };
2289
2290 /*?
2291  * @cliexpar
2292  * @cliexstart{show nat timeouts}
2293  * Show values of timeouts for NAT sessions.
2294  * vpp# show nat timeouts
2295  * udp timeout: 300sec
2296  * tcp-established timeout: 7440sec
2297  * tcp-transitory timeout: 240sec
2298  * icmp timeout: 60sec
2299  * @cliexend
2300 ?*/
2301 VLIB_CLI_COMMAND (nat_show_timeouts_command, static) = {
2302   .path = "show nat timeouts",
2303   .short_help = "show nat timeouts",
2304   .function = nat_show_timeouts_command_fn,
2305 };
2306
2307 /*?
2308  * @cliexpar
2309  * @cliexstart{nat set logging level}
2310  * To set NAT logging level use:
2311  * Set nat logging level
2312  * @cliexend
2313 ?*/
2314 VLIB_CLI_COMMAND (snat_set_log_level_command, static) = {
2315   .path = "nat set logging level",
2316   .function = snat_set_log_level_command_fn,
2317   .short_help = "nat set logging level <level>",
2318 };
2319
2320 /*?
2321  * @cliexpar
2322  * @cliexstart{snat ipfix logging}
2323  * To enable NAT IPFIX logging use:
2324  *  vpp# nat ipfix logging
2325  * To set IPFIX exporter use:
2326  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
2327  * @cliexend
2328 ?*/
2329 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
2330   .path = "nat ipfix logging",
2331   .function = snat_ipfix_logging_enable_disable_command_fn,
2332   .short_help = "nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
2333 };
2334
2335 /*?
2336  * @cliexpar
2337  * @cliexstart{nat addr-port-assignment-alg}
2338  * Set address and port assignment algorithm
2339  * For the MAP-E CE limit port choice based on PSID use:
2340  *  vpp# nat addr-port-assignment-alg map-e psid 10 psid-offset 6 psid-len 6
2341  * For port range use:
2342  *  vpp# nat addr-port-assignment-alg port-range <start-port> - <end-port>
2343  * To set standard (default) address and port assignment algorithm use:
2344  *  vpp# nat addr-port-assignment-alg default
2345  * @cliexend
2346 ?*/
2347 VLIB_CLI_COMMAND (nat44_set_alloc_addr_and_port_alg_command, static) = {
2348     .path = "nat addr-port-assignment-alg",
2349     .short_help = "nat addr-port-assignment-alg <alg-name> [<alg-params>]",
2350     .function = nat44_set_alloc_addr_and_port_alg_command_fn,
2351 };
2352
2353 /*?
2354  * @cliexpar
2355  * @cliexstart{show nat addr-port-assignment-alg}
2356  * Show address and port assignment algorithm
2357  * @cliexend
2358 ?*/
2359 VLIB_CLI_COMMAND (nat44_show_alloc_addr_and_port_alg_command, static) = {
2360     .path = "show nat addr-port-assignment-alg",
2361     .short_help = "show nat addr-port-assignment-alg",
2362     .function = nat44_show_alloc_addr_and_port_alg_command_fn,
2363 };
2364
2365 /*?
2366  * @cliexpar
2367  * @cliexstart{nat mss-clamping}
2368  * Set TCP MSS rewriting configuration
2369  * To enable TCP MSS rewriting use:
2370  *  vpp# nat mss-clamping 1452
2371  * To disbale TCP MSS rewriting use:
2372  *  vpp# nat mss-clamping disable
2373  * @cliexend
2374 ?*/
2375 VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = {
2376     .path = "nat mss-clamping",
2377     .short_help = "nat mss-clamping <mss-value>|disable",
2378     .function = nat_set_mss_clamping_command_fn,
2379 };
2380
2381 /*?
2382  * @cliexpar
2383  * @cliexstart{show nat mss-clamping}
2384  * Show TCP MSS rewriting configuration
2385  * @cliexend
2386 ?*/
2387 VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = {
2388     .path = "show nat mss-clamping",
2389     .short_help = "show nat mss-clamping",
2390     .function = nat_show_mss_clamping_command_fn,
2391 };
2392
2393 /*?
2394  * @cliexpar
2395  * @cliexstart{nat ha failover}
2396  * Set HA failover (remote settings)
2397  * @cliexend
2398 ?*/
2399 VLIB_CLI_COMMAND (nat_ha_failover_command, static) = {
2400     .path = "nat ha failover",
2401     .short_help = "nat ha failover <ip4-address>:<port> [refresh-interval <sec>]",
2402     .function = nat_ha_failover_command_fn,
2403 };
2404
2405 /*?
2406  * @cliexpar
2407  * @cliexstart{nat ha listener}
2408  * Set HA listener (local settings)
2409  * @cliexend
2410 ?*/
2411 VLIB_CLI_COMMAND (nat_ha_listener_command, static) = {
2412     .path = "nat ha listener",
2413     .short_help = "nat ha listener <ip4-address>:<port> [path-mtu <path-mtu>]",
2414     .function = nat_ha_listener_command_fn,
2415 };
2416
2417 /*?
2418  * @cliexpar
2419  * @cliexstart{show nat ha}
2420  * Show HA configuration/status
2421  * @cliexend
2422 ?*/
2423 VLIB_CLI_COMMAND (nat_show_ha_command, static) = {
2424     .path = "show nat ha",
2425     .short_help = "show nat ha",
2426     .function = nat_show_ha_command_fn,
2427 };
2428
2429 /*?
2430  * @cliexpar
2431  * @cliexstart{nat ha flush}
2432  * Flush the current HA data (for testing)
2433  * @cliexend
2434 ?*/
2435 VLIB_CLI_COMMAND (nat_ha_flush_command, static) = {
2436     .path = "nat ha flush",
2437     .short_help = "nat ha flush",
2438     .function = nat_ha_flush_command_fn,
2439 };
2440
2441 /*?
2442  * @cliexpar
2443  * @cliexstart{nat ha resync}
2444  * Resync HA (resend existing sessions to new failover)
2445  * @cliexend
2446 ?*/
2447 VLIB_CLI_COMMAND (nat_ha_resync_command, static) = {
2448     .path = "nat ha resync",
2449     .short_help = "nat ha resync",
2450     .function = nat_ha_resync_command_fn,
2451 };
2452
2453 /*?
2454  * @cliexpar
2455  * @cliexstart{show nat44 hash tables}
2456  * Show NAT44 hash tables
2457  * @cliexend
2458 ?*/
2459 VLIB_CLI_COMMAND (nat44_show_hash, static) = {
2460   .path = "show nat44 hash tables",
2461   .short_help = "show nat44 hash tables [detail|verbose]",
2462   .function = nat44_show_hash_command_fn,
2463 };
2464
2465 /*?
2466  * @cliexpar
2467  * @cliexstart{nat44 add address}
2468  * Add/delete NAT44 pool address.
2469  * To add NAT44 pool address use:
2470  *  vpp# nat44 add address 172.16.1.3
2471  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
2472  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
2473  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
2474  * @cliexend
2475 ?*/
2476 VLIB_CLI_COMMAND (add_address_command, static) = {
2477   .path = "nat44 add address",
2478   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
2479                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
2480   .function = add_address_command_fn,
2481 };
2482
2483 /*?
2484  * @cliexpar
2485  * @cliexstart{show nat44 summary}
2486  * Show NAT44 summary
2487  * vpp# show nat44 summary
2488  * @cliexend
2489 ?*/
2490 VLIB_CLI_COMMAND (nat44_show_summary_command, static) = {
2491   .path = "show nat44 summary",
2492   .short_help = "show nat44 summary",
2493   .function = nat44_show_summary_command_fn,
2494 };
2495
2496 /*?
2497  * @cliexpar
2498  * @cliexstart{show nat44 addresses}
2499  * Show NAT44 pool addresses.
2500  * vpp# show nat44 addresses
2501  * NAT44 pool addresses:
2502  * 172.16.2.2
2503  *   tenant VRF independent
2504  *   10 busy udp ports
2505  *   0 busy tcp ports
2506  *   0 busy icmp ports
2507  * 172.16.1.3
2508  *   tenant VRF: 10
2509  *   0 busy udp ports
2510  *   2 busy tcp ports
2511  *   0 busy icmp ports
2512  * NAT44 twice-nat pool addresses:
2513  * 10.20.30.72
2514  *   tenant VRF independent
2515  *   0 busy udp ports
2516  *   0 busy tcp ports
2517  *   0 busy icmp ports
2518  * @cliexend
2519 ?*/
2520 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
2521   .path = "show nat44 addresses",
2522   .short_help = "show nat44 addresses",
2523   .function = nat44_show_addresses_command_fn,
2524 };
2525
2526 /*?
2527  * @cliexpar
2528  * @cliexstart{set interface nat44}
2529  * Enable/disable NAT44 feature on the interface.
2530  * To enable NAT44 feature with local network interface use:
2531  *  vpp# set interface nat44 in GigabitEthernet0/8/0
2532  * To enable NAT44 feature with external network interface use:
2533  *  vpp# set interface nat44 out GigabitEthernet0/a/0
2534  * @cliexend
2535 ?*/
2536 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
2537   .path = "set interface nat44",
2538   .function = snat_feature_command_fn,
2539   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
2540                 "[del]",
2541 };
2542
2543 /*?
2544  * @cliexpar
2545  * @cliexstart{show nat44 interfaces}
2546  * Show interfaces with NAT44 feature.
2547  * vpp# show nat44 interfaces
2548  * NAT44 interfaces:
2549  *  GigabitEthernet0/8/0 in
2550  *  GigabitEthernet0/a/0 out
2551  * @cliexend
2552 ?*/
2553 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
2554   .path = "show nat44 interfaces",
2555   .short_help = "show nat44 interfaces",
2556   .function = nat44_show_interfaces_command_fn,
2557 };
2558
2559 /*?
2560  * @cliexpar
2561  * @cliexstart{nat44 add static mapping}
2562  * Static mapping allows hosts on the external network to initiate connection
2563  * to to the local network host.
2564  * To create static mapping between local host address 10.0.0.3 port 6303 and
2565  * external address 4.4.4.4 port 3606 for TCP protocol use:
2566  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
2567  * If not runnig "static mapping only" NAT plugin mode use before:
2568  *  vpp# nat44 add address 4.4.4.4
2569  * To create address only static mapping between local and external address use:
2570  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
2571  * To create ICMP static mapping between local and external with ICMP echo
2572  * identifier 10 use:
2573  *  vpp# nat44 add static mapping icmp local 10.0.0.3 10 external 4.4.4.4 10
2574  * @cliexend
2575 ?*/
2576 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
2577   .path = "nat44 add static mapping",
2578   .function = add_static_mapping_command_fn,
2579   .short_help =
2580     "nat44 add static mapping tcp|udp|icmp local <addr> [<port|icmp-echo-id>] "
2581     "external <addr> [<port|icmp-echo-id>] [vrf <table-id>] [twice-nat|self-twice-nat] "
2582     "[out2in-only] [del]",
2583 };
2584
2585 /*?
2586  * @cliexpar
2587  * @cliexstart{nat44 add identity mapping}
2588  * Identity mapping translate an IP address to itself.
2589  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
2590  * use:
2591  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
2592  * To create identity mapping for address 10.0.0.3 use:
2593  *  vpp# nat44 add identity mapping 10.0.0.3
2594  * To create identity mapping for DHCP addressed interface use:
2595  *  vpp# nat44 add identity mapping external GigabitEthernet0/a/0 tcp 3606
2596  * @cliexend
2597 ?*/
2598 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
2599   .path = "nat44 add identity mapping",
2600   .function = add_identity_mapping_command_fn,
2601   .short_help = "nat44 add identity mapping <ip4-addr>|external <interface> "
2602     "[<protocol> <port>] [vrf <table-id>] [del]",
2603 };
2604
2605 /*?
2606  * @cliexpar
2607  * @cliexstart{nat44 add load-balancing static mapping}
2608  * Service load balancing using NAT44
2609  * To add static mapping with load balancing for service with external IP
2610  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
2611  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
2612  *  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
2613  * @cliexend
2614 ?*/
2615 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
2616   .path = "nat44 add load-balancing static mapping",
2617   .function = add_lb_static_mapping_command_fn,
2618   .short_help =
2619     "nat44 add load-balancing static mapping protocol tcp|udp "
2620     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2621     "probability <n> [twice-nat|self-twice-nat] [out2in-only] "
2622     "[affinity <timeout-seconds>] [del]",
2623 };
2624
2625 /*?
2626  * @cliexpar
2627  * @cliexstart{nat44 add load-balancing static mapping}
2628  * Modify service load balancing using NAT44
2629  * To add new back-end server 10.100.10.30:8080 for service load balancing
2630  * static mapping with external IP address 1.2.3.4 and TCP port 80 use:
2631  *  vpp# nat44 add load-balancing back-end protocol tcp external 1.2.3.4:80 local 10.100.10.30:8080 probability 25
2632  * @cliexend
2633 ?*/
2634 VLIB_CLI_COMMAND (add_lb_backend_command, static) = {
2635   .path = "nat44 add load-balancing back-end",
2636   .function = add_lb_backend_command_fn,
2637   .short_help =
2638     "nat44 add load-balancing back-end protocol tcp|udp "
2639     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2640     "probability <n> [del]",
2641 };
2642
2643 /*?
2644  * @cliexpar
2645  * @cliexstart{show nat44 static mappings}
2646  * Show NAT44 static mappings.
2647  * vpp# show nat44 static mappings
2648  * NAT44 static mappings:
2649  *  local 10.0.0.3 external 4.4.4.4 vrf 0
2650  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
2651  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
2652  *   local 10.100.10.10:8080 probability 80
2653  *   local 10.100.10.20:8080 probability 20
2654  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
2655  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
2656  * @cliexend
2657 ?*/
2658 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
2659   .path = "show nat44 static mappings",
2660   .short_help = "show nat44 static mappings",
2661   .function = nat44_show_static_mappings_command_fn,
2662 };
2663
2664 /*?
2665  * @cliexpar
2666  * @cliexstart{nat44 add interface address}
2667  * Use NAT44 pool address from specific interfce
2668  * To add NAT44 pool address from specific interface use:
2669  *  vpp# nat44 add interface address GigabitEthernet0/8/0
2670  * @cliexend
2671 ?*/
2672 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
2673     .path = "nat44 add interface address",
2674     .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
2675     .function = snat_add_interface_address_command_fn,
2676 };
2677
2678 /*?
2679  * @cliexpar
2680  * @cliexstart{show nat44 interface address}
2681  * Show NAT44 pool address interfaces
2682  * vpp# show nat44 interface address
2683  * NAT44 pool address interfaces:
2684  *  GigabitEthernet0/a/0
2685  * NAT44 twice-nat pool address interfaces:
2686  *  GigabitEthernet0/8/0
2687  * @cliexend
2688 ?*/
2689 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
2690   .path = "show nat44 interface address",
2691   .short_help = "show nat44 interface address",
2692   .function = nat44_show_interface_address_command_fn,
2693 };
2694
2695 /*?
2696  * @cliexpar
2697  * @cliexstart{show nat44 sessions}
2698  * Show NAT44 sessions.
2699  * @cliexend
2700 ?*/
2701 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
2702   .path = "show nat44 sessions",
2703   .short_help = "show nat44 sessions [detail|metrics]",
2704   .function = nat44_show_sessions_command_fn,
2705 };
2706
2707 /*?
2708  * @cliexpar
2709  * @cliexstart{set nat44 session limit}
2710  * Set NAT44 session limit.
2711  * @cliexend
2712 ?*/
2713 VLIB_CLI_COMMAND (nat44_set_session_limit_command, static) = {
2714   .path = "set nat44 session limit",
2715   .short_help = "set nat44 session limit <limit> [vrf <table-id>]",
2716   .function = nat44_set_session_limit_command_fn,
2717 };
2718
2719 /*?
2720  * @cliexpar
2721  * @cliexstart{nat44 del user}
2722  * To delete all NAT44 user sessions:
2723  *  vpp# nat44 del user 10.0.0.3
2724  * @cliexend
2725 ?*/
2726 VLIB_CLI_COMMAND (nat44_del_user_command, static) = {
2727     .path = "nat44 del user",
2728     .short_help = "nat44 del user <addr> [fib <index>]",
2729     .function = nat44_del_user_command_fn,
2730 };
2731
2732 /*?
2733  * @cliexpar
2734  * @cliexstart{clear nat44 sessions}
2735  * To clear all NAT44 sessions
2736  *  vpp# clear nat44 sessions
2737  * @cliexend
2738 ?*/
2739 VLIB_CLI_COMMAND (nat44_clear_sessions_command, static) = {
2740     .path = "clear nat44 sessions",
2741     .short_help = "clear nat44 sessions",
2742     .function = nat44_clear_sessions_command_fn,
2743 };
2744
2745 /*?
2746  * @cliexpar
2747  * @cliexstart{nat44 del session}
2748  * To administratively delete NAT44 session by inside address and port use:
2749  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
2750  * To administratively delete NAT44 session by outside address and port use:
2751  *  vpp# nat44 del session out 1.0.0.3:6033 udp
2752  * @cliexend
2753 ?*/
2754 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
2755     .path = "nat44 del session",
2756     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>] [external-host <addr>:<port>]",
2757     .function = nat44_del_session_command_fn,
2758 };
2759
2760 /*?
2761  * @cliexpar
2762  * @cliexstart{nat44 forwarding}
2763  * Enable or disable forwarding
2764  * Forward packets which don't match existing translation
2765  * or static mapping instead of dropping them.
2766  * To enable forwarding, use:
2767  *  vpp# nat44 forwarding enable
2768  * To disable forwarding, use:
2769  *  vpp# nat44 forwarding disable
2770  * @cliexend
2771 ?*/
2772 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
2773   .path = "nat44 forwarding",
2774   .short_help = "nat44 forwarding enable|disable",
2775   .function = snat_forwarding_set_command_fn,
2776 };
2777
2778 /*?
2779  * @cliexpar
2780  * @cliexstart{nat44 deterministic add}
2781  * Create bijective mapping of inside address to outside address and port range
2782  * pairs, with the purpose of enabling deterministic NAT to reduce logging in
2783  * CGN deployments.
2784  * To create deterministic mapping between inside network 10.0.0.0/18 and
2785  * outside network 1.1.1.0/30 use:
2786  * # vpp# nat44 deterministic add in 10.0.0.0/18 out 1.1.1.0/30
2787  * @cliexend
2788 ?*/
2789 VLIB_CLI_COMMAND (snat_det_map_command, static) = {
2790     .path = "nat44 deterministic add",
2791     .short_help = "nat44 deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
2792     .function = snat_det_map_command_fn,
2793 };
2794
2795 /*?
2796  * @cliexpar
2797  * @cliexpstart{show nat44 deterministic mappings}
2798  * Show NAT44 deterministic mappings
2799  * vpp# show nat44 deterministic mappings
2800  * NAT44 deterministic mappings:
2801  *  in 10.0.0.0/24 out 1.1.1.1/32
2802  *   outside address sharing ratio: 256
2803  *   number of ports per inside host: 252
2804  *   sessions number: 0
2805  * @cliexend
2806 ?*/
2807 VLIB_CLI_COMMAND (nat44_det_show_mappings_command, static) = {
2808     .path = "show nat44 deterministic mappings",
2809     .short_help = "show nat44 deterministic mappings",
2810     .function = nat44_det_show_mappings_command_fn,
2811 };
2812
2813 /*?
2814  * @cliexpar
2815  * @cliexstart{nat44 deterministic forward}
2816  * Return outside address and port range from inside address for deterministic
2817  * NAT.
2818  * To obtain outside address and port of inside host use:
2819  *  vpp# nat44 deterministic forward 10.0.0.2
2820  *  1.1.1.0:<1054-1068>
2821  * @cliexend
2822 ?*/
2823 VLIB_CLI_COMMAND (snat_det_forward_command, static) = {
2824     .path = "nat44 deterministic forward",
2825     .short_help = "nat44 deterministic forward <addr>",
2826     .function = snat_det_forward_command_fn,
2827 };
2828
2829 /*?
2830  * @cliexpar
2831  * @cliexstart{nat44 deterministic reverse}
2832  * Return inside address from outside address and port for deterministic NAT.
2833  * To obtain inside host address from outside address and port use:
2834  *  #vpp nat44 deterministic reverse 1.1.1.1:1276
2835  *  10.0.16.16
2836  * @cliexend
2837 ?*/
2838 VLIB_CLI_COMMAND (snat_det_reverse_command, static) = {
2839     .path = "nat44 deterministic reverse",
2840     .short_help = "nat44 deterministic reverse <addr>:<port>",
2841     .function = snat_det_reverse_command_fn,
2842 };
2843
2844 /*?
2845  * @cliexpar
2846  * @cliexstart{show nat44 deterministic sessions}
2847  * Show NAT44 deterministic sessions.
2848  * vpp# show nat44 deterministic sessions
2849  * NAT44 deterministic sessions:
2850  *   in 10.0.0.3:3005 out 1.1.1.2:1146 external host 172.16.1.2:3006 state: udp-active expire: 306
2851  *   in 10.0.0.3:3000 out 1.1.1.2:1141 external host 172.16.1.2:3001 state: udp-active expire: 306
2852  *   in 10.0.0.4:3005 out 1.1.1.2:1177 external host 172.16.1.2:3006 state: udp-active expire: 306
2853  * @cliexend
2854 ?*/
2855 VLIB_CLI_COMMAND (nat44_det_show_sessions_command, static) = {
2856   .path = "show nat44 deterministic sessions",
2857   .short_help = "show nat44 deterministic sessions",
2858   .function = nat44_det_show_sessions_command_fn,
2859 };
2860
2861 /*?
2862  * @cliexpar
2863  * @cliexstart{nat44 deterministic close session out}
2864  * Close session using outside ip address and port
2865  * and external ip address and port, use:
2866  *  vpp# nat44 deterministic close session out 1.1.1.1:1276 2.2.2.2:2387
2867  * @cliexend
2868 ?*/
2869 VLIB_CLI_COMMAND (snat_det_close_sesion_out_command, static) = {
2870   .path = "nat44 deterministic close session out",
2871   .short_help = "nat44 deterministic close session out "
2872                 "<out_addr>:<out_port> <ext_addr>:<ext_port>",
2873   .function = snat_det_close_session_out_fn,
2874 };
2875
2876 /*?
2877  * @cliexpar
2878  * @cliexstart{nat44 deterministic close session in}
2879  * Close session using inside ip address and port
2880  * and external ip address and port, use:
2881  *  vpp# nat44 deterministic close session in 3.3.3.3:3487 2.2.2.2:2387
2882  * @cliexend
2883 ?*/
2884 VLIB_CLI_COMMAND (snat_det_close_session_in_command, static) = {
2885   .path = "nat44 deterministic close session in",
2886   .short_help = "nat44 deterministic close session in "
2887                 "<in_addr>:<in_port> <ext_addr>:<ext_port>",
2888   .function = snat_det_close_session_in_fn,
2889 };
2890
2891 /* *INDENT-ON* */
2892
2893 /*
2894  * fd.io coding-style-patch-verification: ON
2895  *
2896  * Local Variables:
2897  * eval: (c-set-style "gnu")
2898  * End:
2899  */