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