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