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