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