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