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