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