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