nat: api,cli and test update & cleanup
[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 #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 nat44_enable_command_fn (vlib_main_t * vm,
36                          unformat_input_t * input, vlib_cli_command_t * cmd)
37 {
38   snat_main_t *sm = &snat_main;
39   unformat_input_t _line_input, *line_input = &_line_input;
40   clib_error_t *error = 0;
41
42   nat44_config_t c = { 0 };
43   u8 mode_set = 0;
44
45   // TODO: check this also inside the function so it can be
46   //       safely called from anyplace, also sanity checking required
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
346   /* Get a line of input. */
347   if (!unformat_user (input, unformat_line_input, line_input))
348     return 0;
349
350   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
351     {
352       if (unformat (line_input, "default"))
353         nat_set_alloc_addr_and_port_default ();
354       else
355         if (unformat
356             (line_input, "map-e psid %d psid-offset %d psid-len %d", &psid,
357              &psid_offset, &psid_length))
358         nat_set_alloc_addr_and_port_mape ((u16) psid, (u16) psid_offset,
359                                           (u16) psid_length);
360       else
361         if (unformat
362             (line_input, "port-range %d - %d", &port_start, &port_end))
363         {
364           if (port_end <= port_start)
365             {
366               error =
367                 clib_error_return (0,
368                                    "The end-port must be greater than start-port");
369               goto done;
370             }
371           nat_set_alloc_addr_and_port_range ((u16) port_start,
372                                              (u16) port_end);
373         }
374       else
375         {
376           error = clib_error_return (0, "unknown input '%U'",
377                                      format_unformat_error, line_input);
378           goto done;
379         }
380     }
381
382 done:
383   unformat_free (line_input);
384
385   return error;
386 };
387
388 static clib_error_t *
389 nat44_show_alloc_addr_and_port_alg_command_fn (vlib_main_t * vm,
390                                                unformat_input_t * input,
391                                                vlib_cli_command_t * cmd)
392 {
393   snat_main_t *sm = &snat_main;
394
395   vlib_cli_output (vm, "NAT address and port: %U",
396                    format_nat_addr_and_port_alloc_alg,
397                    sm->addr_and_port_alloc_alg);
398   switch (sm->addr_and_port_alloc_alg)
399     {
400     case NAT_ADDR_AND_PORT_ALLOC_ALG_MAPE:
401       vlib_cli_output (vm, "  psid %d psid-offset %d psid-len %d", sm->psid,
402                        sm->psid_offset, sm->psid_length);
403       break;
404     case NAT_ADDR_AND_PORT_ALLOC_ALG_RANGE:
405       vlib_cli_output (vm, "  start-port %d end-port %d", sm->start_port,
406                        sm->end_port);
407       break;
408     default:
409       break;
410     }
411
412   return 0;
413 }
414
415 static clib_error_t *
416 nat_set_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input,
417                                  vlib_cli_command_t * cmd)
418 {
419   unformat_input_t _line_input, *line_input = &_line_input;
420   snat_main_t *sm = &snat_main;
421   clib_error_t *error = 0;
422   u32 mss;
423
424   /* Get a line of input. */
425   if (!unformat_user (input, unformat_line_input, line_input))
426     return 0;
427
428   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
429     {
430       if (unformat (line_input, "disable"))
431         sm->mss_clamping = 0;
432       else if (unformat (line_input, "%d", &mss))
433         sm->mss_clamping = (u16) mss;
434       else
435         {
436           error = clib_error_return (0, "unknown input '%U'",
437                                      format_unformat_error, line_input);
438           goto done;
439         }
440     }
441
442 done:
443   unformat_free (line_input);
444
445   return error;
446 }
447
448 static clib_error_t *
449 nat_show_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input,
450                                   vlib_cli_command_t * cmd)
451 {
452   snat_main_t *sm = &snat_main;
453
454   if (sm->mss_clamping)
455     vlib_cli_output (vm, "mss-clamping %d", sm->mss_clamping);
456   else
457     vlib_cli_output (vm, "mss-clamping disabled");
458
459   return 0;
460 }
461
462 static clib_error_t *
463 nat_ha_failover_command_fn (vlib_main_t * vm, unformat_input_t * input,
464                             vlib_cli_command_t * cmd)
465 {
466   unformat_input_t _line_input, *line_input = &_line_input;
467   ip4_address_t addr;
468   u32 port, session_refresh_interval = 10;
469   int rv;
470   clib_error_t *error = 0;
471
472   /* Get a line of input. */
473   if (!unformat_user (input, unformat_line_input, line_input))
474     return 0;
475
476   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
477     {
478       if (unformat (line_input, "%U:%u", unformat_ip4_address, &addr, &port))
479         ;
480       else
481         if (unformat
482             (line_input, "refresh-interval %u", &session_refresh_interval))
483         ;
484       else
485         {
486           error = clib_error_return (0, "unknown input '%U'",
487                                      format_unformat_error, line_input);
488           goto done;
489         }
490     }
491
492   rv = nat_ha_set_failover (&addr, (u16) port, session_refresh_interval);
493   if (rv)
494     error = clib_error_return (0, "set HA failover failed");
495
496 done:
497   unformat_free (line_input);
498
499   return error;
500 }
501
502 static clib_error_t *
503 nat_ha_listener_command_fn (vlib_main_t * vm, unformat_input_t * input,
504                             vlib_cli_command_t * cmd)
505 {
506   unformat_input_t _line_input, *line_input = &_line_input;
507   ip4_address_t addr;
508   u32 port, path_mtu = 512;
509   int rv;
510   clib_error_t *error = 0;
511
512   /* Get a line of input. */
513   if (!unformat_user (input, unformat_line_input, line_input))
514     return 0;
515
516   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
517     {
518       if (unformat (line_input, "%U:%u", unformat_ip4_address, &addr, &port))
519         ;
520       else if (unformat (line_input, "path-mtu %u", &path_mtu))
521         ;
522       else
523         {
524           error = clib_error_return (0, "unknown input '%U'",
525                                      format_unformat_error, line_input);
526           goto done;
527         }
528     }
529
530   rv = nat_ha_set_listener (&addr, (u16) port, path_mtu);
531   if (rv)
532     error = clib_error_return (0, "set HA listener failed");
533
534 done:
535   unformat_free (line_input);
536
537   return error;
538 }
539
540 static clib_error_t *
541 nat_show_ha_command_fn (vlib_main_t * vm, unformat_input_t * input,
542                         vlib_cli_command_t * cmd)
543 {
544   ip4_address_t addr;
545   u16 port;
546   u32 path_mtu, session_refresh_interval, resync_ack_missed;
547   u8 in_resync;
548
549   nat_ha_get_listener (&addr, &port, &path_mtu);
550   if (!port)
551     {
552       vlib_cli_output (vm, "NAT HA disabled\n");
553       return 0;
554     }
555
556   vlib_cli_output (vm, "LISTENER:\n");
557   vlib_cli_output (vm, "  %U:%u path-mtu %u\n",
558                    format_ip4_address, &addr, port, path_mtu);
559
560   nat_ha_get_failover (&addr, &port, &session_refresh_interval);
561   vlib_cli_output (vm, "FAILOVER:\n");
562   if (port)
563     vlib_cli_output (vm, "  %U:%u refresh-interval %usec\n",
564                      format_ip4_address, &addr, port,
565                      session_refresh_interval);
566   else
567     vlib_cli_output (vm, "  NA\n");
568
569   nat_ha_get_resync_status (&in_resync, &resync_ack_missed);
570   vlib_cli_output (vm, "RESYNC:\n");
571   if (in_resync)
572     vlib_cli_output (vm, "  in progress\n");
573   else
574     vlib_cli_output (vm, "  completed (%d ACK missed)\n", resync_ack_missed);
575
576   return 0;
577 }
578
579 static clib_error_t *
580 nat_ha_flush_command_fn (vlib_main_t * vm, unformat_input_t * input,
581                          vlib_cli_command_t * cmd)
582 {
583   nat_ha_flush (0);
584   return 0;
585 }
586
587 static clib_error_t *
588 nat_ha_resync_command_fn (vlib_main_t * vm, unformat_input_t * input,
589                           vlib_cli_command_t * cmd)
590 {
591   clib_error_t *error = 0;
592
593   if (nat_ha_resync (0, 0, 0))
594     error = clib_error_return (0, "NAT HA resync already running");
595
596   return error;
597 }
598
599 static clib_error_t *
600 add_address_command_fn (vlib_main_t * vm,
601                         unformat_input_t * input, vlib_cli_command_t * cmd)
602 {
603   unformat_input_t _line_input, *line_input = &_line_input;
604   snat_main_t *sm = &snat_main;
605   ip4_address_t start_addr, end_addr, this_addr;
606   u32 start_host_order, end_host_order;
607   u32 vrf_id = ~0;
608   int i, count;
609   int is_add = 1;
610   int rv = 0;
611   clib_error_t *error = 0;
612   u8 twice_nat = 0;
613
614   /* Get a line of input. */
615   if (!unformat_user (input, unformat_line_input, line_input))
616     return 0;
617
618   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
619     {
620       if (unformat (line_input, "%U - %U",
621                     unformat_ip4_address, &start_addr,
622                     unformat_ip4_address, &end_addr))
623         ;
624       else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
625         ;
626       else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
627         end_addr = start_addr;
628       else if (unformat (line_input, "twice-nat"))
629         twice_nat = 1;
630       else if (unformat (line_input, "del"))
631         is_add = 0;
632       else
633         {
634           error = clib_error_return (0, "unknown input '%U'",
635                                      format_unformat_error, line_input);
636           goto done;
637         }
638     }
639
640   if (sm->static_mapping_only)
641     {
642       error = clib_error_return (0, "static mapping only mode");
643       goto done;
644     }
645
646   start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
647   end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
648
649   if (end_host_order < start_host_order)
650     {
651       error = clib_error_return (0, "end address less than start address");
652       goto done;
653     }
654
655   count = (end_host_order - start_host_order) + 1;
656
657   if (count > 1024)
658     nat_log_info ("%U - %U, %d addresses...",
659                   format_ip4_address, &start_addr,
660                   format_ip4_address, &end_addr, count);
661
662   this_addr = start_addr;
663
664   for (i = 0; i < count; i++)
665     {
666       if (is_add)
667         rv = snat_add_address (sm, &this_addr, vrf_id, twice_nat);
668       else
669         rv = snat_del_address (sm, this_addr, 0, twice_nat);
670
671       switch (rv)
672         {
673         case VNET_API_ERROR_VALUE_EXIST:
674           error = clib_error_return (0, "NAT address already in use.");
675           goto done;
676         case VNET_API_ERROR_NO_SUCH_ENTRY:
677           error = clib_error_return (0, "NAT address not exist.");
678           goto done;
679         case VNET_API_ERROR_UNSPECIFIED:
680           error =
681             clib_error_return (0, "NAT address used in static mapping.");
682           goto done;
683         case VNET_API_ERROR_FEATURE_DISABLED:
684           error =
685             clib_error_return (0,
686                                "twice NAT available only for endpoint-dependent mode.");
687           goto done;
688         default:
689           break;
690         }
691
692       if (sm->out2in_dpo)
693         nat44_add_del_address_dpo (this_addr, is_add);
694
695       increment_v4_address (&this_addr);
696     }
697
698 done:
699   unformat_free (line_input);
700
701   return error;
702 }
703
704 static void
705 nat44_show_lru_summary (vlib_main_t * vm, snat_main_per_thread_data_t * tsm,
706                         u64 now, u64 sess_timeout_time)
707 {
708   snat_main_t *sm = &snat_main;
709   dlist_elt_t *oldest_elt;
710   snat_session_t *s;
711   u32 oldest_index;
712
713 #define _(n, d)                                                          \
714   oldest_index =                                                         \
715       clib_dlist_remove_head (tsm->lru_pool, tsm->n##_lru_head_index);   \
716   if (~0 != oldest_index)                                                \
717     {                                                                    \
718       oldest_elt = pool_elt_at_index (tsm->lru_pool, oldest_index);      \
719       s = pool_elt_at_index (tsm->sessions, oldest_elt->value);          \
720       sess_timeout_time =                                                \
721           s->last_heard + (f64)nat44_session_get_timeout (sm, s);        \
722       vlib_cli_output (vm, d " LRU min session timeout %llu (now %llu)", \
723                        sess_timeout_time, now);                          \
724       clib_dlist_addhead (tsm->lru_pool, tsm->n##_lru_head_index,        \
725                           oldest_index);                                 \
726     }
727   _(tcp_estab, "established tcp");
728   _(tcp_trans, "transitory tcp");
729   _(udp, "udp");
730   _(unk_proto, "unknown protocol");
731   _(icmp, "icmp");
732 #undef _
733 }
734
735 static clib_error_t *
736 nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
737                                vlib_cli_command_t * cmd)
738 {
739   snat_main_per_thread_data_t *tsm;
740   snat_main_t *sm = &snat_main;
741   snat_session_t *s;
742
743   if (!sm->endpoint_dependent)
744     return clib_error_return (0, SUPPORTED_ONLY_IN_ED_MODE_STR);
745
746   u32 count = 0;
747
748   u64 now = vlib_time_now (vm);
749   u64 sess_timeout_time;
750
751   u32 udp_sessions = 0;
752   u32 tcp_sessions = 0;
753   u32 icmp_sessions = 0;
754
755   u32 timed_out = 0;
756   u32 transitory = 0;
757   u32 transitory_wait_closed = 0;
758   u32 transitory_closed = 0;
759   u32 established = 0;
760
761   u32 fib;
762
763   for (fib = 0; fib < vec_len (sm->max_translations_per_fib); fib++)
764     vlib_cli_output (vm, "max translations per thread: %u fib %u",
765                      sm->max_translations_per_fib[fib], fib);
766
767   if (sm->num_workers > 1)
768     {
769       /* *INDENT-OFF* */
770       vec_foreach (tsm, sm->per_thread_data)
771         {
772           pool_foreach (s, tsm->sessions,
773           ({
774             sess_timeout_time = s->last_heard +
775               (f64) nat44_session_get_timeout (sm, s);
776             if (now >= sess_timeout_time)
777               timed_out++;
778
779             switch (s->nat_proto)
780               {
781               case NAT_PROTOCOL_ICMP:
782                 icmp_sessions++;
783                 break;
784               case NAT_PROTOCOL_TCP:
785                 tcp_sessions++;
786                 if (s->state)
787                   {
788                     if (s->tcp_closed_timestamp)
789                       {
790                         if (now >= s->tcp_closed_timestamp)
791                           {
792                             ++transitory_closed;
793                           }
794                         else
795                           {
796                             ++transitory_wait_closed;
797                           }
798                       }
799                     transitory++;
800                   }
801                 else
802                   established++;
803                 break;
804               case NAT_PROTOCOL_UDP:
805               default:
806                 udp_sessions++;
807                 break;
808               }
809           }));
810           nat44_show_lru_summary (vm, tsm, now, sess_timeout_time);
811           count += pool_elts (tsm->sessions);
812         }
813       /* *INDENT-ON* */
814     }
815   else
816     {
817       tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
818       /* *INDENT-OFF* */
819       pool_foreach (s, tsm->sessions,
820       ({
821         sess_timeout_time = s->last_heard +
822             (f64) nat44_session_get_timeout (sm, s);
823         if (now >= sess_timeout_time)
824           timed_out++;
825
826         switch (s->nat_proto)
827           {
828           case NAT_PROTOCOL_ICMP:
829             icmp_sessions++;
830             break;
831           case NAT_PROTOCOL_TCP:
832             tcp_sessions++;
833             if (s->state)
834               {
835                 if (s->tcp_closed_timestamp)
836                   {
837                     if (now >= s->tcp_closed_timestamp)
838                       {
839                         ++transitory_closed;
840                       }
841                     else
842                       {
843                         ++transitory_wait_closed;
844                       }
845                   }
846                 transitory++;
847               }
848             else
849               established++;
850             break;
851           case NAT_PROTOCOL_UDP:
852           default:
853             udp_sessions++;
854             break;
855           }
856       }));
857       /* *INDENT-ON* */
858       nat44_show_lru_summary (vm, tsm, now, sess_timeout_time);
859       count = pool_elts (tsm->sessions);
860     }
861
862   vlib_cli_output (vm, "total timed out sessions: %u", timed_out);
863   vlib_cli_output (vm, "total sessions: %u", count);
864   vlib_cli_output (vm, "total tcp sessions: %u", tcp_sessions);
865   vlib_cli_output (vm, "total tcp established sessions: %u", established);
866   vlib_cli_output (vm, "total tcp transitory sessions: %u", transitory);
867   vlib_cli_output (vm, "total tcp transitory (WAIT-CLOSED) sessions: %u",
868                    transitory_wait_closed);
869   vlib_cli_output (vm, "total tcp transitory (CLOSED) sessions: %u",
870                    transitory_closed);
871   vlib_cli_output (vm, "total udp sessions: %u", udp_sessions);
872   vlib_cli_output (vm, "total icmp sessions: %u", icmp_sessions);
873   return 0;
874 }
875
876 static clib_error_t *
877 nat44_show_addresses_command_fn (vlib_main_t * vm, unformat_input_t * input,
878                                  vlib_cli_command_t * cmd)
879 {
880   snat_main_t *sm = &snat_main;
881   snat_address_t *ap;
882
883   vlib_cli_output (vm, "NAT44 pool addresses:");
884   /* *INDENT-OFF* */
885   vec_foreach (ap, sm->addresses)
886     {
887       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
888       if (ap->fib_index != ~0)
889           vlib_cli_output (vm, "  tenant VRF: %u",
890             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
891       else
892         vlib_cli_output (vm, "  tenant VRF independent");
893     #define _(N, i, n, s) \
894       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
895       foreach_nat_protocol
896     #undef _
897     }
898   vlib_cli_output (vm, "NAT44 twice-nat pool addresses:");
899   vec_foreach (ap, sm->twice_nat_addresses)
900     {
901       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
902       if (ap->fib_index != ~0)
903           vlib_cli_output (vm, "  tenant VRF: %u",
904             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
905       else
906         vlib_cli_output (vm, "  tenant VRF independent");
907     #define _(N, i, n, s) \
908       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
909       foreach_nat_protocol
910     #undef _
911     }
912   /* *INDENT-ON* */
913   return 0;
914 }
915
916 static clib_error_t *
917 snat_feature_command_fn (vlib_main_t * vm,
918                          unformat_input_t * input, vlib_cli_command_t * cmd)
919 {
920   unformat_input_t _line_input, *line_input = &_line_input;
921   vnet_main_t *vnm = vnet_get_main ();
922   clib_error_t *error = 0;
923   u32 sw_if_index;
924   u32 *inside_sw_if_indices = 0;
925   u32 *outside_sw_if_indices = 0;
926   u8 is_output_feature = 0;
927   int is_del = 0;
928   int i;
929
930   sw_if_index = ~0;
931
932   /* Get a line of input. */
933   if (!unformat_user (input, unformat_line_input, line_input))
934     return 0;
935
936   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
937     {
938       if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
939                     vnm, &sw_if_index))
940         vec_add1 (inside_sw_if_indices, sw_if_index);
941       else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
942                          vnm, &sw_if_index))
943         vec_add1 (outside_sw_if_indices, sw_if_index);
944       else if (unformat (line_input, "output-feature"))
945         is_output_feature = 1;
946       else if (unformat (line_input, "del"))
947         is_del = 1;
948       else
949         {
950           error = clib_error_return (0, "unknown input '%U'",
951                                      format_unformat_error, line_input);
952           goto done;
953         }
954     }
955
956   if (vec_len (inside_sw_if_indices))
957     {
958       for (i = 0; i < vec_len (inside_sw_if_indices); i++)
959         {
960           sw_if_index = inside_sw_if_indices[i];
961           if (is_output_feature)
962             {
963               if (snat_interface_add_del_output_feature
964                   (sw_if_index, 1, is_del))
965                 {
966                   error = clib_error_return (0, "%s %U failed",
967                                              is_del ? "del" : "add",
968                                              format_vnet_sw_if_index_name,
969                                              vnm, sw_if_index);
970                   goto done;
971                 }
972             }
973           else
974             {
975               if (snat_interface_add_del (sw_if_index, 1, is_del))
976                 {
977                   error = clib_error_return (0, "%s %U failed",
978                                              is_del ? "del" : "add",
979                                              format_vnet_sw_if_index_name,
980                                              vnm, sw_if_index);
981                   goto done;
982                 }
983             }
984         }
985     }
986
987   if (vec_len (outside_sw_if_indices))
988     {
989       for (i = 0; i < vec_len (outside_sw_if_indices); i++)
990         {
991           sw_if_index = outside_sw_if_indices[i];
992           if (is_output_feature)
993             {
994               if (snat_interface_add_del_output_feature
995                   (sw_if_index, 0, is_del))
996                 {
997                   error = clib_error_return (0, "%s %U failed",
998                                              is_del ? "del" : "add",
999                                              format_vnet_sw_if_index_name,
1000                                              vnm, sw_if_index);
1001                   goto done;
1002                 }
1003             }
1004           else
1005             {
1006               if (snat_interface_add_del (sw_if_index, 0, is_del))
1007                 {
1008                   error = clib_error_return (0, "%s %U failed",
1009                                              is_del ? "del" : "add",
1010                                              format_vnet_sw_if_index_name,
1011                                              vnm, sw_if_index);
1012                   goto done;
1013                 }
1014             }
1015         }
1016     }
1017
1018 done:
1019   unformat_free (line_input);
1020   vec_free (inside_sw_if_indices);
1021   vec_free (outside_sw_if_indices);
1022
1023   return error;
1024 }
1025
1026 static clib_error_t *
1027 nat44_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
1028                                   vlib_cli_command_t * cmd)
1029 {
1030   snat_main_t *sm = &snat_main;
1031   snat_interface_t *i;
1032   vnet_main_t *vnm = vnet_get_main ();
1033
1034   vlib_cli_output (vm, "NAT44 interfaces:");
1035   /* *INDENT-OFF* */
1036   pool_foreach (i, sm->interfaces,
1037   ({
1038     vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
1039                      i->sw_if_index,
1040                      (nat_interface_is_inside(i) &&
1041                       nat_interface_is_outside(i)) ? "in out" :
1042                      (nat_interface_is_inside(i) ? "in" : "out"));
1043   }));
1044
1045   pool_foreach (i, sm->output_feature_interfaces,
1046   ({
1047     vlib_cli_output (vm, " %U output-feature %s",
1048                      format_vnet_sw_if_index_name, vnm,
1049                      i->sw_if_index,
1050                      (nat_interface_is_inside(i) &&
1051                       nat_interface_is_outside(i)) ? "in out" :
1052                      (nat_interface_is_inside(i) ? "in" : "out"));
1053   }));
1054   /* *INDENT-ON* */
1055
1056   return 0;
1057 }
1058
1059 static clib_error_t *
1060 add_static_mapping_command_fn (vlib_main_t * vm,
1061                                unformat_input_t * input,
1062                                vlib_cli_command_t * cmd)
1063 {
1064   unformat_input_t _line_input, *line_input = &_line_input;
1065   clib_error_t *error = 0;
1066   ip4_address_t l_addr, e_addr, exact_addr;
1067   u32 l_port = 0, e_port = 0, vrf_id = ~0;
1068   int is_add = 1, addr_only = 1, rv, exact = 0;
1069   u32 sw_if_index = ~0;
1070   vnet_main_t *vnm = vnet_get_main ();
1071   nat_protocol_t proto = NAT_PROTOCOL_OTHER;
1072   u8 proto_set = 0;
1073   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1074   u8 out2in_only = 0;
1075
1076   /* Get a line of input. */
1077   if (!unformat_user (input, unformat_line_input, line_input))
1078     return 0;
1079
1080   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1081     {
1082       if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
1083                     &l_port))
1084         addr_only = 0;
1085       else
1086         if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr))
1087         ;
1088       else if (unformat (line_input, "external %U %u", unformat_ip4_address,
1089                          &e_addr, &e_port))
1090         addr_only = 0;
1091       else if (unformat (line_input, "external %U", unformat_ip4_address,
1092                          &e_addr))
1093         ;
1094       else if (unformat (line_input, "external %U %u",
1095                          unformat_vnet_sw_interface, vnm, &sw_if_index,
1096                          &e_port))
1097         addr_only = 0;
1098       else if (unformat (line_input, "external %U",
1099                          unformat_vnet_sw_interface, vnm, &sw_if_index))
1100         ;
1101       else if (unformat (line_input, "exact %U", unformat_ip4_address,
1102                          &exact_addr))
1103         exact = 1;
1104       else if (unformat (line_input, "vrf %u", &vrf_id))
1105         ;
1106       else if (unformat (line_input, "%U", unformat_nat_protocol, &proto))
1107         proto_set = 1;
1108       else if (unformat (line_input, "twice-nat"))
1109         twice_nat = TWICE_NAT;
1110       else if (unformat (line_input, "self-twice-nat"))
1111         twice_nat = TWICE_NAT_SELF;
1112       else if (unformat (line_input, "out2in-only"))
1113         out2in_only = 1;
1114       else if (unformat (line_input, "del"))
1115         is_add = 0;
1116       else
1117         {
1118           error = clib_error_return (0, "unknown input: '%U'",
1119                                      format_unformat_error, line_input);
1120           goto done;
1121         }
1122     }
1123
1124   if (twice_nat && addr_only)
1125     {
1126       error = clib_error_return (0, "twice NAT only for 1:1 NAPT");
1127       goto done;
1128     }
1129
1130   if (addr_only)
1131     {
1132       if (proto_set)
1133         {
1134           error =
1135             clib_error_return (0,
1136                                "address only mapping doesn't support protocol");
1137           goto done;
1138         }
1139     }
1140   else if (!proto_set)
1141     {
1142       error = clib_error_return (0, "protocol is required");
1143       goto done;
1144     }
1145
1146   rv = snat_add_static_mapping (l_addr, e_addr, clib_host_to_net_u16 (l_port),
1147                                 clib_host_to_net_u16 (e_port),
1148                                 vrf_id, addr_only, sw_if_index, proto, is_add,
1149                                 twice_nat, out2in_only, 0, 0, exact_addr,
1150                                 exact);
1151
1152   switch (rv)
1153     {
1154     case VNET_API_ERROR_INVALID_VALUE:
1155       error = clib_error_return (0, "External port already in use.");
1156       goto done;
1157     case VNET_API_ERROR_NO_SUCH_ENTRY:
1158       if (is_add)
1159         error = clib_error_return (0, "External address must be allocated.");
1160       else
1161         error = clib_error_return (0, "Mapping not exist.");
1162       goto done;
1163     case VNET_API_ERROR_NO_SUCH_FIB:
1164       error = clib_error_return (0, "No such VRF id.");
1165       goto done;
1166     case VNET_API_ERROR_VALUE_EXIST:
1167       error = clib_error_return (0, "Mapping already exist.");
1168       goto done;
1169     case VNET_API_ERROR_FEATURE_DISABLED:
1170       error =
1171         clib_error_return (0,
1172                            "twice-nat/out2in-only available only for endpoint-dependent mode.");
1173       goto done;
1174     default:
1175       break;
1176     }
1177
1178 done:
1179   unformat_free (line_input);
1180
1181   return error;
1182 }
1183
1184 static clib_error_t *
1185 add_identity_mapping_command_fn (vlib_main_t * vm,
1186                                  unformat_input_t * input,
1187                                  vlib_cli_command_t * cmd)
1188 {
1189   unformat_input_t _line_input, *line_input = &_line_input;
1190   clib_error_t *error = 0;
1191   ip4_address_t addr, pool_addr = { 0 };
1192   u32 port = 0, vrf_id = ~0;
1193   int is_add = 1;
1194   int addr_only = 1;
1195   u32 sw_if_index = ~0;
1196   vnet_main_t *vnm = vnet_get_main ();
1197   int rv;
1198   nat_protocol_t proto;
1199
1200   addr.as_u32 = 0;
1201
1202   /* Get a line of input. */
1203   if (!unformat_user (input, unformat_line_input, line_input))
1204     return 0;
1205
1206   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1207     {
1208       if (unformat (line_input, "%U", unformat_ip4_address, &addr))
1209         ;
1210       else if (unformat (line_input, "external %U",
1211                          unformat_vnet_sw_interface, vnm, &sw_if_index))
1212         ;
1213       else if (unformat (line_input, "vrf %u", &vrf_id))
1214         ;
1215       else if (unformat (line_input, "%U %u", unformat_nat_protocol, &proto,
1216                          &port))
1217         addr_only = 0;
1218       else if (unformat (line_input, "del"))
1219         is_add = 0;
1220       else
1221         {
1222           error = clib_error_return (0, "unknown input: '%U'",
1223                                      format_unformat_error, line_input);
1224           goto done;
1225         }
1226     }
1227
1228   rv =
1229     snat_add_static_mapping (addr, addr, clib_host_to_net_u16 (port),
1230                              clib_host_to_net_u16 (port), vrf_id, addr_only,
1231                              sw_if_index, proto, is_add, 0, 0, 0, 1,
1232                              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 =
1778       nat44_del_session (sm, &addr, clib_host_to_net_u16 (port), proto,
1779                          vrf_id, is_in);
1780
1781   switch (rv)
1782     {
1783     case 0:
1784       break;
1785
1786     default:
1787       error = clib_error_return (0, "nat44_del_session returned %d", rv);
1788       goto done;
1789     }
1790
1791 done:
1792   unformat_free (line_input);
1793
1794   return error;
1795 }
1796
1797 static clib_error_t *
1798 snat_forwarding_set_command_fn (vlib_main_t * vm,
1799                                 unformat_input_t * input,
1800                                 vlib_cli_command_t * cmd)
1801 {
1802   snat_main_t *sm = &snat_main;
1803   unformat_input_t _line_input, *line_input = &_line_input;
1804   u8 forwarding_enable;
1805   u8 forwarding_enable_set = 0;
1806   clib_error_t *error = 0;
1807
1808   /* Get a line of input. */
1809   if (!unformat_user (input, unformat_line_input, line_input))
1810     return clib_error_return (0, "'enable' or 'disable' expected");
1811
1812   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1813     {
1814       if (!forwarding_enable_set && unformat (line_input, "enable"))
1815         {
1816           forwarding_enable = 1;
1817           forwarding_enable_set = 1;
1818         }
1819       else if (!forwarding_enable_set && unformat (line_input, "disable"))
1820         {
1821           forwarding_enable = 0;
1822           forwarding_enable_set = 1;
1823         }
1824       else
1825         {
1826           error = clib_error_return (0, "unknown input '%U'",
1827                                      format_unformat_error, line_input);
1828           goto done;
1829         }
1830     }
1831
1832   if (!forwarding_enable_set)
1833     {
1834       error = clib_error_return (0, "'enable' or 'disable' expected");
1835       goto done;
1836     }
1837
1838   sm->forwarding_enabled = forwarding_enable;
1839
1840 done:
1841   unformat_free (line_input);
1842
1843   return error;
1844 }
1845
1846 static clib_error_t *
1847 set_timeout_command_fn (vlib_main_t * vm,
1848                         unformat_input_t * input, vlib_cli_command_t * cmd)
1849 {
1850   snat_main_t *sm = &snat_main;
1851   unformat_input_t _line_input, *line_input = &_line_input;
1852   clib_error_t *error = 0;
1853
1854   /* Get a line of input. */
1855   if (!unformat_user (input, unformat_line_input, line_input))
1856     return 0;
1857
1858   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1859     {
1860       if (unformat (line_input, "udp %u", &sm->udp_timeout));
1861       else if (unformat (line_input, "tcp-established %u",
1862                          &sm->tcp_established_timeout));
1863       else if (unformat (line_input, "tcp-transitory %u",
1864                          &sm->tcp_transitory_timeout));
1865       else if (unformat (line_input, "icmp %u", &sm->icmp_timeout));
1866       else if (unformat (line_input, "reset"))
1867         {
1868           sm->udp_timeout = SNAT_UDP_TIMEOUT;
1869           sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
1870           sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
1871           sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
1872         }
1873       else
1874         {
1875           error = clib_error_return (0, "unknown input '%U'",
1876                                      format_unformat_error, line_input);
1877           goto done;
1878         }
1879     }
1880 done:
1881   unformat_free (line_input);
1882   return error;
1883 }
1884
1885 static clib_error_t *
1886 nat_show_timeouts_command_fn (vlib_main_t * vm,
1887                               unformat_input_t * input,
1888                               vlib_cli_command_t * cmd)
1889 {
1890   snat_main_t *sm = &snat_main;
1891
1892   vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
1893   vlib_cli_output (vm, "tcp-established timeout: %dsec",
1894                    sm->tcp_established_timeout);
1895   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
1896                    sm->tcp_transitory_timeout);
1897   vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
1898
1899   return 0;
1900 }
1901
1902 static clib_error_t *
1903 nat44_debug_fib_expire_command_fn (vlib_main_t * vm,
1904                                    unformat_input_t * input,
1905                                    vlib_cli_command_t * cmd)
1906 {
1907   unformat_input_t _line_input, *line_input = &_line_input;
1908   clib_error_t *error = 0;
1909   u32 fib = ~0;
1910
1911   /* Get a line of input. */
1912   if (!unformat_user (input, unformat_line_input, line_input))
1913     return 0;
1914
1915   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1916     {
1917       if (unformat (line_input, "%u", &fib))
1918         ;
1919       else
1920         {
1921           error = clib_error_return (0, "unknown input '%U'",
1922                                      format_unformat_error, line_input);
1923           goto done;
1924         }
1925     }
1926   expire_per_vrf_sessions (fib);
1927 done:
1928   unformat_free (line_input);
1929   return error;
1930 }
1931
1932 static clib_error_t *
1933 nat44_debug_fib_registration_command_fn (vlib_main_t * vm,
1934                                          unformat_input_t * input,
1935                                          vlib_cli_command_t * cmd)
1936 {
1937   snat_main_t *sm = &snat_main;
1938   snat_main_per_thread_data_t *tsm;
1939   per_vrf_sessions_t *per_vrf_sessions;
1940
1941   vlib_cli_output (vm, "VRF registration debug:");
1942   vec_foreach (tsm, sm->per_thread_data)
1943   {
1944     vlib_cli_output (vm, "thread %u:", tsm->thread_index);
1945     vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
1946     {
1947       vlib_cli_output (vm, "rx fib %u tx fib %u ses count %u %s",
1948                        per_vrf_sessions->rx_fib_index,
1949                        per_vrf_sessions->tx_fib_index,
1950                        per_vrf_sessions->ses_count,
1951                        per_vrf_sessions->expired ? "expired" : "");
1952     }
1953   }
1954   return 0;
1955 }
1956
1957 /* *INDENT-OFF* */
1958
1959 /*?
1960 ?*/
1961 VLIB_CLI_COMMAND (nat44_debug_fib_expire_command, static) = {
1962   .path = "debug nat44 fib expire",
1963   .short_help = "debug nat44 fib expire <fib-index>",
1964   .function = nat44_debug_fib_expire_command_fn,
1965 };
1966
1967 /*?
1968 ?*/
1969 VLIB_CLI_COMMAND (nat44_debug_fib_registration_command, static) = {
1970   .path = "debug nat44 fib registration",
1971   .short_help = "debug nat44 fib registration",
1972   .function = nat44_debug_fib_registration_command_fn,
1973 };
1974
1975 /*?
1976  * @cliexpar
1977  * @cliexstart{nat44 enable}
1978  * Enable nat44 plugin
1979  * To enable nat44, use:
1980  *  vpp# nat44 enable sessions <n>
1981  * To enable nat44 static mapping only, use:
1982  *  vpp# nat44 enable sessions <n> static-mapping
1983  * To enable nat44 static mapping with connection tracking, use:
1984  *  vpp# nat44 enable sessions <n> static-mapping connection-tracking
1985  * To enable nat44 out2in dpo, use:
1986  *  vpp# nat44 enable sessions <n> out2in-dpo
1987  * To enable nat44 endpoint-dependent, use:
1988  *  vpp# nat44 enable sessions <n> endpoint-dependent
1989  * To set inside-vrf outside-vrf, use:
1990  *  vpp# nat44 enable sessions <n> inside-vrf <id> outside-vrf <id>
1991  * @cliexend
1992 ?*/
1993 VLIB_CLI_COMMAND (nat44_enable_command, static) = {
1994   .path = "nat44 enable",
1995   .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>]",
1996   .function = nat44_enable_command_fn,
1997 };
1998
1999 /*?
2000  * @cliexpar
2001  * @cliexstart{nat44 disable}
2002  * Disable nat44 plugin
2003  * To disable nat44, use:
2004  *  vpp# nat44 disable
2005  * @cliexend
2006 ?*/
2007 VLIB_CLI_COMMAND (nat44_disable_command, static) = {
2008   .path = "nat44 disable",
2009   .short_help = "nat44 disable",
2010   .function = nat44_disable_command_fn,
2011 };
2012
2013 /*?
2014  * @cliexpar
2015  * @cliexstart{set snat workers}
2016  * Set NAT workers if 2 or more workers available, use:
2017  *  vpp# set snat workers 0-2,5
2018  * @cliexend
2019 ?*/
2020 VLIB_CLI_COMMAND (set_workers_command, static) = {
2021   .path = "set nat workers",
2022   .function = set_workers_command_fn,
2023   .short_help = "set nat workers <workers-list>",
2024 };
2025
2026 /*?
2027  * @cliexpar
2028  * @cliexstart{show nat workers}
2029  * Show NAT workers.
2030  *  vpp# show nat workers:
2031  *  2 workers
2032  *    vpp_wk_0
2033  *    vpp_wk_1
2034  * @cliexend
2035 ?*/
2036 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
2037   .path = "show nat workers",
2038   .short_help = "show nat workers",
2039   .function = nat_show_workers_commnad_fn,
2040 };
2041
2042 /*?
2043  * @cliexpar
2044  * @cliexstart{set nat timeout}
2045  * Set values of timeouts for NAT sessions (in seconds), use:
2046  *  vpp# set nat timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90
2047  * To reset default values use:
2048  *  vpp# set nat timeout reset
2049  * @cliexend
2050 ?*/
2051 VLIB_CLI_COMMAND (set_timeout_command, static) = {
2052   .path = "set nat timeout",
2053   .function = set_timeout_command_fn,
2054   .short_help =
2055     "set nat timeout [udp <sec> | tcp-established <sec> "
2056     "tcp-transitory <sec> | icmp <sec> | reset]",
2057 };
2058
2059 /*?
2060  * @cliexpar
2061  * @cliexstart{show nat timeouts}
2062  * Show values of timeouts for NAT sessions.
2063  * vpp# show nat timeouts
2064  * udp timeout: 300sec
2065  * tcp-established timeout: 7440sec
2066  * tcp-transitory timeout: 240sec
2067  * icmp timeout: 60sec
2068  * @cliexend
2069 ?*/
2070 VLIB_CLI_COMMAND (nat_show_timeouts_command, static) = {
2071   .path = "show nat timeouts",
2072   .short_help = "show nat timeouts",
2073   .function = nat_show_timeouts_command_fn,
2074 };
2075
2076 /*?
2077  * @cliexpar
2078  * @cliexstart{nat set logging level}
2079  * To set NAT logging level use:
2080  * Set nat logging level
2081  * @cliexend
2082 ?*/
2083 VLIB_CLI_COMMAND (snat_set_log_level_command, static) = {
2084   .path = "nat set logging level",
2085   .function = snat_set_log_level_command_fn,
2086   .short_help = "nat set logging level <level>",
2087 };
2088
2089 /*?
2090  * @cliexpar
2091  * @cliexstart{snat ipfix logging}
2092  * To enable NAT IPFIX logging use:
2093  *  vpp# nat ipfix logging
2094  * To set IPFIX exporter use:
2095  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
2096  * @cliexend
2097 ?*/
2098 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
2099   .path = "nat ipfix logging",
2100   .function = snat_ipfix_logging_enable_disable_command_fn,
2101   .short_help = "nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
2102 };
2103
2104 /*?
2105  * @cliexpar
2106  * @cliexstart{nat addr-port-assignment-alg}
2107  * Set address and port assignment algorithm
2108  * For the MAP-E CE limit port choice based on PSID use:
2109  *  vpp# nat addr-port-assignment-alg map-e psid 10 psid-offset 6 psid-len 6
2110  * For port range use:
2111  *  vpp# nat addr-port-assignment-alg port-range <start-port> - <end-port>
2112  * To set standard (default) address and port assignment algorithm use:
2113  *  vpp# nat addr-port-assignment-alg default
2114  * @cliexend
2115 ?*/
2116 VLIB_CLI_COMMAND (nat44_set_alloc_addr_and_port_alg_command, static) = {
2117     .path = "nat addr-port-assignment-alg",
2118     .short_help = "nat addr-port-assignment-alg <alg-name> [<alg-params>]",
2119     .function = nat44_set_alloc_addr_and_port_alg_command_fn,
2120 };
2121
2122 /*?
2123  * @cliexpar
2124  * @cliexstart{show nat addr-port-assignment-alg}
2125  * Show address and port assignment algorithm
2126  * @cliexend
2127 ?*/
2128 VLIB_CLI_COMMAND (nat44_show_alloc_addr_and_port_alg_command, static) = {
2129     .path = "show nat addr-port-assignment-alg",
2130     .short_help = "show nat addr-port-assignment-alg",
2131     .function = nat44_show_alloc_addr_and_port_alg_command_fn,
2132 };
2133
2134 /*?
2135  * @cliexpar
2136  * @cliexstart{nat mss-clamping}
2137  * Set TCP MSS rewriting configuration
2138  * To enable TCP MSS rewriting use:
2139  *  vpp# nat mss-clamping 1452
2140  * To disbale TCP MSS rewriting use:
2141  *  vpp# nat mss-clamping disable
2142  * @cliexend
2143 ?*/
2144 VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = {
2145     .path = "nat mss-clamping",
2146     .short_help = "nat mss-clamping <mss-value>|disable",
2147     .function = nat_set_mss_clamping_command_fn,
2148 };
2149
2150 /*?
2151  * @cliexpar
2152  * @cliexstart{show nat mss-clamping}
2153  * Show TCP MSS rewriting configuration
2154  * @cliexend
2155 ?*/
2156 VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = {
2157     .path = "show nat mss-clamping",
2158     .short_help = "show nat mss-clamping",
2159     .function = nat_show_mss_clamping_command_fn,
2160 };
2161
2162 /*?
2163  * @cliexpar
2164  * @cliexstart{nat ha failover}
2165  * Set HA failover (remote settings)
2166  * @cliexend
2167 ?*/
2168 VLIB_CLI_COMMAND (nat_ha_failover_command, static) = {
2169     .path = "nat ha failover",
2170     .short_help = "nat ha failover <ip4-address>:<port> [refresh-interval <sec>]",
2171     .function = nat_ha_failover_command_fn,
2172 };
2173
2174 /*?
2175  * @cliexpar
2176  * @cliexstart{nat ha listener}
2177  * Set HA listener (local settings)
2178  * @cliexend
2179 ?*/
2180 VLIB_CLI_COMMAND (nat_ha_listener_command, static) = {
2181     .path = "nat ha listener",
2182     .short_help = "nat ha listener <ip4-address>:<port> [path-mtu <path-mtu>]",
2183     .function = nat_ha_listener_command_fn,
2184 };
2185
2186 /*?
2187  * @cliexpar
2188  * @cliexstart{show nat ha}
2189  * Show HA configuration/status
2190  * @cliexend
2191 ?*/
2192 VLIB_CLI_COMMAND (nat_show_ha_command, static) = {
2193     .path = "show nat ha",
2194     .short_help = "show nat ha",
2195     .function = nat_show_ha_command_fn,
2196 };
2197
2198 /*?
2199  * @cliexpar
2200  * @cliexstart{nat ha flush}
2201  * Flush the current HA data (for testing)
2202  * @cliexend
2203 ?*/
2204 VLIB_CLI_COMMAND (nat_ha_flush_command, static) = {
2205     .path = "nat ha flush",
2206     .short_help = "nat ha flush",
2207     .function = nat_ha_flush_command_fn,
2208 };
2209
2210 /*?
2211  * @cliexpar
2212  * @cliexstart{nat ha resync}
2213  * Resync HA (resend existing sessions to new failover)
2214  * @cliexend
2215 ?*/
2216 VLIB_CLI_COMMAND (nat_ha_resync_command, static) = {
2217     .path = "nat ha resync",
2218     .short_help = "nat ha resync",
2219     .function = nat_ha_resync_command_fn,
2220 };
2221
2222 /*?
2223  * @cliexpar
2224  * @cliexstart{show nat44 hash tables}
2225  * Show NAT44 hash tables
2226  * @cliexend
2227 ?*/
2228 VLIB_CLI_COMMAND (nat44_show_hash, static) = {
2229   .path = "show nat44 hash tables",
2230   .short_help = "show nat44 hash tables [detail|verbose]",
2231   .function = nat44_show_hash_command_fn,
2232 };
2233
2234 /*?
2235  * @cliexpar
2236  * @cliexstart{nat44 add address}
2237  * Add/delete NAT44 pool address.
2238  * To add NAT44 pool address use:
2239  *  vpp# nat44 add address 172.16.1.3
2240  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
2241  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
2242  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
2243  * @cliexend
2244 ?*/
2245 VLIB_CLI_COMMAND (add_address_command, static) = {
2246   .path = "nat44 add address",
2247   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
2248                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
2249   .function = add_address_command_fn,
2250 };
2251
2252 /*?
2253  * @cliexpar
2254  * @cliexstart{show nat44 summary}
2255  * Show NAT44 summary
2256  * vpp# show nat44 summary
2257  * @cliexend
2258 ?*/
2259 VLIB_CLI_COMMAND (nat44_show_summary_command, static) = {
2260   .path = "show nat44 summary",
2261   .short_help = "show nat44 summary",
2262   .function = nat44_show_summary_command_fn,
2263 };
2264
2265 /*?
2266  * @cliexpar
2267  * @cliexstart{show nat44 addresses}
2268  * Show NAT44 pool addresses.
2269  * vpp# show nat44 addresses
2270  * NAT44 pool addresses:
2271  * 172.16.2.2
2272  *   tenant VRF independent
2273  *   10 busy udp ports
2274  *   0 busy tcp ports
2275  *   0 busy icmp ports
2276  * 172.16.1.3
2277  *   tenant VRF: 10
2278  *   0 busy udp ports
2279  *   2 busy tcp ports
2280  *   0 busy icmp ports
2281  * NAT44 twice-nat pool addresses:
2282  * 10.20.30.72
2283  *   tenant VRF independent
2284  *   0 busy udp ports
2285  *   0 busy tcp ports
2286  *   0 busy icmp ports
2287  * @cliexend
2288 ?*/
2289 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
2290   .path = "show nat44 addresses",
2291   .short_help = "show nat44 addresses",
2292   .function = nat44_show_addresses_command_fn,
2293 };
2294
2295 /*?
2296  * @cliexpar
2297  * @cliexstart{set interface nat44}
2298  * Enable/disable NAT44 feature on the interface.
2299  * To enable NAT44 feature with local network interface use:
2300  *  vpp# set interface nat44 in GigabitEthernet0/8/0
2301  * To enable NAT44 feature with external network interface use:
2302  *  vpp# set interface nat44 out GigabitEthernet0/a/0
2303  * @cliexend
2304 ?*/
2305 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
2306   .path = "set interface nat44",
2307   .function = snat_feature_command_fn,
2308   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
2309                 "[del]",
2310 };
2311
2312 /*?
2313  * @cliexpar
2314  * @cliexstart{show nat44 interfaces}
2315  * Show interfaces with NAT44 feature.
2316  * vpp# show nat44 interfaces
2317  * NAT44 interfaces:
2318  *  GigabitEthernet0/8/0 in
2319  *  GigabitEthernet0/a/0 out
2320  * @cliexend
2321 ?*/
2322 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
2323   .path = "show nat44 interfaces",
2324   .short_help = "show nat44 interfaces",
2325   .function = nat44_show_interfaces_command_fn,
2326 };
2327
2328 /*?
2329  * @cliexpar
2330  * @cliexstart{nat44 add static mapping}
2331  * Static mapping allows hosts on the external network to initiate connection
2332  * to to the local network host.
2333  * To create static mapping between local host address 10.0.0.3 port 6303 and
2334  * external address 4.4.4.4 port 3606 for TCP protocol use:
2335  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
2336  * If not runnig "static mapping only" NAT plugin mode use before:
2337  *  vpp# nat44 add address 4.4.4.4
2338  * To create address only static mapping between local and external address use:
2339  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
2340  * To create ICMP static mapping between local and external with ICMP echo
2341  * identifier 10 use:
2342  *  vpp# nat44 add static mapping icmp local 10.0.0.3 10 external 4.4.4.4 10
2343  * To force use of specific pool address, vrf independent
2344  *  vpp# nat44 add static mapping local 10.0.0.2 1234 external 10.0.2.2 1234 twice-nat exact 10.0.1.2
2345  * @cliexend
2346 ?*/
2347 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
2348   .path = "nat44 add static mapping",
2349   .function = add_static_mapping_command_fn,
2350   .short_help =
2351     "nat44 add static mapping tcp|udp|icmp local <addr> [<port|icmp-echo-id>] "
2352     "external <addr> [<port|icmp-echo-id>] [vrf <table-id>] [twice-nat|self-twice-nat] "
2353     "[out2in-only] [exact <pool-addr>] [del]",
2354 };
2355
2356 /*?
2357  * @cliexpar
2358  * @cliexstart{nat44 add identity mapping}
2359  * Identity mapping translate an IP address to itself.
2360  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
2361  * use:
2362  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
2363  * To create identity mapping for address 10.0.0.3 use:
2364  *  vpp# nat44 add identity mapping 10.0.0.3
2365  * To create identity mapping for DHCP addressed interface use:
2366  *  vpp# nat44 add identity mapping external GigabitEthernet0/a/0 tcp 3606
2367  * @cliexend
2368 ?*/
2369 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
2370   .path = "nat44 add identity mapping",
2371   .function = add_identity_mapping_command_fn,
2372   .short_help = "nat44 add identity mapping <ip4-addr>|external <interface> "
2373     "[<protocol> <port>] [vrf <table-id>] [del]",
2374 };
2375
2376 /*?
2377  * @cliexpar
2378  * @cliexstart{nat44 add load-balancing static mapping}
2379  * Service load balancing using NAT44
2380  * To add static mapping with load balancing for service with external IP
2381  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
2382  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
2383  *  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
2384  * @cliexend
2385 ?*/
2386 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
2387   .path = "nat44 add load-balancing static mapping",
2388   .function = add_lb_static_mapping_command_fn,
2389   .short_help =
2390     "nat44 add load-balancing static mapping protocol tcp|udp "
2391     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2392     "probability <n> [twice-nat|self-twice-nat] [out2in-only] "
2393     "[affinity <timeout-seconds>] [del]",
2394 };
2395
2396 /*?
2397  * @cliexpar
2398  * @cliexstart{nat44 add load-balancing static mapping}
2399  * Modify service load balancing using NAT44
2400  * To add new back-end server 10.100.10.30:8080 for service load balancing
2401  * static mapping with external IP address 1.2.3.4 and TCP port 80 use:
2402  *  vpp# nat44 add load-balancing back-end protocol tcp external 1.2.3.4:80 local 10.100.10.30:8080 probability 25
2403  * @cliexend
2404 ?*/
2405 VLIB_CLI_COMMAND (add_lb_backend_command, static) = {
2406   .path = "nat44 add load-balancing back-end",
2407   .function = add_lb_backend_command_fn,
2408   .short_help =
2409     "nat44 add load-balancing back-end protocol tcp|udp "
2410     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2411     "probability <n> [del]",
2412 };
2413
2414 /*?
2415  * @cliexpar
2416  * @cliexstart{show nat44 static mappings}
2417  * Show NAT44 static mappings.
2418  * vpp# show nat44 static mappings
2419  * NAT44 static mappings:
2420  *  local 10.0.0.3 external 4.4.4.4 vrf 0
2421  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
2422  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
2423  *   local 10.100.10.10:8080 probability 80
2424  *   local 10.100.10.20:8080 probability 20
2425  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
2426  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
2427  * @cliexend
2428 ?*/
2429 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
2430   .path = "show nat44 static mappings",
2431   .short_help = "show nat44 static mappings",
2432   .function = nat44_show_static_mappings_command_fn,
2433 };
2434
2435 /*?
2436  * @cliexpar
2437  * @cliexstart{nat44 add interface address}
2438  * Use NAT44 pool address from specific interfce
2439  * To add NAT44 pool address from specific interface use:
2440  *  vpp# nat44 add interface address GigabitEthernet0/8/0
2441  * @cliexend
2442 ?*/
2443 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
2444     .path = "nat44 add interface address",
2445     .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
2446     .function = snat_add_interface_address_command_fn,
2447 };
2448
2449 /*?
2450  * @cliexpar
2451  * @cliexstart{show nat44 interface address}
2452  * Show NAT44 pool address interfaces
2453  * vpp# show nat44 interface address
2454  * NAT44 pool address interfaces:
2455  *  GigabitEthernet0/a/0
2456  * NAT44 twice-nat pool address interfaces:
2457  *  GigabitEthernet0/8/0
2458  * @cliexend
2459 ?*/
2460 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
2461   .path = "show nat44 interface address",
2462   .short_help = "show nat44 interface address",
2463   .function = nat44_show_interface_address_command_fn,
2464 };
2465
2466 /*?
2467  * @cliexpar
2468  * @cliexstart{show nat44 sessions}
2469  * Show NAT44 sessions.
2470  * @cliexend
2471 ?*/
2472 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
2473   .path = "show nat44 sessions",
2474   .short_help = "show nat44 sessions [detail|metrics]",
2475   .function = nat44_show_sessions_command_fn,
2476 };
2477
2478 /*?
2479  * @cliexpar
2480  * @cliexstart{set nat44 session limit}
2481  * Set NAT44 session limit.
2482  * @cliexend
2483 ?*/
2484 VLIB_CLI_COMMAND (nat44_set_session_limit_command, static) = {
2485   .path = "set nat44 session limit",
2486   .short_help = "set nat44 session limit <limit> [vrf <table-id>]",
2487   .function = nat44_set_session_limit_command_fn,
2488 };
2489
2490 /*?
2491  * @cliexpar
2492  * @cliexstart{nat44 del user}
2493  * To delete all NAT44 user sessions:
2494  *  vpp# nat44 del user 10.0.0.3
2495  * @cliexend
2496 ?*/
2497 VLIB_CLI_COMMAND (nat44_del_user_command, static) = {
2498     .path = "nat44 del user",
2499     .short_help = "nat44 del user <addr> [fib <index>]",
2500     .function = nat44_del_user_command_fn,
2501 };
2502
2503 /*?
2504  * @cliexpar
2505  * @cliexstart{clear nat44 sessions}
2506  * To clear all NAT44 sessions
2507  *  vpp# clear nat44 sessions
2508  * @cliexend
2509 ?*/
2510 VLIB_CLI_COMMAND (nat44_clear_sessions_command, static) = {
2511     .path = "clear nat44 sessions",
2512     .short_help = "clear nat44 sessions",
2513     .function = nat44_clear_sessions_command_fn,
2514 };
2515
2516 /*?
2517  * @cliexpar
2518  * @cliexstart{nat44 del session}
2519  * To administratively delete NAT44 session by inside address and port use:
2520  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
2521  * To administratively delete NAT44 session by outside address and port use:
2522  *  vpp# nat44 del session out 1.0.0.3:6033 udp
2523  * @cliexend
2524 ?*/
2525 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
2526     .path = "nat44 del session",
2527     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>] [external-host <addr>:<port>]",
2528     .function = nat44_del_session_command_fn,
2529 };
2530
2531 /*?
2532  * @cliexpar
2533  * @cliexstart{nat44 forwarding}
2534  * Enable or disable forwarding
2535  * Forward packets which don't match existing translation
2536  * or static mapping instead of dropping them.
2537  * To enable forwarding, use:
2538  *  vpp# nat44 forwarding enable
2539  * To disable forwarding, use:
2540  *  vpp# nat44 forwarding disable
2541  * @cliexend
2542 ?*/
2543 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
2544   .path = "nat44 forwarding",
2545   .short_help = "nat44 forwarding enable|disable",
2546   .function = snat_forwarding_set_command_fn,
2547 };
2548
2549 /* *INDENT-ON* */
2550
2551 /*
2552  * fd.io coding-style-patch-verification: ON
2553  *
2554  * Local Variables:
2555  * eval: (c-set-style "gnu")
2556  * End:
2557  */