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