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