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