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