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