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