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