7d74f36c754188f3945f44f2b28ea162c414446e
[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   if (in_plen > 32 || out_plen > 32)
1862     {
1863       error = clib_error_return (0, "network prefix length must be <= 32");
1864       goto done;
1865     }
1866
1867   rv = snat_det_add_map (sm, &in_addr, in_plen, &out_addr, out_plen, is_add);
1868
1869   if (rv)
1870     {
1871       error = clib_error_return (0, "snat_det_add_map return %d", rv);
1872       goto done;
1873     }
1874
1875 done:
1876   unformat_free (line_input);
1877
1878   return error;
1879 }
1880
1881 static clib_error_t *
1882 nat44_det_show_mappings_command_fn (vlib_main_t * vm,
1883                                     unformat_input_t * input,
1884                                     vlib_cli_command_t * cmd)
1885 {
1886   snat_main_t *sm = &snat_main;
1887   snat_det_map_t *dm;
1888
1889   if (!sm->deterministic)
1890     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1891
1892   vlib_cli_output (vm, "NAT44 deterministic mappings:");
1893   /* *INDENT-OFF* */
1894   pool_foreach (dm, sm->det_maps,
1895   ({
1896     vlib_cli_output (vm, " in %U/%d out %U/%d\n",
1897                      format_ip4_address, &dm->in_addr, dm->in_plen,
1898                      format_ip4_address, &dm->out_addr, dm->out_plen);
1899     vlib_cli_output (vm, "  outside address sharing ratio: %d\n",
1900                      dm->sharing_ratio);
1901     vlib_cli_output (vm, "  number of ports per inside host: %d\n",
1902                      dm->ports_per_host);
1903     vlib_cli_output (vm, "  sessions number: %d\n", dm->ses_num);
1904   }));
1905   /* *INDENT-ON* */
1906
1907   return 0;
1908 }
1909
1910 static clib_error_t *
1911 snat_det_forward_command_fn (vlib_main_t * vm,
1912                              unformat_input_t * input,
1913                              vlib_cli_command_t * cmd)
1914 {
1915   snat_main_t *sm = &snat_main;
1916   unformat_input_t _line_input, *line_input = &_line_input;
1917   ip4_address_t in_addr, out_addr;
1918   u16 lo_port;
1919   snat_det_map_t *dm;
1920   clib_error_t *error = 0;
1921
1922   if (!sm->deterministic)
1923     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1924
1925   /* Get a line of input. */
1926   if (!unformat_user (input, unformat_line_input, line_input))
1927     return 0;
1928
1929   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1930     {
1931       if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
1932         ;
1933       else
1934         {
1935           error = clib_error_return (0, "unknown input '%U'",
1936                                      format_unformat_error, line_input);
1937           goto done;
1938         }
1939     }
1940
1941   dm = snat_det_map_by_user (sm, &in_addr);
1942   if (!dm)
1943     vlib_cli_output (vm, "no match");
1944   else
1945     {
1946       snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1947       vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
1948                        lo_port, lo_port + dm->ports_per_host - 1);
1949     }
1950
1951 done:
1952   unformat_free (line_input);
1953
1954   return error;
1955 }
1956
1957 static clib_error_t *
1958 snat_det_reverse_command_fn (vlib_main_t * vm,
1959                              unformat_input_t * input,
1960                              vlib_cli_command_t * cmd)
1961 {
1962   snat_main_t *sm = &snat_main;
1963   unformat_input_t _line_input, *line_input = &_line_input;
1964   ip4_address_t in_addr, out_addr;
1965   u32 out_port;
1966   snat_det_map_t *dm;
1967   clib_error_t *error = 0;
1968
1969   if (!sm->deterministic)
1970     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1971
1972   /* Get a line of input. */
1973   if (!unformat_user (input, unformat_line_input, line_input))
1974     return 0;
1975
1976   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1977     {
1978       if (unformat
1979           (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
1980         ;
1981       else
1982         {
1983           error = clib_error_return (0, "unknown input '%U'",
1984                                      format_unformat_error, line_input);
1985           goto done;
1986         }
1987     }
1988
1989   if (out_port < 1024 || out_port > 65535)
1990     {
1991       error = clib_error_return (0, "wrong port, must be <1024-65535>");
1992       goto done;
1993     }
1994
1995   dm = snat_det_map_by_out (sm, &out_addr);
1996   if (!dm)
1997     vlib_cli_output (vm, "no match");
1998   else
1999     {
2000       snat_det_reverse (dm, &out_addr, (u16) out_port, &in_addr);
2001       vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
2002     }
2003
2004 done:
2005   unformat_free (line_input);
2006
2007   return error;
2008 }
2009
2010 static clib_error_t *
2011 set_timeout_command_fn (vlib_main_t * vm,
2012                         unformat_input_t * input, vlib_cli_command_t * cmd)
2013 {
2014   snat_main_t *sm = &snat_main;
2015   unformat_input_t _line_input, *line_input = &_line_input;
2016   clib_error_t *error = 0;
2017
2018   /* Get a line of input. */
2019   if (!unformat_user (input, unformat_line_input, line_input))
2020     return 0;
2021
2022   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2023     {
2024       if (unformat (line_input, "udp %u", &sm->udp_timeout))
2025         {
2026           if (nat64_set_udp_timeout (sm->udp_timeout))
2027             {
2028               error = clib_error_return (0, "Invalid UDP timeout value");
2029               goto done;
2030             }
2031         }
2032       else if (unformat (line_input, "tcp-established %u",
2033                          &sm->tcp_established_timeout))
2034         {
2035           if (nat64_set_tcp_timeouts
2036               (sm->tcp_transitory_timeout, sm->tcp_established_timeout))
2037             {
2038               error =
2039                 clib_error_return (0,
2040                                    "Invalid TCP established timeouts value");
2041               goto done;
2042             }
2043         }
2044       else if (unformat (line_input, "tcp-transitory %u",
2045                          &sm->tcp_transitory_timeout))
2046         {
2047           if (nat64_set_tcp_timeouts
2048               (sm->tcp_transitory_timeout, sm->tcp_established_timeout))
2049             {
2050               error =
2051                 clib_error_return (0,
2052                                    "Invalid TCP transitory timeouts value");
2053               goto done;
2054             }
2055         }
2056       else if (unformat (line_input, "icmp %u", &sm->icmp_timeout))
2057         {
2058           if (nat64_set_icmp_timeout (sm->icmp_timeout))
2059             {
2060               error = clib_error_return (0, "Invalid ICMP timeout value");
2061               goto done;
2062             }
2063         }
2064       else if (unformat (line_input, "reset"))
2065         {
2066           sm->udp_timeout = SNAT_UDP_TIMEOUT;
2067           sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
2068           sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
2069           sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
2070           nat64_set_udp_timeout (0);
2071           nat64_set_icmp_timeout (0);
2072           nat64_set_tcp_timeouts (0, 0);
2073         }
2074       else
2075         {
2076           error = clib_error_return (0, "unknown input '%U'",
2077                                      format_unformat_error, line_input);
2078           goto done;
2079         }
2080     }
2081 done:
2082   unformat_free (line_input);
2083   return error;
2084 }
2085
2086 static clib_error_t *
2087 nat_show_timeouts_command_fn (vlib_main_t * vm,
2088                               unformat_input_t * input,
2089                               vlib_cli_command_t * cmd)
2090 {
2091   snat_main_t *sm = &snat_main;
2092
2093   vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
2094   vlib_cli_output (vm, "tcp-established timeout: %dsec",
2095                    sm->tcp_established_timeout);
2096   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
2097                    sm->tcp_transitory_timeout);
2098   vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
2099
2100   return 0;
2101 }
2102
2103 static clib_error_t *
2104 nat44_det_show_sessions_command_fn (vlib_main_t * vm,
2105                                     unformat_input_t * input,
2106                                     vlib_cli_command_t * cmd)
2107 {
2108   snat_main_t *sm = &snat_main;
2109   snat_det_map_t *dm;
2110   snat_det_session_t *ses;
2111   int i;
2112
2113   if (!sm->deterministic)
2114     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
2115
2116   vlib_cli_output (vm, "NAT44 deterministic sessions:");
2117   /* *INDENT-OFF* */
2118   pool_foreach (dm, sm->det_maps,
2119   ({
2120     vec_foreach_index (i, dm->sessions)
2121       {
2122         ses = vec_elt_at_index (dm->sessions, i);
2123         if (ses->in_port)
2124           vlib_cli_output (vm, "  %U", format_det_map_ses, dm, ses, &i);
2125       }
2126   }));
2127   /* *INDENT-ON* */
2128   return 0;
2129 }
2130
2131 static clib_error_t *
2132 snat_det_close_session_out_fn (vlib_main_t * vm,
2133                                unformat_input_t * input,
2134                                vlib_cli_command_t * cmd)
2135 {
2136   snat_main_t *sm = &snat_main;
2137   unformat_input_t _line_input, *line_input = &_line_input;
2138   ip4_address_t out_addr, ext_addr, in_addr;
2139   u32 out_port, ext_port;
2140   snat_det_map_t *dm;
2141   snat_det_session_t *ses;
2142   snat_det_out_key_t key;
2143   clib_error_t *error = 0;
2144
2145   if (!sm->deterministic)
2146     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
2147
2148   /* Get a line of input. */
2149   if (!unformat_user (input, unformat_line_input, line_input))
2150     return 0;
2151
2152   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2153     {
2154       if (unformat (line_input, "%U:%d %U:%d",
2155                     unformat_ip4_address, &out_addr, &out_port,
2156                     unformat_ip4_address, &ext_addr, &ext_port))
2157         ;
2158       else
2159         {
2160           error = clib_error_return (0, "unknown input '%U'",
2161                                      format_unformat_error, line_input);
2162           goto done;
2163         }
2164     }
2165
2166   unformat_free (line_input);
2167
2168   dm = snat_det_map_by_out (sm, &out_addr);
2169   if (!dm)
2170     vlib_cli_output (vm, "no match");
2171   else
2172     {
2173       snat_det_reverse (dm, &ext_addr, (u16) out_port, &in_addr);
2174       key.ext_host_addr = out_addr;
2175       key.ext_host_port = ntohs ((u16) ext_port);
2176       key.out_port = ntohs ((u16) out_port);
2177       ses = snat_det_get_ses_by_out (dm, &out_addr, key.as_u64);
2178       if (!ses)
2179         vlib_cli_output (vm, "no match");
2180       else
2181         snat_det_ses_close (dm, ses);
2182     }
2183
2184 done:
2185   unformat_free (line_input);
2186
2187   return error;
2188 }
2189
2190 static clib_error_t *
2191 snat_det_close_session_in_fn (vlib_main_t * vm,
2192                               unformat_input_t * input,
2193                               vlib_cli_command_t * cmd)
2194 {
2195   snat_main_t *sm = &snat_main;
2196   unformat_input_t _line_input, *line_input = &_line_input;
2197   ip4_address_t in_addr, ext_addr;
2198   u32 in_port, ext_port;
2199   snat_det_map_t *dm;
2200   snat_det_session_t *ses;
2201   snat_det_out_key_t key;
2202   clib_error_t *error = 0;
2203
2204   if (!sm->deterministic)
2205     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
2206
2207   /* Get a line of input. */
2208   if (!unformat_user (input, unformat_line_input, line_input))
2209     return 0;
2210
2211   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2212     {
2213       if (unformat (line_input, "%U:%d %U:%d",
2214                     unformat_ip4_address, &in_addr, &in_port,
2215                     unformat_ip4_address, &ext_addr, &ext_port))
2216         ;
2217       else
2218         {
2219           error = clib_error_return (0, "unknown input '%U'",
2220                                      format_unformat_error, line_input);
2221           goto done;
2222         }
2223     }
2224
2225   unformat_free (line_input);
2226
2227   dm = snat_det_map_by_user (sm, &in_addr);
2228   if (!dm)
2229     vlib_cli_output (vm, "no match");
2230   else
2231     {
2232       key.ext_host_addr = ext_addr;
2233       key.ext_host_port = ntohs ((u16) ext_port);
2234       ses =
2235         snat_det_find_ses_by_in (dm, &in_addr, ntohs ((u16) in_port), key);
2236       if (!ses)
2237         vlib_cli_output (vm, "no match");
2238       else
2239         snat_det_ses_close (dm, ses);
2240     }
2241
2242 done:
2243   unformat_free (line_input);
2244
2245   return error;
2246 }
2247 /* *INDENT-OFF* */
2248
2249 /*?
2250  * @cliexpar
2251  * @cliexstart{set snat workers}
2252  * Set NAT workers if 2 or more workers available, use:
2253  *  vpp# set snat workers 0-2,5
2254  * @cliexend
2255 ?*/
2256 VLIB_CLI_COMMAND (set_workers_command, static) = {
2257   .path = "set nat workers",
2258   .function = set_workers_command_fn,
2259   .short_help = "set nat workers <workers-list>",
2260 };
2261
2262 /*?
2263  * @cliexpar
2264  * @cliexstart{show nat workers}
2265  * Show NAT workers.
2266  *  vpp# show nat workers:
2267  *  2 workers
2268  *    vpp_wk_0
2269  *    vpp_wk_1
2270  * @cliexend
2271 ?*/
2272 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
2273   .path = "show nat workers",
2274   .short_help = "show nat workers",
2275   .function = nat_show_workers_commnad_fn,
2276 };
2277
2278 /*?
2279  * @cliexpar
2280  * @cliexstart{set nat timeout}
2281  * Set values of timeouts for NAT sessions (in seconds), use:
2282  *  vpp# set nat timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90
2283  * To reset default values use:
2284  *  vpp# set nat44 deterministic timeout reset
2285  * @cliexend
2286 ?*/
2287 VLIB_CLI_COMMAND (set_timeout_command, static) = {
2288   .path = "set nat timeout",
2289   .function = set_timeout_command_fn,
2290   .short_help =
2291     "set nat timeout [udp <sec> | tcp-established <sec> "
2292     "tcp-transitory <sec> | icmp <sec> | reset]",
2293 };
2294
2295 /*?
2296  * @cliexpar
2297  * @cliexstart{show nat timeouts}
2298  * Show values of timeouts for NAT sessions.
2299  * vpp# show nat timeouts
2300  * udp timeout: 300sec
2301  * tcp-established timeout: 7440sec
2302  * tcp-transitory timeout: 240sec
2303  * icmp timeout: 60sec
2304  * @cliexend
2305 ?*/
2306 VLIB_CLI_COMMAND (nat_show_timeouts_command, static) = {
2307   .path = "show nat timeouts",
2308   .short_help = "show nat timeouts",
2309   .function = nat_show_timeouts_command_fn,
2310 };
2311
2312 /*?
2313  * @cliexpar
2314  * @cliexstart{nat set logging level}
2315  * To set NAT logging level use:
2316  * Set nat logging level
2317  * @cliexend
2318 ?*/
2319 VLIB_CLI_COMMAND (snat_set_log_level_command, static) = {
2320   .path = "nat set logging level",
2321   .function = snat_set_log_level_command_fn,
2322   .short_help = "nat set logging level <level>",
2323 };
2324
2325 /*?
2326  * @cliexpar
2327  * @cliexstart{snat ipfix logging}
2328  * To enable NAT IPFIX logging use:
2329  *  vpp# nat ipfix logging
2330  * To set IPFIX exporter use:
2331  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
2332  * @cliexend
2333 ?*/
2334 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
2335   .path = "nat ipfix logging",
2336   .function = snat_ipfix_logging_enable_disable_command_fn,
2337   .short_help = "nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
2338 };
2339
2340 /*?
2341  * @cliexpar
2342  * @cliexstart{nat addr-port-assignment-alg}
2343  * Set address and port assignment algorithm
2344  * For the MAP-E CE limit port choice based on PSID use:
2345  *  vpp# nat addr-port-assignment-alg map-e psid 10 psid-offset 6 psid-len 6
2346  * For port range use:
2347  *  vpp# nat addr-port-assignment-alg port-range <start-port> - <end-port>
2348  * To set standard (default) address and port assignment algorithm use:
2349  *  vpp# nat addr-port-assignment-alg default
2350  * @cliexend
2351 ?*/
2352 VLIB_CLI_COMMAND (nat44_set_alloc_addr_and_port_alg_command, static) = {
2353     .path = "nat addr-port-assignment-alg",
2354     .short_help = "nat addr-port-assignment-alg <alg-name> [<alg-params>]",
2355     .function = nat44_set_alloc_addr_and_port_alg_command_fn,
2356 };
2357
2358 /*?
2359  * @cliexpar
2360  * @cliexstart{show nat addr-port-assignment-alg}
2361  * Show address and port assignment algorithm
2362  * @cliexend
2363 ?*/
2364 VLIB_CLI_COMMAND (nat44_show_alloc_addr_and_port_alg_command, static) = {
2365     .path = "show nat addr-port-assignment-alg",
2366     .short_help = "show nat addr-port-assignment-alg",
2367     .function = nat44_show_alloc_addr_and_port_alg_command_fn,
2368 };
2369
2370 /*?
2371  * @cliexpar
2372  * @cliexstart{nat mss-clamping}
2373  * Set TCP MSS rewriting configuration
2374  * To enable TCP MSS rewriting use:
2375  *  vpp# nat mss-clamping 1452
2376  * To disbale TCP MSS rewriting use:
2377  *  vpp# nat mss-clamping disable
2378  * @cliexend
2379 ?*/
2380 VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = {
2381     .path = "nat mss-clamping",
2382     .short_help = "nat mss-clamping <mss-value>|disable",
2383     .function = nat_set_mss_clamping_command_fn,
2384 };
2385
2386 /*?
2387  * @cliexpar
2388  * @cliexstart{show nat mss-clamping}
2389  * Show TCP MSS rewriting configuration
2390  * @cliexend
2391 ?*/
2392 VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = {
2393     .path = "show nat mss-clamping",
2394     .short_help = "show nat mss-clamping",
2395     .function = nat_show_mss_clamping_command_fn,
2396 };
2397
2398 /*?
2399  * @cliexpar
2400  * @cliexstart{nat ha failover}
2401  * Set HA failover (remote settings)
2402  * @cliexend
2403 ?*/
2404 VLIB_CLI_COMMAND (nat_ha_failover_command, static) = {
2405     .path = "nat ha failover",
2406     .short_help = "nat ha failover <ip4-address>:<port> [refresh-interval <sec>]",
2407     .function = nat_ha_failover_command_fn,
2408 };
2409
2410 /*?
2411  * @cliexpar
2412  * @cliexstart{nat ha listener}
2413  * Set HA listener (local settings)
2414  * @cliexend
2415 ?*/
2416 VLIB_CLI_COMMAND (nat_ha_listener_command, static) = {
2417     .path = "nat ha listener",
2418     .short_help = "nat ha listener <ip4-address>:<port> [path-mtu <path-mtu>]",
2419     .function = nat_ha_listener_command_fn,
2420 };
2421
2422 /*?
2423  * @cliexpar
2424  * @cliexstart{show nat ha}
2425  * Show HA configuration/status
2426  * @cliexend
2427 ?*/
2428 VLIB_CLI_COMMAND (nat_show_ha_command, static) = {
2429     .path = "show nat ha",
2430     .short_help = "show nat ha",
2431     .function = nat_show_ha_command_fn,
2432 };
2433
2434 /*?
2435  * @cliexpar
2436  * @cliexstart{nat ha flush}
2437  * Flush the current HA data (for testing)
2438  * @cliexend
2439 ?*/
2440 VLIB_CLI_COMMAND (nat_ha_flush_command, static) = {
2441     .path = "nat ha flush",
2442     .short_help = "nat ha flush",
2443     .function = nat_ha_flush_command_fn,
2444 };
2445
2446 /*?
2447  * @cliexpar
2448  * @cliexstart{nat ha resync}
2449  * Resync HA (resend existing sessions to new failover)
2450  * @cliexend
2451 ?*/
2452 VLIB_CLI_COMMAND (nat_ha_resync_command, static) = {
2453     .path = "nat ha resync",
2454     .short_help = "nat ha resync",
2455     .function = nat_ha_resync_command_fn,
2456 };
2457
2458 /*?
2459  * @cliexpar
2460  * @cliexstart{show nat44 hash tables}
2461  * Show NAT44 hash tables
2462  * @cliexend
2463 ?*/
2464 VLIB_CLI_COMMAND (nat44_show_hash, static) = {
2465   .path = "show nat44 hash tables",
2466   .short_help = "show nat44 hash tables [detail|verbose]",
2467   .function = nat44_show_hash_command_fn,
2468 };
2469
2470 /*?
2471  * @cliexpar
2472  * @cliexstart{nat44 add address}
2473  * Add/delete NAT44 pool address.
2474  * To add NAT44 pool address use:
2475  *  vpp# nat44 add address 172.16.1.3
2476  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
2477  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
2478  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
2479  * @cliexend
2480 ?*/
2481 VLIB_CLI_COMMAND (add_address_command, static) = {
2482   .path = "nat44 add address",
2483   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
2484                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
2485   .function = add_address_command_fn,
2486 };
2487
2488 /*?
2489  * @cliexpar
2490  * @cliexstart{show nat44 summary}
2491  * Show NAT44 summary
2492  * vpp# show nat44 summary
2493  * @cliexend
2494 ?*/
2495 VLIB_CLI_COMMAND (nat44_show_summary_command, static) = {
2496   .path = "show nat44 summary",
2497   .short_help = "show nat44 summary",
2498   .function = nat44_show_summary_command_fn,
2499 };
2500
2501 /*?
2502  * @cliexpar
2503  * @cliexstart{show nat44 addresses}
2504  * Show NAT44 pool addresses.
2505  * vpp# show nat44 addresses
2506  * NAT44 pool addresses:
2507  * 172.16.2.2
2508  *   tenant VRF independent
2509  *   10 busy udp ports
2510  *   0 busy tcp ports
2511  *   0 busy icmp ports
2512  * 172.16.1.3
2513  *   tenant VRF: 10
2514  *   0 busy udp ports
2515  *   2 busy tcp ports
2516  *   0 busy icmp ports
2517  * NAT44 twice-nat pool addresses:
2518  * 10.20.30.72
2519  *   tenant VRF independent
2520  *   0 busy udp ports
2521  *   0 busy tcp ports
2522  *   0 busy icmp ports
2523  * @cliexend
2524 ?*/
2525 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
2526   .path = "show nat44 addresses",
2527   .short_help = "show nat44 addresses",
2528   .function = nat44_show_addresses_command_fn,
2529 };
2530
2531 /*?
2532  * @cliexpar
2533  * @cliexstart{set interface nat44}
2534  * Enable/disable NAT44 feature on the interface.
2535  * To enable NAT44 feature with local network interface use:
2536  *  vpp# set interface nat44 in GigabitEthernet0/8/0
2537  * To enable NAT44 feature with external network interface use:
2538  *  vpp# set interface nat44 out GigabitEthernet0/a/0
2539  * @cliexend
2540 ?*/
2541 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
2542   .path = "set interface nat44",
2543   .function = snat_feature_command_fn,
2544   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
2545                 "[del]",
2546 };
2547
2548 /*?
2549  * @cliexpar
2550  * @cliexstart{show nat44 interfaces}
2551  * Show interfaces with NAT44 feature.
2552  * vpp# show nat44 interfaces
2553  * NAT44 interfaces:
2554  *  GigabitEthernet0/8/0 in
2555  *  GigabitEthernet0/a/0 out
2556  * @cliexend
2557 ?*/
2558 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
2559   .path = "show nat44 interfaces",
2560   .short_help = "show nat44 interfaces",
2561   .function = nat44_show_interfaces_command_fn,
2562 };
2563
2564 /*?
2565  * @cliexpar
2566  * @cliexstart{nat44 add static mapping}
2567  * Static mapping allows hosts on the external network to initiate connection
2568  * to to the local network host.
2569  * To create static mapping between local host address 10.0.0.3 port 6303 and
2570  * external address 4.4.4.4 port 3606 for TCP protocol use:
2571  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
2572  * If not runnig "static mapping only" NAT plugin mode use before:
2573  *  vpp# nat44 add address 4.4.4.4
2574  * To create address only static mapping between local and external address use:
2575  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
2576  * To create ICMP static mapping between local and external with ICMP echo
2577  * identifier 10 use:
2578  *  vpp# nat44 add static mapping icmp local 10.0.0.3 10 external 4.4.4.4 10
2579  * @cliexend
2580 ?*/
2581 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
2582   .path = "nat44 add static mapping",
2583   .function = add_static_mapping_command_fn,
2584   .short_help =
2585     "nat44 add static mapping tcp|udp|icmp local <addr> [<port|icmp-echo-id>] "
2586     "external <addr> [<port|icmp-echo-id>] [vrf <table-id>] [twice-nat|self-twice-nat] "
2587     "[out2in-only] [del]",
2588 };
2589
2590 /*?
2591  * @cliexpar
2592  * @cliexstart{nat44 add identity mapping}
2593  * Identity mapping translate an IP address to itself.
2594  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
2595  * use:
2596  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
2597  * To create identity mapping for address 10.0.0.3 use:
2598  *  vpp# nat44 add identity mapping 10.0.0.3
2599  * To create identity mapping for DHCP addressed interface use:
2600  *  vpp# nat44 add identity mapping external GigabitEthernet0/a/0 tcp 3606
2601  * @cliexend
2602 ?*/
2603 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
2604   .path = "nat44 add identity mapping",
2605   .function = add_identity_mapping_command_fn,
2606   .short_help = "nat44 add identity mapping <ip4-addr>|external <interface> "
2607     "[<protocol> <port>] [vrf <table-id>] [del]",
2608 };
2609
2610 /*?
2611  * @cliexpar
2612  * @cliexstart{nat44 add load-balancing static mapping}
2613  * Service load balancing using NAT44
2614  * To add static mapping with load balancing for service with external IP
2615  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
2616  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
2617  *  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
2618  * @cliexend
2619 ?*/
2620 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
2621   .path = "nat44 add load-balancing static mapping",
2622   .function = add_lb_static_mapping_command_fn,
2623   .short_help =
2624     "nat44 add load-balancing static mapping protocol tcp|udp "
2625     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2626     "probability <n> [twice-nat|self-twice-nat] [out2in-only] "
2627     "[affinity <timeout-seconds>] [del]",
2628 };
2629
2630 /*?
2631  * @cliexpar
2632  * @cliexstart{nat44 add load-balancing static mapping}
2633  * Modify service load balancing using NAT44
2634  * To add new back-end server 10.100.10.30:8080 for service load balancing
2635  * static mapping with external IP address 1.2.3.4 and TCP port 80 use:
2636  *  vpp# nat44 add load-balancing back-end protocol tcp external 1.2.3.4:80 local 10.100.10.30:8080 probability 25
2637  * @cliexend
2638 ?*/
2639 VLIB_CLI_COMMAND (add_lb_backend_command, static) = {
2640   .path = "nat44 add load-balancing back-end",
2641   .function = add_lb_backend_command_fn,
2642   .short_help =
2643     "nat44 add load-balancing back-end protocol tcp|udp "
2644     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2645     "probability <n> [del]",
2646 };
2647
2648 /*?
2649  * @cliexpar
2650  * @cliexstart{show nat44 static mappings}
2651  * Show NAT44 static mappings.
2652  * vpp# show nat44 static mappings
2653  * NAT44 static mappings:
2654  *  local 10.0.0.3 external 4.4.4.4 vrf 0
2655  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
2656  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
2657  *   local 10.100.10.10:8080 probability 80
2658  *   local 10.100.10.20:8080 probability 20
2659  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
2660  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
2661  * @cliexend
2662 ?*/
2663 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
2664   .path = "show nat44 static mappings",
2665   .short_help = "show nat44 static mappings",
2666   .function = nat44_show_static_mappings_command_fn,
2667 };
2668
2669 /*?
2670  * @cliexpar
2671  * @cliexstart{nat44 add interface address}
2672  * Use NAT44 pool address from specific interfce
2673  * To add NAT44 pool address from specific interface use:
2674  *  vpp# nat44 add interface address GigabitEthernet0/8/0
2675  * @cliexend
2676 ?*/
2677 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
2678     .path = "nat44 add interface address",
2679     .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
2680     .function = snat_add_interface_address_command_fn,
2681 };
2682
2683 /*?
2684  * @cliexpar
2685  * @cliexstart{show nat44 interface address}
2686  * Show NAT44 pool address interfaces
2687  * vpp# show nat44 interface address
2688  * NAT44 pool address interfaces:
2689  *  GigabitEthernet0/a/0
2690  * NAT44 twice-nat pool address interfaces:
2691  *  GigabitEthernet0/8/0
2692  * @cliexend
2693 ?*/
2694 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
2695   .path = "show nat44 interface address",
2696   .short_help = "show nat44 interface address",
2697   .function = nat44_show_interface_address_command_fn,
2698 };
2699
2700 /*?
2701  * @cliexpar
2702  * @cliexstart{show nat44 sessions}
2703  * Show NAT44 sessions.
2704  * @cliexend
2705 ?*/
2706 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
2707   .path = "show nat44 sessions",
2708   .short_help = "show nat44 sessions [detail|metrics]",
2709   .function = nat44_show_sessions_command_fn,
2710 };
2711
2712 /*?
2713  * @cliexpar
2714  * @cliexstart{set nat44 session limit}
2715  * Set NAT44 session limit.
2716  * @cliexend
2717 ?*/
2718 VLIB_CLI_COMMAND (nat44_set_session_limit_command, static) = {
2719   .path = "set nat44 session limit",
2720   .short_help = "set nat44 session limit <limit> [vrf <table-id>]",
2721   .function = nat44_set_session_limit_command_fn,
2722 };
2723
2724 /*?
2725  * @cliexpar
2726  * @cliexstart{nat44 del user}
2727  * To delete all NAT44 user sessions:
2728  *  vpp# nat44 del user 10.0.0.3
2729  * @cliexend
2730 ?*/
2731 VLIB_CLI_COMMAND (nat44_del_user_command, static) = {
2732     .path = "nat44 del user",
2733     .short_help = "nat44 del user <addr> [fib <index>]",
2734     .function = nat44_del_user_command_fn,
2735 };
2736
2737 /*?
2738  * @cliexpar
2739  * @cliexstart{clear nat44 sessions}
2740  * To clear all NAT44 sessions
2741  *  vpp# clear nat44 sessions
2742  * @cliexend
2743 ?*/
2744 VLIB_CLI_COMMAND (nat44_clear_sessions_command, static) = {
2745     .path = "clear nat44 sessions",
2746     .short_help = "clear nat44 sessions",
2747     .function = nat44_clear_sessions_command_fn,
2748 };
2749
2750 /*?
2751  * @cliexpar
2752  * @cliexstart{nat44 del session}
2753  * To administratively delete NAT44 session by inside address and port use:
2754  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
2755  * To administratively delete NAT44 session by outside address and port use:
2756  *  vpp# nat44 del session out 1.0.0.3:6033 udp
2757  * @cliexend
2758 ?*/
2759 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
2760     .path = "nat44 del session",
2761     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>] [external-host <addr>:<port>]",
2762     .function = nat44_del_session_command_fn,
2763 };
2764
2765 /*?
2766  * @cliexpar
2767  * @cliexstart{nat44 forwarding}
2768  * Enable or disable forwarding
2769  * Forward packets which don't match existing translation
2770  * or static mapping instead of dropping them.
2771  * To enable forwarding, use:
2772  *  vpp# nat44 forwarding enable
2773  * To disable forwarding, use:
2774  *  vpp# nat44 forwarding disable
2775  * @cliexend
2776 ?*/
2777 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
2778   .path = "nat44 forwarding",
2779   .short_help = "nat44 forwarding enable|disable",
2780   .function = snat_forwarding_set_command_fn,
2781 };
2782
2783 /*?
2784  * @cliexpar
2785  * @cliexstart{nat44 deterministic add}
2786  * Create bijective mapping of inside address to outside address and port range
2787  * pairs, with the purpose of enabling deterministic NAT to reduce logging in
2788  * CGN deployments.
2789  * To create deterministic mapping between inside network 10.0.0.0/18 and
2790  * outside network 1.1.1.0/30 use:
2791  * # vpp# nat44 deterministic add in 10.0.0.0/18 out 1.1.1.0/30
2792  * @cliexend
2793 ?*/
2794 VLIB_CLI_COMMAND (snat_det_map_command, static) = {
2795     .path = "nat44 deterministic add",
2796     .short_help = "nat44 deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
2797     .function = snat_det_map_command_fn,
2798 };
2799
2800 /*?
2801  * @cliexpar
2802  * @cliexpstart{show nat44 deterministic mappings}
2803  * Show NAT44 deterministic mappings
2804  * vpp# show nat44 deterministic mappings
2805  * NAT44 deterministic mappings:
2806  *  in 10.0.0.0/24 out 1.1.1.1/32
2807  *   outside address sharing ratio: 256
2808  *   number of ports per inside host: 252
2809  *   sessions number: 0
2810  * @cliexend
2811 ?*/
2812 VLIB_CLI_COMMAND (nat44_det_show_mappings_command, static) = {
2813     .path = "show nat44 deterministic mappings",
2814     .short_help = "show nat44 deterministic mappings",
2815     .function = nat44_det_show_mappings_command_fn,
2816 };
2817
2818 /*?
2819  * @cliexpar
2820  * @cliexstart{nat44 deterministic forward}
2821  * Return outside address and port range from inside address for deterministic
2822  * NAT.
2823  * To obtain outside address and port of inside host use:
2824  *  vpp# nat44 deterministic forward 10.0.0.2
2825  *  1.1.1.0:<1054-1068>
2826  * @cliexend
2827 ?*/
2828 VLIB_CLI_COMMAND (snat_det_forward_command, static) = {
2829     .path = "nat44 deterministic forward",
2830     .short_help = "nat44 deterministic forward <addr>",
2831     .function = snat_det_forward_command_fn,
2832 };
2833
2834 /*?
2835  * @cliexpar
2836  * @cliexstart{nat44 deterministic reverse}
2837  * Return inside address from outside address and port for deterministic NAT.
2838  * To obtain inside host address from outside address and port use:
2839  *  #vpp nat44 deterministic reverse 1.1.1.1:1276
2840  *  10.0.16.16
2841  * @cliexend
2842 ?*/
2843 VLIB_CLI_COMMAND (snat_det_reverse_command, static) = {
2844     .path = "nat44 deterministic reverse",
2845     .short_help = "nat44 deterministic reverse <addr>:<port>",
2846     .function = snat_det_reverse_command_fn,
2847 };
2848
2849 /*?
2850  * @cliexpar
2851  * @cliexstart{show nat44 deterministic sessions}
2852  * Show NAT44 deterministic sessions.
2853  * vpp# show nat44 deterministic sessions
2854  * NAT44 deterministic sessions:
2855  *   in 10.0.0.3:3005 out 1.1.1.2:1146 external host 172.16.1.2:3006 state: udp-active expire: 306
2856  *   in 10.0.0.3:3000 out 1.1.1.2:1141 external host 172.16.1.2:3001 state: udp-active expire: 306
2857  *   in 10.0.0.4:3005 out 1.1.1.2:1177 external host 172.16.1.2:3006 state: udp-active expire: 306
2858  * @cliexend
2859 ?*/
2860 VLIB_CLI_COMMAND (nat44_det_show_sessions_command, static) = {
2861   .path = "show nat44 deterministic sessions",
2862   .short_help = "show nat44 deterministic sessions",
2863   .function = nat44_det_show_sessions_command_fn,
2864 };
2865
2866 /*?
2867  * @cliexpar
2868  * @cliexstart{nat44 deterministic close session out}
2869  * Close session using outside ip address and port
2870  * and external ip address and port, use:
2871  *  vpp# nat44 deterministic close session out 1.1.1.1:1276 2.2.2.2:2387
2872  * @cliexend
2873 ?*/
2874 VLIB_CLI_COMMAND (snat_det_close_sesion_out_command, static) = {
2875   .path = "nat44 deterministic close session out",
2876   .short_help = "nat44 deterministic close session out "
2877                 "<out_addr>:<out_port> <ext_addr>:<ext_port>",
2878   .function = snat_det_close_session_out_fn,
2879 };
2880
2881 /*?
2882  * @cliexpar
2883  * @cliexstart{nat44 deterministic close session in}
2884  * Close session using inside ip address and port
2885  * and external ip address and port, use:
2886  *  vpp# nat44 deterministic close session in 3.3.3.3:3487 2.2.2.2:2387
2887  * @cliexend
2888 ?*/
2889 VLIB_CLI_COMMAND (snat_det_close_session_in_command, static) = {
2890   .path = "nat44 deterministic close session in",
2891   .short_help = "nat44 deterministic close session in "
2892                 "<in_addr>:<in_port> <ext_addr>:<ext_port>",
2893   .function = snat_det_close_session_in_fn,
2894 };
2895
2896 /* *INDENT-ON* */
2897
2898 /*
2899  * fd.io coding-style-patch-verification: ON
2900  *
2901  * Local Variables:
2902  * eval: (c-set-style "gnu")
2903  * End:
2904  */