nat: refactor and split fo EI/ED features
[vpp.git] / src / plugins / nat / nat44_cli.c
1 /*
2  * Copyright (c) 2018 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /**
16  * @file
17  * @brief NAT44 CLI
18  */
19
20 #include <nat/nat.h>
21 #include <nat/lib/ipfix_logging.h>
22 #include <nat/lib/nat_inlines.h>
23 #include <nat/nat_inlines.h>
24 #include <nat/nat44/inlines.h>
25 #include <nat/nat_affinity.h>
26 #include <vnet/fib/fib_table.h>
27
28 #include <nat/nat44-ei/nat44_ei_ha.h>
29 #include <nat/nat44-ei/nat44_ei.h>
30
31 #define UNSUPPORTED_IN_ED_MODE_STR \
32   "This command is unsupported in endpoint dependent mode"
33 #define SUPPORTED_ONLY_IN_ED_MODE_STR \
34   "This command is supported only in endpoint dependent mode"
35
36 static clib_error_t *
37 nat44_enable_command_fn (vlib_main_t * vm,
38                          unformat_input_t * input, vlib_cli_command_t * cmd)
39 {
40   snat_main_t *sm = &snat_main;
41   unformat_input_t _line_input, *line_input = &_line_input;
42   clib_error_t *error = 0;
43
44   nat44_config_t c = { 0 };
45   u8 mode_set = 0;
46
47   // TODO: check this also inside the function so it can be
48   //       safely called from anyplace, also sanity checking required
49   if (sm->enabled)
50     return clib_error_return (0, "nat44 already enabled");
51
52   /* Get a line of input. */
53   if (!unformat_user (input, unformat_line_input, line_input))
54     {
55       if (nat44_plugin_enable (c) != 0)
56         return clib_error_return (0, "nat44 enable failed");
57       return 0;
58     }
59
60   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
61     {
62       if (!mode_set && unformat (line_input, "static-mapping-only"))
63         {
64           mode_set = 1;
65           c.static_mapping_only = 1;
66           if (unformat (line_input, "connection-tracking"))
67             {
68               c.connection_tracking = 1;
69             }
70         }
71       else if (!mode_set && unformat (line_input, "out2in-dpo"))
72         {
73           mode_set = 1;
74           c.out2in_dpo = 1;
75         }
76       else if (!mode_set && unformat (line_input, "endpoint-dependent"))
77         {
78           mode_set = 1;
79           c.endpoint_dependent = 1;
80         }
81       else if (unformat (line_input, "inside-vrf %u", &c.inside_vrf));
82       else if (unformat (line_input, "outside-vrf %u", &c.outside_vrf));
83       else if (unformat (line_input, "users %u", &c.users));
84       else if (unformat (line_input, "sessions %u", &c.sessions));
85       else if (unformat (line_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)
95     {
96       error = clib_error_return (0, "number of sessions is required");
97       goto done;
98     }
99
100   if (nat44_plugin_enable (c) != 0)
101     error = clib_error_return (0, "nat44 enable failed");
102 done:
103   unformat_free (line_input);
104   return error;
105 }
106
107 static clib_error_t *
108 nat44_disable_command_fn (vlib_main_t * vm,
109                           unformat_input_t * input, vlib_cli_command_t * cmd)
110 {
111   snat_main_t *sm = &snat_main;
112   clib_error_t *error = 0;
113
114   if (!sm->enabled)
115     return clib_error_return (0, "nat44 already disabled");
116
117   if (nat44_plugin_disable () != 0)
118     error = clib_error_return (0, "nat44 disable failed");
119
120   return error;
121 }
122
123 static clib_error_t *
124 set_workers_command_fn (vlib_main_t * vm,
125                         unformat_input_t * input, vlib_cli_command_t * cmd)
126 {
127   unformat_input_t _line_input, *line_input = &_line_input;
128   uword *bitmap = 0;
129   int rv = 0;
130   clib_error_t *error = 0;
131
132   /* Get a line of input. */
133   if (!unformat_user (input, unformat_line_input, line_input))
134     return 0;
135
136   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
137     {
138       if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap))
139         ;
140       else
141         {
142           error = clib_error_return (0, "unknown input '%U'",
143                                      format_unformat_error, line_input);
144           goto done;
145         }
146     }
147
148   if (bitmap == 0)
149     {
150       error = clib_error_return (0, "List of workers must be specified.");
151       goto done;
152     }
153
154   rv = snat_set_workers (bitmap);
155
156   clib_bitmap_free (bitmap);
157
158   switch (rv)
159     {
160     case VNET_API_ERROR_INVALID_WORKER:
161       error = clib_error_return (0, "Invalid worker(s).");
162       goto done;
163     case VNET_API_ERROR_FEATURE_DISABLED:
164       error = clib_error_return (0,
165                                  "Supported only if 2 or more workes available.");
166       goto done;
167     default:
168       break;
169     }
170
171 done:
172   unformat_free (line_input);
173
174   return error;
175 }
176
177 static clib_error_t *
178 nat_show_workers_commnad_fn (vlib_main_t * vm, unformat_input_t * input,
179                              vlib_cli_command_t * cmd)
180 {
181   snat_main_t *sm = &snat_main;
182   u32 *worker;
183
184   if (sm->num_workers > 1)
185     {
186       vlib_cli_output (vm, "%d workers", vec_len (sm->workers));
187       /* *INDENT-OFF* */
188       vec_foreach (worker, sm->workers)
189         {
190           vlib_worker_thread_t *w =
191             vlib_worker_threads + *worker + sm->first_worker_index;
192           vlib_cli_output (vm, "  %s", w->name);
193         }
194       /* *INDENT-ON* */
195     }
196
197   return 0;
198 }
199
200 static clib_error_t *
201 snat_set_log_level_command_fn (vlib_main_t * vm,
202                                unformat_input_t * input,
203                                vlib_cli_command_t * cmd)
204 {
205   unformat_input_t _line_input, *line_input = &_line_input;
206   snat_main_t *sm = &snat_main;
207   u8 log_level = SNAT_LOG_NONE;
208   clib_error_t *error = 0;
209
210   /* Get a line of input. */
211   if (!unformat_user (input, unformat_line_input, line_input))
212     return 0;
213
214   if (!unformat (line_input, "%d", &log_level))
215     {
216       error = clib_error_return (0, "unknown input '%U'",
217                                  format_unformat_error, line_input);
218       goto done;
219     }
220   if (log_level > SNAT_LOG_DEBUG)
221     {
222       error = clib_error_return (0, "unknown logging level '%d'", log_level);
223       goto done;
224     }
225   sm->log_level = log_level;
226
227 done:
228   unformat_free (line_input);
229
230   return error;
231 }
232
233 static clib_error_t *
234 snat_ipfix_logging_enable_disable_command_fn (vlib_main_t * vm,
235                                               unformat_input_t * input,
236                                               vlib_cli_command_t * cmd)
237 {
238   unformat_input_t _line_input, *line_input = &_line_input;
239   u32 domain_id = 0;
240   u32 src_port = 0;
241   u8 enable = 1;
242   int rv = 0;
243   clib_error_t *error = 0;
244
245   /* Get a line of input. */
246   if (!unformat_user (input, unformat_line_input, line_input))
247     {
248       rv = nat_ipfix_logging_enable_disable (enable, domain_id,
249                                              (u16) src_port);
250       if (rv)
251         return clib_error_return (0, "ipfix logging enable failed");
252       return 0;
253     }
254
255   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
256     {
257       if (unformat (line_input, "domain %d", &domain_id))
258         ;
259       else if (unformat (line_input, "src-port %d", &src_port))
260         ;
261       else if (unformat (line_input, "disable"))
262         enable = 0;
263       else
264         {
265           error = clib_error_return (0, "unknown input '%U'",
266                                      format_unformat_error, line_input);
267           goto done;
268         }
269     }
270
271   rv = nat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port);
272
273   if (rv)
274     {
275       error = clib_error_return (0, "ipfix logging enable failed");
276       goto done;
277     }
278
279 done:
280   unformat_free (line_input);
281
282   return error;
283 }
284
285 static clib_error_t *
286 nat44_show_hash_command_fn (vlib_main_t * vm, unformat_input_t * input,
287                             vlib_cli_command_t * cmd)
288 {
289   snat_main_t *sm = &snat_main;
290   snat_main_per_thread_data_t *tsm;
291   nat_affinity_main_t *nam = &nat_affinity_main;
292   int i;
293   int verbose = 0;
294
295   if (unformat (input, "detail"))
296     verbose = 1;
297   else if (unformat (input, "verbose"))
298     verbose = 2;
299
300   vlib_cli_output (vm, "%U", format_bihash_8_8, &sm->static_mapping_by_local,
301                    verbose);
302   vlib_cli_output (vm, "%U",
303                    format_bihash_8_8, &sm->static_mapping_by_external,
304                    verbose);
305   vlib_cli_output (vm, "%U", format_bihash_16_8, &sm->out2in_ed, verbose);
306   vec_foreach_index (i, sm->per_thread_data)
307   {
308     tsm = vec_elt_at_index (sm->per_thread_data, i);
309     vlib_cli_output (vm, "-------- thread %d %s --------\n",
310                      i, vlib_worker_threads[i].name);
311     if (sm->endpoint_dependent)
312       {
313         vlib_cli_output (vm, "%U", format_bihash_16_8, &tsm->in2out_ed,
314                          verbose);
315       }
316     else
317       {
318         vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->in2out, verbose);
319         vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->out2in, verbose);
320       }
321     vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->user_hash, verbose);
322   }
323
324   if (sm->endpoint_dependent)
325     {
326       vlib_cli_output (vm, "%U", format_bihash_16_8, &nam->affinity_hash,
327                        verbose);
328     }
329
330   vlib_cli_output (vm, "-------- hash table parameters --------\n");
331   vlib_cli_output (vm, "translation buckets: %u", sm->translation_buckets);
332   if (!sm->endpoint_dependent)
333     {
334       vlib_cli_output (vm, "user buckets: %u", sm->user_buckets);
335     }
336   return 0;
337 }
338
339 static clib_error_t *
340 nat44_set_alloc_addr_and_port_alg_command_fn (vlib_main_t * vm,
341                                               unformat_input_t * input,
342                                               vlib_cli_command_t * cmd)
343 {
344   unformat_input_t _line_input, *line_input = &_line_input;
345   clib_error_t *error = 0;
346   u32 psid, psid_offset, psid_length, port_start, port_end;
347   snat_main_t *sm = &snat_main;
348
349   if (sm->endpoint_dependent)
350     return clib_error_return (0, UNSUPPORTED_IN_ED_MODE_STR);
351
352   /* Get a line of input. */
353   if (!unformat_user (input, unformat_line_input, line_input))
354     return 0;
355
356   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
357     {
358       if (unformat (line_input, "default"))
359         nat44_ei_set_alloc_default ();
360       else
361         if (unformat
362             (line_input, "map-e psid %d psid-offset %d psid-len %d", &psid,
363              &psid_offset, &psid_length))
364         nat44_ei_set_alloc_mape ((u16) psid, (u16) psid_offset,
365                                  (u16) psid_length);
366       else
367         if (unformat
368             (line_input, "port-range %d - %d", &port_start, &port_end))
369         {
370           if (port_end <= port_start)
371             {
372               error =
373                 clib_error_return (0,
374                                    "The end-port must be greater than start-port");
375               goto done;
376             }
377           nat44_ei_set_alloc_range ((u16) port_start, (u16) port_end);
378         }
379       else
380         {
381           error = clib_error_return (0, "unknown input '%U'",
382                                      format_unformat_error, line_input);
383           goto done;
384         }
385     }
386
387 done:
388   unformat_free (line_input);
389
390   return error;
391 };
392
393 static clib_error_t *
394 nat44_show_alloc_addr_and_port_alg_command_fn (vlib_main_t * vm,
395                                                unformat_input_t * input,
396                                                vlib_cli_command_t * cmd)
397 {
398   snat_main_t *sm = &snat_main;
399
400   vlib_cli_output (vm, "NAT address and port: %U",
401                    format_nat_addr_and_port_alloc_alg,
402                    sm->addr_and_port_alloc_alg);
403   switch (sm->addr_and_port_alloc_alg)
404     {
405     case NAT_ADDR_AND_PORT_ALLOC_ALG_MAPE:
406       vlib_cli_output (vm, "  psid %d psid-offset %d psid-len %d", sm->psid,
407                        sm->psid_offset, sm->psid_length);
408       break;
409     case NAT_ADDR_AND_PORT_ALLOC_ALG_RANGE:
410       vlib_cli_output (vm, "  start-port %d end-port %d", sm->start_port,
411                        sm->end_port);
412       break;
413     default:
414       break;
415     }
416
417   return 0;
418 }
419
420 static clib_error_t *
421 nat_set_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input,
422                                  vlib_cli_command_t * cmd)
423 {
424   unformat_input_t _line_input, *line_input = &_line_input;
425   snat_main_t *sm = &snat_main;
426   clib_error_t *error = 0;
427   u32 mss;
428
429   /* Get a line of input. */
430   if (!unformat_user (input, unformat_line_input, line_input))
431     return 0;
432
433   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
434     {
435       if (unformat (line_input, "disable"))
436         sm->mss_clamping = 0;
437       else if (unformat (line_input, "%d", &mss))
438         sm->mss_clamping = (u16) mss;
439       else
440         {
441           error = clib_error_return (0, "unknown input '%U'",
442                                      format_unformat_error, line_input);
443           goto done;
444         }
445     }
446
447 done:
448   unformat_free (line_input);
449
450   return error;
451 }
452
453 static clib_error_t *
454 nat_show_mss_clamping_command_fn (vlib_main_t * vm, unformat_input_t * input,
455                                   vlib_cli_command_t * cmd)
456 {
457   snat_main_t *sm = &snat_main;
458
459   if (sm->mss_clamping)
460     vlib_cli_output (vm, "mss-clamping %d", sm->mss_clamping);
461   else
462     vlib_cli_output (vm, "mss-clamping disabled");
463
464   return 0;
465 }
466
467 static clib_error_t *
468 nat_ha_failover_command_fn (vlib_main_t * vm, unformat_input_t * input,
469                             vlib_cli_command_t * cmd)
470 {
471   unformat_input_t _line_input, *line_input = &_line_input;
472   ip4_address_t addr;
473   u32 port, session_refresh_interval = 10;
474   int rv;
475   clib_error_t *error = 0;
476
477   /* Get a line of input. */
478   if (!unformat_user (input, unformat_line_input, line_input))
479     return 0;
480
481   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
482     {
483       if (unformat (line_input, "%U:%u", unformat_ip4_address, &addr, &port))
484         ;
485       else
486         if (unformat
487             (line_input, "refresh-interval %u", &session_refresh_interval))
488         ;
489       else
490         {
491           error = clib_error_return (0, "unknown input '%U'",
492                                      format_unformat_error, line_input);
493           goto done;
494         }
495     }
496
497   rv = nat_ha_set_failover (&addr, (u16) port, session_refresh_interval);
498   if (rv)
499     error = clib_error_return (0, "set HA failover failed");
500
501 done:
502   unformat_free (line_input);
503
504   return error;
505 }
506
507 static clib_error_t *
508 nat_ha_listener_command_fn (vlib_main_t * vm, unformat_input_t * input,
509                             vlib_cli_command_t * cmd)
510 {
511   unformat_input_t _line_input, *line_input = &_line_input;
512   ip4_address_t addr;
513   u32 port, path_mtu = 512;
514   int rv;
515   clib_error_t *error = 0;
516
517   /* Get a line of input. */
518   if (!unformat_user (input, unformat_line_input, line_input))
519     return 0;
520
521   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
522     {
523       if (unformat (line_input, "%U:%u", unformat_ip4_address, &addr, &port))
524         ;
525       else if (unformat (line_input, "path-mtu %u", &path_mtu))
526         ;
527       else
528         {
529           error = clib_error_return (0, "unknown input '%U'",
530                                      format_unformat_error, line_input);
531           goto done;
532         }
533     }
534
535   rv = nat_ha_set_listener (&addr, (u16) port, path_mtu);
536   if (rv)
537     error = clib_error_return (0, "set HA listener failed");
538
539 done:
540   unformat_free (line_input);
541
542   return error;
543 }
544
545 static clib_error_t *
546 nat_show_ha_command_fn (vlib_main_t * vm, unformat_input_t * input,
547                         vlib_cli_command_t * cmd)
548 {
549   ip4_address_t addr;
550   u16 port;
551   u32 path_mtu, session_refresh_interval, resync_ack_missed;
552   u8 in_resync;
553
554   nat_ha_get_listener (&addr, &port, &path_mtu);
555   if (!port)
556     {
557       vlib_cli_output (vm, "NAT HA disabled\n");
558       return 0;
559     }
560
561   vlib_cli_output (vm, "LISTENER:\n");
562   vlib_cli_output (vm, "  %U:%u path-mtu %u\n",
563                    format_ip4_address, &addr, port, path_mtu);
564
565   nat_ha_get_failover (&addr, &port, &session_refresh_interval);
566   vlib_cli_output (vm, "FAILOVER:\n");
567   if (port)
568     vlib_cli_output (vm, "  %U:%u refresh-interval %usec\n",
569                      format_ip4_address, &addr, port,
570                      session_refresh_interval);
571   else
572     vlib_cli_output (vm, "  NA\n");
573
574   nat_ha_get_resync_status (&in_resync, &resync_ack_missed);
575   vlib_cli_output (vm, "RESYNC:\n");
576   if (in_resync)
577     vlib_cli_output (vm, "  in progress\n");
578   else
579     vlib_cli_output (vm, "  completed (%d ACK missed)\n", resync_ack_missed);
580
581   return 0;
582 }
583
584 static clib_error_t *
585 nat_ha_flush_command_fn (vlib_main_t * vm, unformat_input_t * input,
586                          vlib_cli_command_t * cmd)
587 {
588   nat_ha_flush (0);
589   return 0;
590 }
591
592 static clib_error_t *
593 nat_ha_resync_command_fn (vlib_main_t * vm, unformat_input_t * input,
594                           vlib_cli_command_t * cmd)
595 {
596   clib_error_t *error = 0;
597
598   if (nat_ha_resync (0, 0, 0))
599     error = clib_error_return (0, "NAT HA resync already running");
600
601   return error;
602 }
603
604 static clib_error_t *
605 add_address_command_fn (vlib_main_t * vm,
606                         unformat_input_t * input, vlib_cli_command_t * cmd)
607 {
608   unformat_input_t _line_input, *line_input = &_line_input;
609   snat_main_t *sm = &snat_main;
610   ip4_address_t start_addr, end_addr, this_addr;
611   u32 start_host_order, end_host_order;
612   u32 vrf_id = ~0;
613   int i, count;
614   int is_add = 1;
615   int rv = 0;
616   clib_error_t *error = 0;
617   u8 twice_nat = 0;
618
619   /* Get a line of input. */
620   if (!unformat_user (input, unformat_line_input, line_input))
621     return 0;
622
623   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
624     {
625       if (unformat (line_input, "%U - %U",
626                     unformat_ip4_address, &start_addr,
627                     unformat_ip4_address, &end_addr))
628         ;
629       else if (unformat (line_input, "tenant-vrf %u", &vrf_id))
630         ;
631       else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
632         end_addr = start_addr;
633       else if (unformat (line_input, "twice-nat"))
634         twice_nat = 1;
635       else if (unformat (line_input, "del"))
636         is_add = 0;
637       else
638         {
639           error = clib_error_return (0, "unknown input '%U'",
640                                      format_unformat_error, line_input);
641           goto done;
642         }
643     }
644
645   if (sm->static_mapping_only)
646     {
647       error = clib_error_return (0, "static mapping only mode");
648       goto done;
649     }
650
651   start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
652   end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
653
654   if (end_host_order < start_host_order)
655     {
656       error = clib_error_return (0, "end address less than start address");
657       goto done;
658     }
659
660   count = (end_host_order - start_host_order) + 1;
661
662   if (count > 1024)
663     nat_log_info ("%U - %U, %d addresses...",
664                   format_ip4_address, &start_addr,
665                   format_ip4_address, &end_addr, count);
666
667   this_addr = start_addr;
668
669   for (i = 0; i < count; i++)
670     {
671       if (is_add)
672         rv = snat_add_address (sm, &this_addr, vrf_id, twice_nat);
673       else
674         rv = snat_del_address (sm, this_addr, 0, twice_nat);
675
676       switch (rv)
677         {
678         case VNET_API_ERROR_VALUE_EXIST:
679           error = clib_error_return (0, "NAT address already in use.");
680           goto done;
681         case VNET_API_ERROR_NO_SUCH_ENTRY:
682           error = clib_error_return (0, "NAT address not exist.");
683           goto done;
684         case VNET_API_ERROR_UNSPECIFIED:
685           error =
686             clib_error_return (0, "NAT address used in static mapping.");
687           goto done;
688         case VNET_API_ERROR_FEATURE_DISABLED:
689           error =
690             clib_error_return (0,
691                                "twice NAT available only for endpoint-dependent mode.");
692           goto done;
693         default:
694           break;
695         }
696
697       if (sm->out2in_dpo)
698         nat44_add_del_address_dpo (this_addr, is_add);
699
700       increment_v4_address (&this_addr);
701     }
702
703 done:
704   unformat_free (line_input);
705
706   return error;
707 }
708
709 static void
710 nat44_show_lru_summary (vlib_main_t * vm, snat_main_per_thread_data_t * tsm,
711                         u64 now, u64 sess_timeout_time)
712 {
713   snat_main_t *sm = &snat_main;
714   dlist_elt_t *oldest_elt;
715   snat_session_t *s;
716   u32 oldest_index;
717
718 #define _(n, d)                                                          \
719   oldest_index =                                                         \
720       clib_dlist_remove_head (tsm->lru_pool, tsm->n##_lru_head_index);   \
721   if (~0 != oldest_index)                                                \
722     {                                                                    \
723       oldest_elt = pool_elt_at_index (tsm->lru_pool, oldest_index);      \
724       s = pool_elt_at_index (tsm->sessions, oldest_elt->value);          \
725       sess_timeout_time =                                                \
726           s->last_heard + (f64)nat44_session_get_timeout (sm, s);        \
727       vlib_cli_output (vm, d " LRU min session timeout %llu (now %llu)", \
728                        sess_timeout_time, now);                          \
729       clib_dlist_addhead (tsm->lru_pool, tsm->n##_lru_head_index,        \
730                           oldest_index);                                 \
731     }
732   _(tcp_estab, "established tcp");
733   _(tcp_trans, "transitory tcp");
734   _(udp, "udp");
735   _(unk_proto, "unknown protocol");
736   _(icmp, "icmp");
737 #undef _
738 }
739
740 static clib_error_t *
741 nat44_show_summary_command_fn (vlib_main_t * vm, unformat_input_t * input,
742                                vlib_cli_command_t * cmd)
743 {
744   snat_main_per_thread_data_t *tsm;
745   snat_main_t *sm = &snat_main;
746   snat_session_t *s;
747
748   if (!sm->endpoint_dependent)
749     return clib_error_return (0, SUPPORTED_ONLY_IN_ED_MODE_STR);
750
751   u32 count = 0;
752
753   u64 now = vlib_time_now (vm);
754   u64 sess_timeout_time = 0;
755
756   u32 udp_sessions = 0;
757   u32 tcp_sessions = 0;
758   u32 icmp_sessions = 0;
759
760   u32 timed_out = 0;
761   u32 transitory = 0;
762   u32 transitory_wait_closed = 0;
763   u32 transitory_closed = 0;
764   u32 established = 0;
765
766   u32 fib;
767
768   for (fib = 0; fib < vec_len (sm->max_translations_per_fib); fib++)
769     vlib_cli_output (vm, "max translations per thread: %u fib %u",
770                      sm->max_translations_per_fib[fib], fib);
771
772   if (sm->num_workers > 1)
773     {
774       /* *INDENT-OFF* */
775       vec_foreach (tsm, sm->per_thread_data)
776         {
777           pool_foreach (s, tsm->sessions)
778            {
779             sess_timeout_time = s->last_heard +
780               (f64) nat44_session_get_timeout (sm, s);
781             if (now >= sess_timeout_time)
782               timed_out++;
783
784             switch (s->nat_proto)
785               {
786               case NAT_PROTOCOL_ICMP:
787                 icmp_sessions++;
788                 break;
789               case NAT_PROTOCOL_TCP:
790                 tcp_sessions++;
791                 if (s->state)
792                   {
793                     if (s->tcp_closed_timestamp)
794                       {
795                         if (now >= s->tcp_closed_timestamp)
796                           {
797                             ++transitory_closed;
798                           }
799                         else
800                           {
801                             ++transitory_wait_closed;
802                           }
803                       }
804                     transitory++;
805                   }
806                 else
807                   established++;
808                 break;
809               case NAT_PROTOCOL_UDP:
810               default:
811                 udp_sessions++;
812                 break;
813               }
814           }
815           nat44_show_lru_summary (vm, tsm, now, sess_timeout_time);
816           count += pool_elts (tsm->sessions);
817         }
818       /* *INDENT-ON* */
819     }
820   else
821     {
822       tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
823       /* *INDENT-OFF* */
824       pool_foreach (s, tsm->sessions)
825        {
826         sess_timeout_time = s->last_heard +
827             (f64) nat44_session_get_timeout (sm, s);
828         if (now >= sess_timeout_time)
829           timed_out++;
830
831         switch (s->nat_proto)
832           {
833           case NAT_PROTOCOL_ICMP:
834             icmp_sessions++;
835             break;
836           case NAT_PROTOCOL_TCP:
837             tcp_sessions++;
838             if (s->state)
839               {
840                 if (s->tcp_closed_timestamp)
841                   {
842                     if (now >= s->tcp_closed_timestamp)
843                       {
844                         ++transitory_closed;
845                       }
846                     else
847                       {
848                         ++transitory_wait_closed;
849                       }
850                   }
851                 transitory++;
852               }
853             else
854               established++;
855             break;
856           case NAT_PROTOCOL_UDP:
857           default:
858             udp_sessions++;
859             break;
860           }
861       }
862       /* *INDENT-ON* */
863       nat44_show_lru_summary (vm, tsm, now, sess_timeout_time);
864       count = pool_elts (tsm->sessions);
865     }
866
867   vlib_cli_output (vm, "total timed out sessions: %u", timed_out);
868   vlib_cli_output (vm, "total sessions: %u", count);
869   vlib_cli_output (vm, "total tcp sessions: %u", tcp_sessions);
870   vlib_cli_output (vm, "total tcp established sessions: %u", established);
871   vlib_cli_output (vm, "total tcp transitory sessions: %u", transitory);
872   vlib_cli_output (vm, "total tcp transitory (WAIT-CLOSED) sessions: %u",
873                    transitory_wait_closed);
874   vlib_cli_output (vm, "total tcp transitory (CLOSED) sessions: %u",
875                    transitory_closed);
876   vlib_cli_output (vm, "total udp sessions: %u", udp_sessions);
877   vlib_cli_output (vm, "total icmp sessions: %u", icmp_sessions);
878   return 0;
879 }
880
881 static clib_error_t *
882 nat44_show_addresses_command_fn (vlib_main_t * vm, unformat_input_t * input,
883                                  vlib_cli_command_t * cmd)
884 {
885   snat_main_t *sm = &snat_main;
886   snat_address_t *ap;
887
888   vlib_cli_output (vm, "NAT44 pool addresses:");
889   /* *INDENT-OFF* */
890   vec_foreach (ap, sm->addresses)
891     {
892       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
893       if (ap->fib_index != ~0)
894           vlib_cli_output (vm, "  tenant VRF: %u",
895             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
896       else
897         vlib_cli_output (vm, "  tenant VRF independent");
898     #define _(N, i, n, s) \
899       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
900       foreach_nat_protocol
901     #undef _
902     }
903   vlib_cli_output (vm, "NAT44 twice-nat pool addresses:");
904   vec_foreach (ap, sm->twice_nat_addresses)
905     {
906       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
907       if (ap->fib_index != ~0)
908           vlib_cli_output (vm, "  tenant VRF: %u",
909             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
910       else
911         vlib_cli_output (vm, "  tenant VRF independent");
912     #define _(N, i, n, s) \
913       vlib_cli_output (vm, "  %d busy %s ports", ap->busy_##n##_ports, s);
914       foreach_nat_protocol
915     #undef _
916     }
917   /* *INDENT-ON* */
918   return 0;
919 }
920
921 static clib_error_t *
922 snat_feature_command_fn (vlib_main_t * vm,
923                          unformat_input_t * input, vlib_cli_command_t * cmd)
924 {
925   unformat_input_t _line_input, *line_input = &_line_input;
926   vnet_main_t *vnm = vnet_get_main ();
927   clib_error_t *error = 0;
928   u32 sw_if_index;
929   u32 *inside_sw_if_indices = 0;
930   u32 *outside_sw_if_indices = 0;
931   u8 is_output_feature = 0;
932   int is_del = 0;
933   int i;
934
935   sw_if_index = ~0;
936
937   /* Get a line of input. */
938   if (!unformat_user (input, unformat_line_input, line_input))
939     return 0;
940
941   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
942     {
943       if (unformat (line_input, "in %U", unformat_vnet_sw_interface,
944                     vnm, &sw_if_index))
945         vec_add1 (inside_sw_if_indices, sw_if_index);
946       else if (unformat (line_input, "out %U", unformat_vnet_sw_interface,
947                          vnm, &sw_if_index))
948         vec_add1 (outside_sw_if_indices, sw_if_index);
949       else if (unformat (line_input, "output-feature"))
950         is_output_feature = 1;
951       else if (unformat (line_input, "del"))
952         is_del = 1;
953       else
954         {
955           error = clib_error_return (0, "unknown input '%U'",
956                                      format_unformat_error, line_input);
957           goto done;
958         }
959     }
960
961   if (vec_len (inside_sw_if_indices))
962     {
963       for (i = 0; i < vec_len (inside_sw_if_indices); i++)
964         {
965           sw_if_index = inside_sw_if_indices[i];
966           if (is_output_feature)
967             {
968               if (snat_interface_add_del_output_feature
969                   (sw_if_index, 1, is_del))
970                 {
971                   error = clib_error_return (0, "%s %U failed",
972                                              is_del ? "del" : "add",
973                                              format_vnet_sw_if_index_name,
974                                              vnm, sw_if_index);
975                   goto done;
976                 }
977             }
978           else
979             {
980               if (snat_interface_add_del (sw_if_index, 1, is_del))
981                 {
982                   error = clib_error_return (0, "%s %U failed",
983                                              is_del ? "del" : "add",
984                                              format_vnet_sw_if_index_name,
985                                              vnm, sw_if_index);
986                   goto done;
987                 }
988             }
989         }
990     }
991
992   if (vec_len (outside_sw_if_indices))
993     {
994       for (i = 0; i < vec_len (outside_sw_if_indices); i++)
995         {
996           sw_if_index = outside_sw_if_indices[i];
997           if (is_output_feature)
998             {
999               if (snat_interface_add_del_output_feature
1000                   (sw_if_index, 0, is_del))
1001                 {
1002                   error = clib_error_return (0, "%s %U failed",
1003                                              is_del ? "del" : "add",
1004                                              format_vnet_sw_if_index_name,
1005                                              vnm, sw_if_index);
1006                   goto done;
1007                 }
1008             }
1009           else
1010             {
1011               if (snat_interface_add_del (sw_if_index, 0, is_del))
1012                 {
1013                   error = clib_error_return (0, "%s %U failed",
1014                                              is_del ? "del" : "add",
1015                                              format_vnet_sw_if_index_name,
1016                                              vnm, sw_if_index);
1017                   goto done;
1018                 }
1019             }
1020         }
1021     }
1022
1023 done:
1024   unformat_free (line_input);
1025   vec_free (inside_sw_if_indices);
1026   vec_free (outside_sw_if_indices);
1027
1028   return error;
1029 }
1030
1031 static clib_error_t *
1032 nat44_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
1033                                   vlib_cli_command_t * cmd)
1034 {
1035   snat_main_t *sm = &snat_main;
1036   snat_interface_t *i;
1037   vnet_main_t *vnm = vnet_get_main ();
1038
1039   vlib_cli_output (vm, "NAT44 interfaces:");
1040   /* *INDENT-OFF* */
1041   pool_foreach (i, sm->interfaces)
1042    {
1043     vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
1044                      i->sw_if_index,
1045                      (nat_interface_is_inside(i) &&
1046                       nat_interface_is_outside(i)) ? "in out" :
1047                      (nat_interface_is_inside(i) ? "in" : "out"));
1048   }
1049
1050   pool_foreach (i, sm->output_feature_interfaces)
1051    {
1052     vlib_cli_output (vm, " %U output-feature %s",
1053                      format_vnet_sw_if_index_name, vnm,
1054                      i->sw_if_index,
1055                      (nat_interface_is_inside(i) &&
1056                       nat_interface_is_outside(i)) ? "in out" :
1057                      (nat_interface_is_inside(i) ? "in" : "out"));
1058   }
1059   /* *INDENT-ON* */
1060
1061   return 0;
1062 }
1063
1064 static clib_error_t *
1065 add_static_mapping_command_fn (vlib_main_t * vm,
1066                                unformat_input_t * input,
1067                                vlib_cli_command_t * cmd)
1068 {
1069   unformat_input_t _line_input, *line_input = &_line_input;
1070   clib_error_t *error = 0;
1071   ip4_address_t l_addr, e_addr, exact_addr;
1072   u32 l_port = 0, e_port = 0, vrf_id = ~0;
1073   int is_add = 1, addr_only = 1, rv, exact = 0;
1074   u32 sw_if_index = ~0;
1075   vnet_main_t *vnm = vnet_get_main ();
1076   nat_protocol_t proto = NAT_PROTOCOL_OTHER;
1077   u8 proto_set = 0;
1078   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1079   u8 out2in_only = 0;
1080
1081   /* Get a line of input. */
1082   if (!unformat_user (input, unformat_line_input, line_input))
1083     return 0;
1084
1085   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1086     {
1087       if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
1088                     &l_port))
1089         addr_only = 0;
1090       else
1091         if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr))
1092         ;
1093       else if (unformat (line_input, "external %U %u", unformat_ip4_address,
1094                          &e_addr, &e_port))
1095         addr_only = 0;
1096       else if (unformat (line_input, "external %U", unformat_ip4_address,
1097                          &e_addr))
1098         ;
1099       else if (unformat (line_input, "external %U %u",
1100                          unformat_vnet_sw_interface, vnm, &sw_if_index,
1101                          &e_port))
1102         addr_only = 0;
1103       else if (unformat (line_input, "external %U",
1104                          unformat_vnet_sw_interface, vnm, &sw_if_index))
1105         ;
1106       else if (unformat (line_input, "exact %U", unformat_ip4_address,
1107                          &exact_addr))
1108         exact = 1;
1109       else if (unformat (line_input, "vrf %u", &vrf_id))
1110         ;
1111       else if (unformat (line_input, "%U", unformat_nat_protocol, &proto))
1112         proto_set = 1;
1113       else if (unformat (line_input, "twice-nat"))
1114         twice_nat = TWICE_NAT;
1115       else if (unformat (line_input, "self-twice-nat"))
1116         twice_nat = TWICE_NAT_SELF;
1117       else if (unformat (line_input, "out2in-only"))
1118         out2in_only = 1;
1119       else if (unformat (line_input, "del"))
1120         is_add = 0;
1121       else
1122         {
1123           error = clib_error_return (0, "unknown input: '%U'",
1124                                      format_unformat_error, line_input);
1125           goto done;
1126         }
1127     }
1128
1129   if (twice_nat && addr_only)
1130     {
1131       error = clib_error_return (0, "twice NAT only for 1:1 NAPT");
1132       goto done;
1133     }
1134
1135   if (addr_only)
1136     {
1137       if (proto_set)
1138         {
1139           error =
1140             clib_error_return (0,
1141                                "address only mapping doesn't support protocol");
1142           goto done;
1143         }
1144     }
1145   else if (!proto_set)
1146     {
1147       error = clib_error_return (0, "protocol is required");
1148       goto done;
1149     }
1150
1151   rv = snat_add_static_mapping (l_addr, e_addr, clib_host_to_net_u16 (l_port),
1152                                 clib_host_to_net_u16 (e_port),
1153                                 vrf_id, addr_only, sw_if_index, proto, is_add,
1154                                 twice_nat, out2in_only, 0, 0, exact_addr,
1155                                 exact);
1156
1157   switch (rv)
1158     {
1159     case VNET_API_ERROR_INVALID_VALUE:
1160       error = clib_error_return (0, "External port already in use.");
1161       goto done;
1162     case VNET_API_ERROR_NO_SUCH_ENTRY:
1163       if (is_add)
1164         error = clib_error_return (0, "External address must be allocated.");
1165       else
1166         error = clib_error_return (0, "Mapping not exist.");
1167       goto done;
1168     case VNET_API_ERROR_NO_SUCH_FIB:
1169       error = clib_error_return (0, "No such VRF id.");
1170       goto done;
1171     case VNET_API_ERROR_VALUE_EXIST:
1172       error = clib_error_return (0, "Mapping already exist.");
1173       goto done;
1174     case VNET_API_ERROR_FEATURE_DISABLED:
1175       error =
1176         clib_error_return (0,
1177                            "twice-nat/out2in-only available only for endpoint-dependent mode.");
1178       goto done;
1179     default:
1180       break;
1181     }
1182
1183 done:
1184   unformat_free (line_input);
1185
1186   return error;
1187 }
1188
1189 static clib_error_t *
1190 add_identity_mapping_command_fn (vlib_main_t * vm,
1191                                  unformat_input_t * input,
1192                                  vlib_cli_command_t * cmd)
1193 {
1194   unformat_input_t _line_input, *line_input = &_line_input;
1195   clib_error_t *error = 0;
1196   ip4_address_t addr, pool_addr = { 0 };
1197   u32 port = 0, vrf_id = ~0;
1198   int is_add = 1;
1199   int addr_only = 1;
1200   u32 sw_if_index = ~0;
1201   vnet_main_t *vnm = vnet_get_main ();
1202   int rv;
1203   nat_protocol_t proto;
1204
1205   addr.as_u32 = 0;
1206
1207   /* Get a line of input. */
1208   if (!unformat_user (input, unformat_line_input, line_input))
1209     return 0;
1210
1211   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1212     {
1213       if (unformat (line_input, "%U", unformat_ip4_address, &addr))
1214         ;
1215       else if (unformat (line_input, "external %U",
1216                          unformat_vnet_sw_interface, vnm, &sw_if_index))
1217         ;
1218       else if (unformat (line_input, "vrf %u", &vrf_id))
1219         ;
1220       else if (unformat (line_input, "%U %u", unformat_nat_protocol, &proto,
1221                          &port))
1222         addr_only = 0;
1223       else if (unformat (line_input, "del"))
1224         is_add = 0;
1225       else
1226         {
1227           error = clib_error_return (0, "unknown input: '%U'",
1228                                      format_unformat_error, line_input);
1229           goto done;
1230         }
1231     }
1232
1233   rv =
1234     snat_add_static_mapping (addr, addr, clib_host_to_net_u16 (port),
1235                              clib_host_to_net_u16 (port), vrf_id, addr_only,
1236                              sw_if_index, proto, is_add, 0, 0, 0, 1,
1237                              pool_addr, 0);
1238
1239   switch (rv)
1240     {
1241     case VNET_API_ERROR_INVALID_VALUE:
1242       error = clib_error_return (0, "External port already in use.");
1243       goto done;
1244     case VNET_API_ERROR_NO_SUCH_ENTRY:
1245       if (is_add)
1246         error = clib_error_return (0, "External address must be allocated.");
1247       else
1248         error = clib_error_return (0, "Mapping not exist.");
1249       goto done;
1250     case VNET_API_ERROR_NO_SUCH_FIB:
1251       error = clib_error_return (0, "No such VRF id.");
1252       goto done;
1253     case VNET_API_ERROR_VALUE_EXIST:
1254       error = clib_error_return (0, "Mapping already exist.");
1255       goto done;
1256     default:
1257       break;
1258     }
1259
1260 done:
1261   unformat_free (line_input);
1262
1263   return error;
1264 }
1265
1266 static clib_error_t *
1267 add_lb_static_mapping_command_fn (vlib_main_t * vm,
1268                                   unformat_input_t * input,
1269                                   vlib_cli_command_t * cmd)
1270 {
1271   unformat_input_t _line_input, *line_input = &_line_input;
1272   clib_error_t *error = 0;
1273   ip4_address_t l_addr, e_addr;
1274   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0, affinity = 0;
1275   int is_add = 1;
1276   int rv;
1277   nat_protocol_t proto;
1278   u8 proto_set = 0;
1279   nat44_lb_addr_port_t *locals = 0, local;
1280   twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
1281   u8 out2in_only = 0;
1282
1283   /* Get a line of input. */
1284   if (!unformat_user (input, unformat_line_input, line_input))
1285     return 0;
1286
1287   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1288     {
1289       if (unformat (line_input, "local %U:%u probability %u",
1290                     unformat_ip4_address, &l_addr, &l_port, &probability))
1291         {
1292           clib_memset (&local, 0, sizeof (local));
1293           local.addr = l_addr;
1294           local.port = (u16) l_port;
1295           local.probability = (u8) probability;
1296           vec_add1 (locals, local);
1297         }
1298       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
1299                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
1300                          &probability))
1301         {
1302           clib_memset (&local, 0, sizeof (local));
1303           local.addr = l_addr;
1304           local.port = (u16) l_port;
1305           local.probability = (u8) probability;
1306           local.vrf_id = vrf_id;
1307           vec_add1 (locals, local);
1308         }
1309       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
1310                          &e_addr, &e_port))
1311         ;
1312       else if (unformat (line_input, "protocol %U", unformat_nat_protocol,
1313                          &proto))
1314         proto_set = 1;
1315       else if (unformat (line_input, "twice-nat"))
1316         twice_nat = TWICE_NAT;
1317       else if (unformat (line_input, "self-twice-nat"))
1318         twice_nat = TWICE_NAT_SELF;
1319       else if (unformat (line_input, "out2in-only"))
1320         out2in_only = 1;
1321       else if (unformat (line_input, "del"))
1322         is_add = 0;
1323       else if (unformat (line_input, "affinity %u", &affinity))
1324         ;
1325       else
1326         {
1327           error = clib_error_return (0, "unknown input: '%U'",
1328                                      format_unformat_error, line_input);
1329           goto done;
1330         }
1331     }
1332
1333   if (vec_len (locals) < 2)
1334     {
1335       error = clib_error_return (0, "at least two local must be set");
1336       goto done;
1337     }
1338
1339   if (!proto_set)
1340     {
1341       error = clib_error_return (0, "missing protocol");
1342       goto done;
1343     }
1344
1345   rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, locals,
1346                                         is_add, twice_nat, out2in_only, 0,
1347                                         affinity);
1348
1349   switch (rv)
1350     {
1351     case VNET_API_ERROR_INVALID_VALUE:
1352       error = clib_error_return (0, "External port already in use.");
1353       goto done;
1354     case VNET_API_ERROR_NO_SUCH_ENTRY:
1355       if (is_add)
1356         error = clib_error_return (0, "External address must be allocated.");
1357       else
1358         error = clib_error_return (0, "Mapping not exist.");
1359       goto done;
1360     case VNET_API_ERROR_VALUE_EXIST:
1361       error = clib_error_return (0, "Mapping already exist.");
1362       goto done;
1363     case VNET_API_ERROR_FEATURE_DISABLED:
1364       error =
1365         clib_error_return (0, "Available only for endpoint-dependent mode.");
1366       goto done;
1367     default:
1368       break;
1369     }
1370
1371 done:
1372   unformat_free (line_input);
1373   vec_free (locals);
1374
1375   return error;
1376 }
1377
1378 static clib_error_t *
1379 add_lb_backend_command_fn (vlib_main_t * vm,
1380                            unformat_input_t * input, vlib_cli_command_t * cmd)
1381 {
1382   unformat_input_t _line_input, *line_input = &_line_input;
1383   clib_error_t *error = 0;
1384   ip4_address_t l_addr, e_addr;
1385   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0;
1386   int is_add = 1;
1387   int rv;
1388   nat_protocol_t proto;
1389   u8 proto_set = 0;
1390
1391   /* Get a line of input. */
1392   if (!unformat_user (input, unformat_line_input, line_input))
1393     return 0;
1394
1395   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1396     {
1397       if (unformat (line_input, "local %U:%u probability %u",
1398                     unformat_ip4_address, &l_addr, &l_port, &probability))
1399         ;
1400       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
1401                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
1402                          &probability))
1403         ;
1404       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
1405                          &e_addr, &e_port))
1406         ;
1407       else if (unformat (line_input, "protocol %U", unformat_nat_protocol,
1408                          &proto))
1409         proto_set = 1;
1410       else if (unformat (line_input, "del"))
1411         is_add = 0;
1412       else
1413         {
1414           error = clib_error_return (0, "unknown input: '%U'",
1415                                      format_unformat_error, line_input);
1416           goto done;
1417         }
1418     }
1419
1420   if (!l_port || !e_port)
1421     {
1422       error = clib_error_return (0, "local or external must be set");
1423       goto done;
1424     }
1425
1426   if (!proto_set)
1427     {
1428       error = clib_error_return (0, "missing protocol");
1429       goto done;
1430     }
1431
1432   rv =
1433     nat44_lb_static_mapping_add_del_local (e_addr, (u16) e_port, l_addr,
1434                                            l_port, proto, vrf_id, probability,
1435                                            is_add);
1436
1437   switch (rv)
1438     {
1439     case VNET_API_ERROR_INVALID_VALUE:
1440       error = clib_error_return (0, "External is not load-balancing static "
1441                                  "mapping.");
1442       goto done;
1443     case VNET_API_ERROR_NO_SUCH_ENTRY:
1444       error = clib_error_return (0, "Mapping or back-end not exist.");
1445       goto done;
1446     case VNET_API_ERROR_VALUE_EXIST:
1447       error = clib_error_return (0, "Back-end already exist.");
1448       goto done;
1449     case VNET_API_ERROR_FEATURE_DISABLED:
1450       error =
1451         clib_error_return (0, "Available only for endpoint-dependent mode.");
1452       goto done;
1453     case VNET_API_ERROR_UNSPECIFIED:
1454       error = clib_error_return (0, "At least two back-ends must remain");
1455       goto done;
1456     default:
1457       break;
1458     }
1459
1460 done:
1461   unformat_free (line_input);
1462
1463   return error;
1464 }
1465
1466 static clib_error_t *
1467 nat44_show_static_mappings_command_fn (vlib_main_t * vm,
1468                                        unformat_input_t * input,
1469                                        vlib_cli_command_t * cmd)
1470 {
1471   snat_main_t *sm = &snat_main;
1472   snat_static_mapping_t *m;
1473   snat_static_map_resolve_t *rp;
1474
1475   vlib_cli_output (vm, "NAT44 static mappings:");
1476   /* *INDENT-OFF* */
1477   pool_foreach (m, sm->static_mappings)
1478    {
1479     vlib_cli_output (vm, " %U", format_snat_static_mapping, m);
1480   }
1481   vec_foreach (rp, sm->to_resolve)
1482     vlib_cli_output (vm, " %U", format_snat_static_map_to_resolve, rp);
1483   /* *INDENT-ON* */
1484
1485   return 0;
1486 }
1487
1488 static clib_error_t *
1489 snat_add_interface_address_command_fn (vlib_main_t * vm,
1490                                        unformat_input_t * input,
1491                                        vlib_cli_command_t * cmd)
1492 {
1493   snat_main_t *sm = &snat_main;
1494   unformat_input_t _line_input, *line_input = &_line_input;
1495   u32 sw_if_index;
1496   int rv;
1497   int is_del = 0;
1498   clib_error_t *error = 0;
1499   u8 twice_nat = 0;
1500
1501   /* Get a line of input. */
1502   if (!unformat_user (input, unformat_line_input, line_input))
1503     return 0;
1504
1505   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1506     {
1507       if (unformat (line_input, "%U", unformat_vnet_sw_interface,
1508                     sm->vnet_main, &sw_if_index))
1509         ;
1510       else if (unformat (line_input, "twice-nat"))
1511         twice_nat = 1;
1512       else if (unformat (line_input, "del"))
1513         is_del = 1;
1514       else
1515         {
1516           error = clib_error_return (0, "unknown input '%U'",
1517                                      format_unformat_error, line_input);
1518           goto done;
1519         }
1520     }
1521
1522   rv = snat_add_interface_address (sm, sw_if_index, is_del, twice_nat);
1523
1524   switch (rv)
1525     {
1526     case 0:
1527       break;
1528
1529     default:
1530       error = clib_error_return (0, "snat_add_interface_address returned %d",
1531                                  rv);
1532       goto done;
1533     }
1534
1535 done:
1536   unformat_free (line_input);
1537
1538   return error;
1539 }
1540
1541 static clib_error_t *
1542 nat44_show_interface_address_command_fn (vlib_main_t * vm,
1543                                          unformat_input_t * input,
1544                                          vlib_cli_command_t * cmd)
1545 {
1546   snat_main_t *sm = &snat_main;
1547   vnet_main_t *vnm = vnet_get_main ();
1548   u32 *sw_if_index;
1549
1550   /* *INDENT-OFF* */
1551   vlib_cli_output (vm, "NAT44 pool address interfaces:");
1552   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
1553     {
1554       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
1555                        *sw_if_index);
1556     }
1557   vlib_cli_output (vm, "NAT44 twice-nat pool address interfaces:");
1558   vec_foreach (sw_if_index, sm->auto_add_sw_if_indices_twice_nat)
1559     {
1560       vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnm,
1561                        *sw_if_index);
1562     }
1563   /* *INDENT-ON* */
1564
1565   return 0;
1566 }
1567
1568 static clib_error_t *
1569 nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
1570                                 vlib_cli_command_t * cmd)
1571 {
1572   unformat_input_t _line_input, *line_input = &_line_input;
1573   clib_error_t *error = 0;
1574
1575   snat_main_per_thread_data_t *tsm;
1576   snat_main_t *sm = &snat_main;
1577
1578   int detail = 0;
1579   int i = 0;
1580
1581   if (!unformat_user (input, unformat_line_input, line_input))
1582     goto print;
1583
1584   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1585     {
1586       if (unformat (line_input, "detail"))
1587         detail = 1;
1588       else
1589         {
1590           error = clib_error_return (0, "unknown input '%U'",
1591                                      format_unformat_error, line_input);
1592           break;
1593         }
1594     }
1595   unformat_free (line_input);
1596
1597 print:
1598   if (!sm->endpoint_dependent)
1599     vlib_cli_output (vm, "NAT44 sessions:");
1600   else
1601     vlib_cli_output (vm, "NAT44 ED sessions:");
1602
1603   /* *INDENT-OFF* */
1604   vec_foreach_index (i, sm->per_thread_data)
1605     {
1606       tsm = vec_elt_at_index (sm->per_thread_data, i);
1607
1608       vlib_cli_output (vm, "-------- thread %d %s: %d sessions --------\n",
1609                        i, vlib_worker_threads[i].name,
1610                        pool_elts (tsm->sessions));
1611
1612       if (!sm->endpoint_dependent)
1613         {
1614           snat_user_t *u;
1615           pool_foreach (u, tsm->users)
1616            {
1617             vlib_cli_output (vm, "  %U", format_snat_user, tsm, u, detail);
1618           }
1619         }
1620       else
1621         {
1622           snat_session_t *s;
1623           pool_foreach (s, tsm->sessions)
1624            {
1625             vlib_cli_output (vm, "  %U\n", format_snat_session, tsm, s);
1626           }
1627         }
1628     }
1629   /* *INDENT-ON* */
1630   return error;
1631 }
1632
1633 static clib_error_t *
1634 nat44_set_session_limit_command_fn (vlib_main_t * vm,
1635                                     unformat_input_t * input,
1636                                     vlib_cli_command_t * cmd)
1637 {
1638   unformat_input_t _line_input, *line_input = &_line_input;
1639   clib_error_t *error = 0;
1640
1641   u32 session_limit = 0, vrf_id = 0;
1642
1643   /* Get a line of input. */
1644   if (!unformat_user (input, unformat_line_input, line_input))
1645     return 0;
1646
1647   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1648     {
1649       if (unformat (line_input, "%u", &session_limit))
1650         ;
1651       else if (unformat (line_input, "vrf %u", &vrf_id))
1652         ;
1653       else
1654         {
1655           error = clib_error_return (0, "unknown input '%U'",
1656                                      format_unformat_error, line_input);
1657           goto done;
1658         }
1659     }
1660
1661   if (!session_limit)
1662     error = clib_error_return (0, "missing value of session limit");
1663   else if (nat44_update_session_limit (session_limit, vrf_id))
1664     error = clib_error_return (0, "nat44_set_session_limit failed");
1665
1666 done:
1667   unformat_free (line_input);
1668
1669   return error;
1670 }
1671
1672 static clib_error_t *
1673 nat44_del_user_command_fn (vlib_main_t * vm,
1674                            unformat_input_t * input, vlib_cli_command_t * cmd)
1675 {
1676   snat_main_t *sm = &snat_main;
1677   unformat_input_t _line_input, *line_input = &_line_input;
1678   clib_error_t *error = 0;
1679   ip4_address_t addr;
1680   u32 fib_index = 0;
1681   int rv;
1682
1683   if (sm->endpoint_dependent)
1684     return clib_error_return (0, UNSUPPORTED_IN_ED_MODE_STR);
1685
1686   /* Get a line of input. */
1687   if (!unformat_user (input, unformat_line_input, line_input))
1688     return 0;
1689
1690   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1691     {
1692       if (unformat (line_input, "%U", unformat_ip4_address, &addr))
1693         ;
1694       else if (unformat (line_input, "fib %u", &fib_index))
1695         ;
1696       else
1697         {
1698           error = clib_error_return (0, "unknown input '%U'",
1699                                      format_unformat_error, line_input);
1700           goto done;
1701         }
1702     }
1703
1704   rv = nat44_ei_user_del (&addr, fib_index);
1705
1706   if (!rv)
1707     {
1708       error = clib_error_return (0, "nat44_ei_user_del returned %d", rv);
1709     }
1710
1711 done:
1712   unformat_free (line_input);
1713
1714   return error;
1715 }
1716
1717 static clib_error_t *
1718 nat44_clear_sessions_command_fn (vlib_main_t * vm,
1719                                  unformat_input_t * input,
1720                                  vlib_cli_command_t * cmd)
1721 {
1722   clib_error_t *error = 0;
1723   nat44_sessions_clear ();
1724   return error;
1725 }
1726
1727 static clib_error_t *
1728 nat44_del_session_command_fn (vlib_main_t * vm,
1729                               unformat_input_t * input,
1730                               vlib_cli_command_t * cmd)
1731 {
1732   snat_main_t *sm = &snat_main;
1733   unformat_input_t _line_input, *line_input = &_line_input;
1734   int is_in = 0, is_ed = 0;
1735   clib_error_t *error = 0;
1736   ip4_address_t addr, eh_addr;
1737   u32 port = 0, eh_port = 0, vrf_id = sm->outside_vrf_id;
1738   nat_protocol_t proto;
1739   int rv;
1740
1741   /* Get a line of input. */
1742   if (!unformat_user (input, unformat_line_input, line_input))
1743     return 0;
1744
1745   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1746     {
1747       if (unformat
1748           (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port,
1749            unformat_nat_protocol, &proto))
1750         ;
1751       else if (unformat (line_input, "in"))
1752         {
1753           is_in = 1;
1754           vrf_id = sm->inside_vrf_id;
1755         }
1756       else if (unformat (line_input, "out"))
1757         {
1758           is_in = 0;
1759           vrf_id = sm->outside_vrf_id;
1760         }
1761       else if (unformat (line_input, "vrf %u", &vrf_id))
1762         ;
1763       else
1764         if (unformat
1765             (line_input, "external-host %U:%u", unformat_ip4_address,
1766              &eh_addr, &eh_port))
1767         is_ed = 1;
1768       else
1769         {
1770           error = clib_error_return (0, "unknown input '%U'",
1771                                      format_unformat_error, line_input);
1772           goto done;
1773         }
1774     }
1775
1776   if (is_ed)
1777     rv =
1778       nat44_del_ed_session (sm, &addr, clib_host_to_net_u16 (port), &eh_addr,
1779                             clib_host_to_net_u16 (eh_port),
1780                             nat_proto_to_ip_proto (proto), vrf_id, is_in);
1781   else
1782     rv =
1783       nat44_del_session (sm, &addr, clib_host_to_net_u16 (port), proto,
1784                          vrf_id, is_in);
1785
1786   switch (rv)
1787     {
1788     case 0:
1789       break;
1790
1791     default:
1792       error = clib_error_return (0, "nat44_del_session returned %d", rv);
1793       goto done;
1794     }
1795
1796 done:
1797   unformat_free (line_input);
1798
1799   return error;
1800 }
1801
1802 static clib_error_t *
1803 snat_forwarding_set_command_fn (vlib_main_t * vm,
1804                                 unformat_input_t * input,
1805                                 vlib_cli_command_t * cmd)
1806 {
1807   snat_main_t *sm = &snat_main;
1808   unformat_input_t _line_input, *line_input = &_line_input;
1809   u8 forwarding_enable;
1810   u8 forwarding_enable_set = 0;
1811   clib_error_t *error = 0;
1812
1813   /* Get a line of input. */
1814   if (!unformat_user (input, unformat_line_input, line_input))
1815     return clib_error_return (0, "'enable' or 'disable' expected");
1816
1817   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1818     {
1819       if (!forwarding_enable_set && unformat (line_input, "enable"))
1820         {
1821           forwarding_enable = 1;
1822           forwarding_enable_set = 1;
1823         }
1824       else if (!forwarding_enable_set && unformat (line_input, "disable"))
1825         {
1826           forwarding_enable = 0;
1827           forwarding_enable_set = 1;
1828         }
1829       else
1830         {
1831           error = clib_error_return (0, "unknown input '%U'",
1832                                      format_unformat_error, line_input);
1833           goto done;
1834         }
1835     }
1836
1837   if (!forwarding_enable_set)
1838     {
1839       error = clib_error_return (0, "'enable' or 'disable' expected");
1840       goto done;
1841     }
1842
1843   sm->forwarding_enabled = forwarding_enable;
1844
1845 done:
1846   unformat_free (line_input);
1847
1848   return error;
1849 }
1850
1851 static clib_error_t *
1852 set_timeout_command_fn (vlib_main_t * vm,
1853                         unformat_input_t * input, vlib_cli_command_t * cmd)
1854 {
1855   snat_main_t *sm = &snat_main;
1856   unformat_input_t _line_input, *line_input = &_line_input;
1857   clib_error_t *error = 0;
1858
1859   /* Get a line of input. */
1860   if (!unformat_user (input, unformat_line_input, line_input))
1861     return 0;
1862
1863   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1864     {
1865       if (unformat (line_input, "udp %u", &sm->timeouts.udp));
1866       else if (unformat (line_input, "tcp-established %u",
1867                          &sm->timeouts.tcp.established));
1868       else if (unformat (line_input, "tcp-transitory %u",
1869                          &sm->timeouts.tcp.transitory));
1870       else if (unformat (line_input, "icmp %u", &sm->timeouts.icmp));
1871       else if (unformat (line_input, "reset"))
1872         nat_reset_timeouts (&sm->timeouts);
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->timeouts.udp);
1893   vlib_cli_output (vm, "tcp-established timeout: %dsec",
1894                    sm->timeouts.tcp.established);
1895   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
1896                    sm->timeouts.tcp.transitory);
1897   vlib_cli_output (vm, "icmp timeout: %dsec", sm->timeouts.icmp);
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  */