nat: move nat64 to a subfeature
[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/lib/nat_inlines.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       else if (unformat (line_input, "tcp-established %u",
1779                          &sm->tcp_established_timeout));
1780       else if (unformat (line_input, "tcp-transitory %u",
1781                          &sm->tcp_transitory_timeout));
1782       else if (unformat (line_input, "icmp %u", &sm->icmp_timeout));
1783       else if (unformat (line_input, "reset"))
1784         {
1785           sm->udp_timeout = SNAT_UDP_TIMEOUT;
1786           sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
1787           sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
1788           sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
1789         }
1790       else
1791         {
1792           error = clib_error_return (0, "unknown input '%U'",
1793                                      format_unformat_error, line_input);
1794           goto done;
1795         }
1796     }
1797 done:
1798   unformat_free (line_input);
1799   return error;
1800 }
1801
1802 static clib_error_t *
1803 nat_show_timeouts_command_fn (vlib_main_t * vm,
1804                               unformat_input_t * input,
1805                               vlib_cli_command_t * cmd)
1806 {
1807   snat_main_t *sm = &snat_main;
1808
1809   vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
1810   vlib_cli_output (vm, "tcp-established timeout: %dsec",
1811                    sm->tcp_established_timeout);
1812   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
1813                    sm->tcp_transitory_timeout);
1814   vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
1815
1816   return 0;
1817 }
1818
1819 static clib_error_t *
1820 nat44_debug_fib_expire_command_fn (vlib_main_t * vm,
1821                                    unformat_input_t * input,
1822                                    vlib_cli_command_t * cmd)
1823 {
1824   unformat_input_t _line_input, *line_input = &_line_input;
1825   clib_error_t *error = 0;
1826   u32 fib = ~0;
1827
1828   /* Get a line of input. */
1829   if (!unformat_user (input, unformat_line_input, line_input))
1830     return 0;
1831
1832   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1833     {
1834       if (unformat (line_input, "%u", &fib))
1835         ;
1836       else
1837         {
1838           error = clib_error_return (0, "unknown input '%U'",
1839                                      format_unformat_error, line_input);
1840           goto done;
1841         }
1842     }
1843   expire_per_vrf_sessions (fib);
1844 done:
1845   unformat_free (line_input);
1846   return error;
1847 }
1848
1849 static clib_error_t *
1850 nat44_debug_fib_registration_command_fn (vlib_main_t * vm,
1851                                          unformat_input_t * input,
1852                                          vlib_cli_command_t * cmd)
1853 {
1854   snat_main_t *sm = &snat_main;
1855   snat_main_per_thread_data_t *tsm;
1856   per_vrf_sessions_t *per_vrf_sessions;
1857
1858   vlib_cli_output (vm, "VRF registration debug:");
1859   vec_foreach (tsm, sm->per_thread_data)
1860   {
1861     vlib_cli_output (vm, "thread %u:", tsm->thread_index);
1862     vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
1863     {
1864       vlib_cli_output (vm, "rx fib %u tx fib %u ses count %u %s",
1865                        per_vrf_sessions->rx_fib_index,
1866                        per_vrf_sessions->tx_fib_index,
1867                        per_vrf_sessions->ses_count,
1868                        per_vrf_sessions->expired ? "expired" : "");
1869     }
1870   }
1871   return 0;
1872 }
1873
1874 /* *INDENT-OFF* */
1875
1876 /*?
1877 ?*/
1878 VLIB_CLI_COMMAND (nat44_debug_fib_expire_command, static) = {
1879   .path = "debug nat44 fib expire",
1880   .short_help = "debug nat44 fib expire <fib-index>",
1881   .function = nat44_debug_fib_expire_command_fn,
1882 };
1883
1884 /*?
1885 ?*/
1886 VLIB_CLI_COMMAND (nat44_debug_fib_registration_command, static) = {
1887   .path = "debug nat44 fib registration",
1888   .short_help = "debug nat44 fib registration",
1889   .function = nat44_debug_fib_registration_command_fn,
1890 };
1891
1892 /*?
1893  * @cliexpar
1894  * @cliexstart{set snat workers}
1895  * Set NAT workers if 2 or more workers available, use:
1896  *  vpp# set snat workers 0-2,5
1897  * @cliexend
1898 ?*/
1899 VLIB_CLI_COMMAND (set_workers_command, static) = {
1900   .path = "set nat workers",
1901   .function = set_workers_command_fn,
1902   .short_help = "set nat workers <workers-list>",
1903 };
1904
1905 /*?
1906  * @cliexpar
1907  * @cliexstart{show nat workers}
1908  * Show NAT workers.
1909  *  vpp# show nat workers:
1910  *  2 workers
1911  *    vpp_wk_0
1912  *    vpp_wk_1
1913  * @cliexend
1914 ?*/
1915 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
1916   .path = "show nat workers",
1917   .short_help = "show nat workers",
1918   .function = nat_show_workers_commnad_fn,
1919 };
1920
1921 /*?
1922  * @cliexpar
1923  * @cliexstart{set nat timeout}
1924  * Set values of timeouts for NAT sessions (in seconds), use:
1925  *  vpp# set nat timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90
1926  * To reset default values use:
1927  *  vpp# set nat timeout reset
1928  * @cliexend
1929 ?*/
1930 VLIB_CLI_COMMAND (set_timeout_command, static) = {
1931   .path = "set nat timeout",
1932   .function = set_timeout_command_fn,
1933   .short_help =
1934     "set nat timeout [udp <sec> | tcp-established <sec> "
1935     "tcp-transitory <sec> | icmp <sec> | reset]",
1936 };
1937
1938 /*?
1939  * @cliexpar
1940  * @cliexstart{show nat timeouts}
1941  * Show values of timeouts for NAT sessions.
1942  * vpp# show nat timeouts
1943  * udp timeout: 300sec
1944  * tcp-established timeout: 7440sec
1945  * tcp-transitory timeout: 240sec
1946  * icmp timeout: 60sec
1947  * @cliexend
1948 ?*/
1949 VLIB_CLI_COMMAND (nat_show_timeouts_command, static) = {
1950   .path = "show nat timeouts",
1951   .short_help = "show nat timeouts",
1952   .function = nat_show_timeouts_command_fn,
1953 };
1954
1955 /*?
1956  * @cliexpar
1957  * @cliexstart{nat set logging level}
1958  * To set NAT logging level use:
1959  * Set nat logging level
1960  * @cliexend
1961 ?*/
1962 VLIB_CLI_COMMAND (snat_set_log_level_command, static) = {
1963   .path = "nat set logging level",
1964   .function = snat_set_log_level_command_fn,
1965   .short_help = "nat set logging level <level>",
1966 };
1967
1968 /*?
1969  * @cliexpar
1970  * @cliexstart{snat ipfix logging}
1971  * To enable NAT IPFIX logging use:
1972  *  vpp# nat ipfix logging
1973  * To set IPFIX exporter use:
1974  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
1975  * @cliexend
1976 ?*/
1977 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
1978   .path = "nat ipfix logging",
1979   .function = snat_ipfix_logging_enable_disable_command_fn,
1980   .short_help = "nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
1981 };
1982
1983 /*?
1984  * @cliexpar
1985  * @cliexstart{nat addr-port-assignment-alg}
1986  * Set address and port assignment algorithm
1987  * For the MAP-E CE limit port choice based on PSID use:
1988  *  vpp# nat addr-port-assignment-alg map-e psid 10 psid-offset 6 psid-len 6
1989  * For port range use:
1990  *  vpp# nat addr-port-assignment-alg port-range <start-port> - <end-port>
1991  * To set standard (default) address and port assignment algorithm use:
1992  *  vpp# nat addr-port-assignment-alg default
1993  * @cliexend
1994 ?*/
1995 VLIB_CLI_COMMAND (nat44_set_alloc_addr_and_port_alg_command, static) = {
1996     .path = "nat addr-port-assignment-alg",
1997     .short_help = "nat addr-port-assignment-alg <alg-name> [<alg-params>]",
1998     .function = nat44_set_alloc_addr_and_port_alg_command_fn,
1999 };
2000
2001 /*?
2002  * @cliexpar
2003  * @cliexstart{show nat addr-port-assignment-alg}
2004  * Show address and port assignment algorithm
2005  * @cliexend
2006 ?*/
2007 VLIB_CLI_COMMAND (nat44_show_alloc_addr_and_port_alg_command, static) = {
2008     .path = "show nat addr-port-assignment-alg",
2009     .short_help = "show nat addr-port-assignment-alg",
2010     .function = nat44_show_alloc_addr_and_port_alg_command_fn,
2011 };
2012
2013 /*?
2014  * @cliexpar
2015  * @cliexstart{nat mss-clamping}
2016  * Set TCP MSS rewriting configuration
2017  * To enable TCP MSS rewriting use:
2018  *  vpp# nat mss-clamping 1452
2019  * To disbale TCP MSS rewriting use:
2020  *  vpp# nat mss-clamping disable
2021  * @cliexend
2022 ?*/
2023 VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = {
2024     .path = "nat mss-clamping",
2025     .short_help = "nat mss-clamping <mss-value>|disable",
2026     .function = nat_set_mss_clamping_command_fn,
2027 };
2028
2029 /*?
2030  * @cliexpar
2031  * @cliexstart{show nat mss-clamping}
2032  * Show TCP MSS rewriting configuration
2033  * @cliexend
2034 ?*/
2035 VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = {
2036     .path = "show nat mss-clamping",
2037     .short_help = "show nat mss-clamping",
2038     .function = nat_show_mss_clamping_command_fn,
2039 };
2040
2041 /*?
2042  * @cliexpar
2043  * @cliexstart{nat ha failover}
2044  * Set HA failover (remote settings)
2045  * @cliexend
2046 ?*/
2047 VLIB_CLI_COMMAND (nat_ha_failover_command, static) = {
2048     .path = "nat ha failover",
2049     .short_help = "nat ha failover <ip4-address>:<port> [refresh-interval <sec>]",
2050     .function = nat_ha_failover_command_fn,
2051 };
2052
2053 /*?
2054  * @cliexpar
2055  * @cliexstart{nat ha listener}
2056  * Set HA listener (local settings)
2057  * @cliexend
2058 ?*/
2059 VLIB_CLI_COMMAND (nat_ha_listener_command, static) = {
2060     .path = "nat ha listener",
2061     .short_help = "nat ha listener <ip4-address>:<port> [path-mtu <path-mtu>]",
2062     .function = nat_ha_listener_command_fn,
2063 };
2064
2065 /*?
2066  * @cliexpar
2067  * @cliexstart{show nat ha}
2068  * Show HA configuration/status
2069  * @cliexend
2070 ?*/
2071 VLIB_CLI_COMMAND (nat_show_ha_command, static) = {
2072     .path = "show nat ha",
2073     .short_help = "show nat ha",
2074     .function = nat_show_ha_command_fn,
2075 };
2076
2077 /*?
2078  * @cliexpar
2079  * @cliexstart{nat ha flush}
2080  * Flush the current HA data (for testing)
2081  * @cliexend
2082 ?*/
2083 VLIB_CLI_COMMAND (nat_ha_flush_command, static) = {
2084     .path = "nat ha flush",
2085     .short_help = "nat ha flush",
2086     .function = nat_ha_flush_command_fn,
2087 };
2088
2089 /*?
2090  * @cliexpar
2091  * @cliexstart{nat ha resync}
2092  * Resync HA (resend existing sessions to new failover)
2093  * @cliexend
2094 ?*/
2095 VLIB_CLI_COMMAND (nat_ha_resync_command, static) = {
2096     .path = "nat ha resync",
2097     .short_help = "nat ha resync",
2098     .function = nat_ha_resync_command_fn,
2099 };
2100
2101 /*?
2102  * @cliexpar
2103  * @cliexstart{show nat44 hash tables}
2104  * Show NAT44 hash tables
2105  * @cliexend
2106 ?*/
2107 VLIB_CLI_COMMAND (nat44_show_hash, static) = {
2108   .path = "show nat44 hash tables",
2109   .short_help = "show nat44 hash tables [detail|verbose]",
2110   .function = nat44_show_hash_command_fn,
2111 };
2112
2113 /*?
2114  * @cliexpar
2115  * @cliexstart{nat44 add address}
2116  * Add/delete NAT44 pool address.
2117  * To add NAT44 pool address use:
2118  *  vpp# nat44 add address 172.16.1.3
2119  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
2120  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
2121  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
2122  * @cliexend
2123 ?*/
2124 VLIB_CLI_COMMAND (add_address_command, static) = {
2125   .path = "nat44 add address",
2126   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
2127                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
2128   .function = add_address_command_fn,
2129 };
2130
2131 /*?
2132  * @cliexpar
2133  * @cliexstart{show nat44 summary}
2134  * Show NAT44 summary
2135  * vpp# show nat44 summary
2136  * @cliexend
2137 ?*/
2138 VLIB_CLI_COMMAND (nat44_show_summary_command, static) = {
2139   .path = "show nat44 summary",
2140   .short_help = "show nat44 summary",
2141   .function = nat44_show_summary_command_fn,
2142 };
2143
2144 /*?
2145  * @cliexpar
2146  * @cliexstart{show nat44 addresses}
2147  * Show NAT44 pool addresses.
2148  * vpp# show nat44 addresses
2149  * NAT44 pool addresses:
2150  * 172.16.2.2
2151  *   tenant VRF independent
2152  *   10 busy udp ports
2153  *   0 busy tcp ports
2154  *   0 busy icmp ports
2155  * 172.16.1.3
2156  *   tenant VRF: 10
2157  *   0 busy udp ports
2158  *   2 busy tcp ports
2159  *   0 busy icmp ports
2160  * NAT44 twice-nat pool addresses:
2161  * 10.20.30.72
2162  *   tenant VRF independent
2163  *   0 busy udp ports
2164  *   0 busy tcp ports
2165  *   0 busy icmp ports
2166  * @cliexend
2167 ?*/
2168 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
2169   .path = "show nat44 addresses",
2170   .short_help = "show nat44 addresses",
2171   .function = nat44_show_addresses_command_fn,
2172 };
2173
2174 /*?
2175  * @cliexpar
2176  * @cliexstart{set interface nat44}
2177  * Enable/disable NAT44 feature on the interface.
2178  * To enable NAT44 feature with local network interface use:
2179  *  vpp# set interface nat44 in GigabitEthernet0/8/0
2180  * To enable NAT44 feature with external network interface use:
2181  *  vpp# set interface nat44 out GigabitEthernet0/a/0
2182  * @cliexend
2183 ?*/
2184 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
2185   .path = "set interface nat44",
2186   .function = snat_feature_command_fn,
2187   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
2188                 "[del]",
2189 };
2190
2191 /*?
2192  * @cliexpar
2193  * @cliexstart{show nat44 interfaces}
2194  * Show interfaces with NAT44 feature.
2195  * vpp# show nat44 interfaces
2196  * NAT44 interfaces:
2197  *  GigabitEthernet0/8/0 in
2198  *  GigabitEthernet0/a/0 out
2199  * @cliexend
2200 ?*/
2201 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
2202   .path = "show nat44 interfaces",
2203   .short_help = "show nat44 interfaces",
2204   .function = nat44_show_interfaces_command_fn,
2205 };
2206
2207 /*?
2208  * @cliexpar
2209  * @cliexstart{nat44 add static mapping}
2210  * Static mapping allows hosts on the external network to initiate connection
2211  * to to the local network host.
2212  * To create static mapping between local host address 10.0.0.3 port 6303 and
2213  * external address 4.4.4.4 port 3606 for TCP protocol use:
2214  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
2215  * If not runnig "static mapping only" NAT plugin mode use before:
2216  *  vpp# nat44 add address 4.4.4.4
2217  * To create address only static mapping between local and external address use:
2218  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
2219  * To create ICMP static mapping between local and external with ICMP echo
2220  * identifier 10 use:
2221  *  vpp# nat44 add static mapping icmp local 10.0.0.3 10 external 4.4.4.4 10
2222  * To force use of specific pool address, vrf independent
2223  *  vpp# nat44 add static mapping local 10.0.0.2 1234 external 10.0.2.2 1234 twice-nat exact 10.0.1.2
2224  * @cliexend
2225 ?*/
2226 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
2227   .path = "nat44 add static mapping",
2228   .function = add_static_mapping_command_fn,
2229   .short_help =
2230     "nat44 add static mapping tcp|udp|icmp local <addr> [<port|icmp-echo-id>] "
2231     "external <addr> [<port|icmp-echo-id>] [vrf <table-id>] [twice-nat|self-twice-nat] "
2232     "[out2in-only] [exact <pool-addr>] [del]",
2233 };
2234
2235 /*?
2236  * @cliexpar
2237  * @cliexstart{nat44 add identity mapping}
2238  * Identity mapping translate an IP address to itself.
2239  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
2240  * use:
2241  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
2242  * To create identity mapping for address 10.0.0.3 use:
2243  *  vpp# nat44 add identity mapping 10.0.0.3
2244  * To create identity mapping for DHCP addressed interface use:
2245  *  vpp# nat44 add identity mapping external GigabitEthernet0/a/0 tcp 3606
2246  * @cliexend
2247 ?*/
2248 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
2249   .path = "nat44 add identity mapping",
2250   .function = add_identity_mapping_command_fn,
2251   .short_help = "nat44 add identity mapping <ip4-addr>|external <interface> "
2252     "[<protocol> <port>] [vrf <table-id>] [del]",
2253 };
2254
2255 /*?
2256  * @cliexpar
2257  * @cliexstart{nat44 add load-balancing static mapping}
2258  * Service load balancing using NAT44
2259  * To add static mapping with load balancing for service with external IP
2260  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
2261  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
2262  *  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
2263  * @cliexend
2264 ?*/
2265 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
2266   .path = "nat44 add load-balancing static mapping",
2267   .function = add_lb_static_mapping_command_fn,
2268   .short_help =
2269     "nat44 add load-balancing static mapping protocol tcp|udp "
2270     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2271     "probability <n> [twice-nat|self-twice-nat] [out2in-only] "
2272     "[affinity <timeout-seconds>] [del]",
2273 };
2274
2275 /*?
2276  * @cliexpar
2277  * @cliexstart{nat44 add load-balancing static mapping}
2278  * Modify service load balancing using NAT44
2279  * To add new back-end server 10.100.10.30:8080 for service load balancing
2280  * static mapping with external IP address 1.2.3.4 and TCP port 80 use:
2281  *  vpp# nat44 add load-balancing back-end protocol tcp external 1.2.3.4:80 local 10.100.10.30:8080 probability 25
2282  * @cliexend
2283 ?*/
2284 VLIB_CLI_COMMAND (add_lb_backend_command, static) = {
2285   .path = "nat44 add load-balancing back-end",
2286   .function = add_lb_backend_command_fn,
2287   .short_help =
2288     "nat44 add load-balancing back-end protocol tcp|udp "
2289     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2290     "probability <n> [del]",
2291 };
2292
2293 /*?
2294  * @cliexpar
2295  * @cliexstart{show nat44 static mappings}
2296  * Show NAT44 static mappings.
2297  * vpp# show nat44 static mappings
2298  * NAT44 static mappings:
2299  *  local 10.0.0.3 external 4.4.4.4 vrf 0
2300  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
2301  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
2302  *   local 10.100.10.10:8080 probability 80
2303  *   local 10.100.10.20:8080 probability 20
2304  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
2305  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
2306  * @cliexend
2307 ?*/
2308 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
2309   .path = "show nat44 static mappings",
2310   .short_help = "show nat44 static mappings",
2311   .function = nat44_show_static_mappings_command_fn,
2312 };
2313
2314 /*?
2315  * @cliexpar
2316  * @cliexstart{nat44 add interface address}
2317  * Use NAT44 pool address from specific interfce
2318  * To add NAT44 pool address from specific interface use:
2319  *  vpp# nat44 add interface address GigabitEthernet0/8/0
2320  * @cliexend
2321 ?*/
2322 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
2323     .path = "nat44 add interface address",
2324     .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
2325     .function = snat_add_interface_address_command_fn,
2326 };
2327
2328 /*?
2329  * @cliexpar
2330  * @cliexstart{show nat44 interface address}
2331  * Show NAT44 pool address interfaces
2332  * vpp# show nat44 interface address
2333  * NAT44 pool address interfaces:
2334  *  GigabitEthernet0/a/0
2335  * NAT44 twice-nat pool address interfaces:
2336  *  GigabitEthernet0/8/0
2337  * @cliexend
2338 ?*/
2339 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
2340   .path = "show nat44 interface address",
2341   .short_help = "show nat44 interface address",
2342   .function = nat44_show_interface_address_command_fn,
2343 };
2344
2345 /*?
2346  * @cliexpar
2347  * @cliexstart{show nat44 sessions}
2348  * Show NAT44 sessions.
2349  * @cliexend
2350 ?*/
2351 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
2352   .path = "show nat44 sessions",
2353   .short_help = "show nat44 sessions [detail|metrics]",
2354   .function = nat44_show_sessions_command_fn,
2355 };
2356
2357 /*?
2358  * @cliexpar
2359  * @cliexstart{set nat44 session limit}
2360  * Set NAT44 session limit.
2361  * @cliexend
2362 ?*/
2363 VLIB_CLI_COMMAND (nat44_set_session_limit_command, static) = {
2364   .path = "set nat44 session limit",
2365   .short_help = "set nat44 session limit <limit> [vrf <table-id>]",
2366   .function = nat44_set_session_limit_command_fn,
2367 };
2368
2369 /*?
2370  * @cliexpar
2371  * @cliexstart{nat44 del user}
2372  * To delete all NAT44 user sessions:
2373  *  vpp# nat44 del user 10.0.0.3
2374  * @cliexend
2375 ?*/
2376 VLIB_CLI_COMMAND (nat44_del_user_command, static) = {
2377     .path = "nat44 del user",
2378     .short_help = "nat44 del user <addr> [fib <index>]",
2379     .function = nat44_del_user_command_fn,
2380 };
2381
2382 /*?
2383  * @cliexpar
2384  * @cliexstart{clear nat44 sessions}
2385  * To clear all NAT44 sessions
2386  *  vpp# clear nat44 sessions
2387  * @cliexend
2388 ?*/
2389 VLIB_CLI_COMMAND (nat44_clear_sessions_command, static) = {
2390     .path = "clear nat44 sessions",
2391     .short_help = "clear nat44 sessions",
2392     .function = nat44_clear_sessions_command_fn,
2393 };
2394
2395 /*?
2396  * @cliexpar
2397  * @cliexstart{nat44 del session}
2398  * To administratively delete NAT44 session by inside address and port use:
2399  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
2400  * To administratively delete NAT44 session by outside address and port use:
2401  *  vpp# nat44 del session out 1.0.0.3:6033 udp
2402  * @cliexend
2403 ?*/
2404 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
2405     .path = "nat44 del session",
2406     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>] [external-host <addr>:<port>]",
2407     .function = nat44_del_session_command_fn,
2408 };
2409
2410 /*?
2411  * @cliexpar
2412  * @cliexstart{nat44 forwarding}
2413  * Enable or disable forwarding
2414  * Forward packets which don't match existing translation
2415  * or static mapping instead of dropping them.
2416  * To enable forwarding, use:
2417  *  vpp# nat44 forwarding enable
2418  * To disable forwarding, use:
2419  *  vpp# nat44 forwarding disable
2420  * @cliexend
2421 ?*/
2422 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
2423   .path = "nat44 forwarding",
2424   .short_help = "nat44 forwarding enable|disable",
2425   .function = snat_forwarding_set_command_fn,
2426 };
2427
2428 /* *INDENT-ON* */
2429
2430 /*
2431  * fd.io coding-style-patch-verification: ON
2432  *
2433  * Local Variables:
2434  * eval: (c-set-style "gnu")
2435  * End:
2436  */