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