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