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