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