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