NAT44: nat44_del_session and nat44_user_session_details API update (VPP-1271)
[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, is_ed = 0;
963   clib_error_t *error = 0;
964   ip4_address_t addr, eh_addr;
965   u32 port = 0, eh_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, "out"))
988         {
989           is_in = 0;
990           vrf_id = sm->outside_vrf_id;
991         }
992       else if (unformat (line_input, "vrf %u", &vrf_id))
993         ;
994       else
995         if (unformat
996             (line_input, "external-host %U:%u", unformat_ip4_address,
997              &eh_addr, &eh_port))
998         is_ed = 1;
999       else
1000         {
1001           error = clib_error_return (0, "unknown input '%U'",
1002                                      format_unformat_error, line_input);
1003           goto done;
1004         }
1005     }
1006
1007   if (is_ed)
1008     rv =
1009       nat44_del_ed_session (sm, &addr, port, &eh_addr, eh_port,
1010                             snat_proto_to_ip_proto (proto), vrf_id, is_in);
1011   else
1012     rv = nat44_del_session (sm, &addr, port, proto, vrf_id, is_in);
1013
1014   switch (rv)
1015     {
1016     case 0:
1017       break;
1018
1019     default:
1020       error = clib_error_return (0, "nat44_del_session returned %d", rv);
1021       goto done;
1022     }
1023
1024 done:
1025   unformat_free (line_input);
1026
1027   return error;
1028 }
1029
1030 static clib_error_t *
1031 snat_forwarding_set_command_fn (vlib_main_t * vm,
1032                                 unformat_input_t * input,
1033                                 vlib_cli_command_t * cmd)
1034 {
1035   snat_main_t *sm = &snat_main;
1036   unformat_input_t _line_input, *line_input = &_line_input;
1037   u8 forwarding_enable;
1038   u8 forwarding_enable_set = 0;
1039   clib_error_t *error = 0;
1040
1041   if (sm->deterministic)
1042     return clib_error_return (0, UNSUPPORTED_IN_DET_MODE_STR);
1043
1044   /* Get a line of input. */
1045   if (!unformat_user (input, unformat_line_input, line_input))
1046     return clib_error_return (0, "'enable' or 'disable' expected");
1047
1048   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1049     {
1050       if (!forwarding_enable_set && unformat (line_input, "enable"))
1051         {
1052           forwarding_enable = 1;
1053           forwarding_enable_set = 1;
1054         }
1055       else if (!forwarding_enable_set && unformat (line_input, "disable"))
1056         {
1057           forwarding_enable = 0;
1058           forwarding_enable_set = 1;
1059         }
1060       else
1061         {
1062           error = clib_error_return (0, "unknown input '%U'",
1063                                      format_unformat_error, line_input);
1064           goto done;
1065         }
1066     }
1067
1068   if (!forwarding_enable_set)
1069     {
1070       error = clib_error_return (0, "'enable' or 'disable' expected");
1071       goto done;
1072     }
1073
1074   sm->forwarding_enabled = forwarding_enable;
1075
1076 done:
1077   unformat_free (line_input);
1078
1079   return error;
1080 }
1081
1082 static clib_error_t *
1083 snat_det_map_command_fn (vlib_main_t * vm,
1084                          unformat_input_t * input, vlib_cli_command_t * cmd)
1085 {
1086   snat_main_t *sm = &snat_main;
1087   unformat_input_t _line_input, *line_input = &_line_input;
1088   ip4_address_t in_addr, out_addr;
1089   u32 in_plen, out_plen;
1090   int is_add = 1, rv;
1091   clib_error_t *error = 0;
1092
1093   if (!sm->deterministic)
1094     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1095
1096   /* Get a line of input. */
1097   if (!unformat_user (input, unformat_line_input, line_input))
1098     return 0;
1099
1100   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1101     {
1102       if (unformat
1103           (line_input, "in %U/%u", unformat_ip4_address, &in_addr, &in_plen))
1104         ;
1105       else
1106         if (unformat
1107             (line_input, "out %U/%u", unformat_ip4_address, &out_addr,
1108              &out_plen))
1109         ;
1110       else if (unformat (line_input, "del"))
1111         is_add = 0;
1112       else
1113         {
1114           error = clib_error_return (0, "unknown input '%U'",
1115                                      format_unformat_error, line_input);
1116           goto done;
1117         }
1118     }
1119
1120   rv = snat_det_add_map (sm, &in_addr, (u8) in_plen, &out_addr, (u8) out_plen,
1121                          is_add);
1122
1123   if (rv)
1124     {
1125       error = clib_error_return (0, "snat_det_add_map return %d", rv);
1126       goto done;
1127     }
1128
1129 done:
1130   unformat_free (line_input);
1131
1132   return error;
1133 }
1134
1135 static clib_error_t *
1136 nat44_det_show_mappings_command_fn (vlib_main_t * vm,
1137                                     unformat_input_t * input,
1138                                     vlib_cli_command_t * cmd)
1139 {
1140   snat_main_t *sm = &snat_main;
1141   snat_det_map_t *dm;
1142
1143   if (!sm->deterministic)
1144     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1145
1146   vlib_cli_output (vm, "NAT44 deterministic mappings:");
1147   /* *INDENT-OFF* */
1148   pool_foreach (dm, sm->det_maps,
1149   ({
1150     vlib_cli_output (vm, " in %U/%d out %U/%d\n",
1151                      format_ip4_address, &dm->in_addr, dm->in_plen,
1152                      format_ip4_address, &dm->out_addr, dm->out_plen);
1153     vlib_cli_output (vm, "  outside address sharing ratio: %d\n",
1154                      dm->sharing_ratio);
1155     vlib_cli_output (vm, "  number of ports per inside host: %d\n",
1156                      dm->ports_per_host);
1157     vlib_cli_output (vm, "  sessions number: %d\n", dm->ses_num);
1158   }));
1159   /* *INDENT-ON* */
1160
1161   return 0;
1162 }
1163
1164 static clib_error_t *
1165 snat_det_forward_command_fn (vlib_main_t * vm,
1166                              unformat_input_t * input,
1167                              vlib_cli_command_t * cmd)
1168 {
1169   snat_main_t *sm = &snat_main;
1170   unformat_input_t _line_input, *line_input = &_line_input;
1171   ip4_address_t in_addr, out_addr;
1172   u16 lo_port;
1173   snat_det_map_t *dm;
1174   clib_error_t *error = 0;
1175
1176   if (!sm->deterministic)
1177     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1178
1179   /* Get a line of input. */
1180   if (!unformat_user (input, unformat_line_input, line_input))
1181     return 0;
1182
1183   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1184     {
1185       if (unformat (line_input, "%U", unformat_ip4_address, &in_addr))
1186         ;
1187       else
1188         {
1189           error = clib_error_return (0, "unknown input '%U'",
1190                                      format_unformat_error, line_input);
1191           goto done;
1192         }
1193     }
1194
1195   dm = snat_det_map_by_user (sm, &in_addr);
1196   if (!dm)
1197     vlib_cli_output (vm, "no match");
1198   else
1199     {
1200       snat_det_forward (dm, &in_addr, &out_addr, &lo_port);
1201       vlib_cli_output (vm, "%U:<%d-%d>", format_ip4_address, &out_addr,
1202                        lo_port, lo_port + dm->ports_per_host - 1);
1203     }
1204
1205 done:
1206   unformat_free (line_input);
1207
1208   return error;
1209 }
1210
1211 static clib_error_t *
1212 snat_det_reverse_command_fn (vlib_main_t * vm,
1213                              unformat_input_t * input,
1214                              vlib_cli_command_t * cmd)
1215 {
1216   snat_main_t *sm = &snat_main;
1217   unformat_input_t _line_input, *line_input = &_line_input;
1218   ip4_address_t in_addr, out_addr;
1219   u32 out_port;
1220   snat_det_map_t *dm;
1221   clib_error_t *error = 0;
1222
1223   if (!sm->deterministic)
1224     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1225
1226   /* Get a line of input. */
1227   if (!unformat_user (input, unformat_line_input, line_input))
1228     return 0;
1229
1230   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1231     {
1232       if (unformat
1233           (line_input, "%U:%d", unformat_ip4_address, &out_addr, &out_port))
1234         ;
1235       else
1236         {
1237           error = clib_error_return (0, "unknown input '%U'",
1238                                      format_unformat_error, line_input);
1239           goto done;
1240         }
1241     }
1242
1243   if (out_port < 1024 || out_port > 65535)
1244     {
1245       error = clib_error_return (0, "wrong port, must be <1024-65535>");
1246       goto done;
1247     }
1248
1249   dm = snat_det_map_by_out (sm, &out_addr);
1250   if (!dm)
1251     vlib_cli_output (vm, "no match");
1252   else
1253     {
1254       snat_det_reverse (dm, &out_addr, (u16) out_port, &in_addr);
1255       vlib_cli_output (vm, "%U", format_ip4_address, &in_addr);
1256     }
1257
1258 done:
1259   unformat_free (line_input);
1260
1261   return error;
1262 }
1263
1264 static clib_error_t *
1265 set_timeout_command_fn (vlib_main_t * vm,
1266                         unformat_input_t * input, vlib_cli_command_t * cmd)
1267 {
1268   snat_main_t *sm = &snat_main;
1269   unformat_input_t _line_input, *line_input = &_line_input;
1270   clib_error_t *error = 0;
1271
1272   if (!sm->deterministic)
1273     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1274
1275   /* Get a line of input. */
1276   if (!unformat_user (input, unformat_line_input, line_input))
1277     return 0;
1278
1279   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1280     {
1281       if (unformat (line_input, "udp %u", &sm->udp_timeout))
1282         ;
1283       else if (unformat (line_input, "tcp-established %u",
1284                          &sm->tcp_established_timeout))
1285         ;
1286       else if (unformat (line_input, "tcp-transitory %u",
1287                          &sm->tcp_transitory_timeout))
1288         ;
1289       else if (unformat (line_input, "icmp %u", &sm->icmp_timeout))
1290         ;
1291       else if (unformat (line_input, "reset"))
1292         {
1293           sm->udp_timeout = SNAT_UDP_TIMEOUT;
1294           sm->tcp_established_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
1295           sm->tcp_transitory_timeout = SNAT_TCP_TRANSITORY_TIMEOUT;
1296           sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
1297         }
1298       else
1299         {
1300           error = clib_error_return (0, "unknown input '%U'",
1301                                      format_unformat_error, line_input);
1302           goto done;
1303         }
1304     }
1305
1306 done:
1307   unformat_free (line_input);
1308
1309   return error;
1310 }
1311
1312 static clib_error_t *
1313 nat44_det_show_timeouts_command_fn (vlib_main_t * vm,
1314                                     unformat_input_t * input,
1315                                     vlib_cli_command_t * cmd)
1316 {
1317   snat_main_t *sm = &snat_main;
1318
1319   if (!sm->deterministic)
1320     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1321
1322   vlib_cli_output (vm, "udp timeout: %dsec", sm->udp_timeout);
1323   vlib_cli_output (vm, "tcp-established timeout: %dsec",
1324                    sm->tcp_established_timeout);
1325   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
1326                    sm->tcp_transitory_timeout);
1327   vlib_cli_output (vm, "icmp timeout: %dsec", sm->icmp_timeout);
1328
1329   return 0;
1330 }
1331
1332 static clib_error_t *
1333 nat44_det_show_sessions_command_fn (vlib_main_t * vm,
1334                                     unformat_input_t * input,
1335                                     vlib_cli_command_t * cmd)
1336 {
1337   snat_main_t *sm = &snat_main;
1338   snat_det_map_t *dm;
1339   snat_det_session_t *ses;
1340   int i;
1341
1342   if (!sm->deterministic)
1343     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1344
1345   vlib_cli_output (vm, "NAT44 deterministic sessions:");
1346   /* *INDENT-OFF* */
1347   pool_foreach (dm, sm->det_maps,
1348   ({
1349     vec_foreach_index (i, dm->sessions)
1350       {
1351         ses = vec_elt_at_index (dm->sessions, i);
1352         if (ses->in_port)
1353           vlib_cli_output (vm, "  %U", format_det_map_ses, dm, ses, &i);
1354       }
1355   }));
1356   /* *INDENT-ON* */
1357   return 0;
1358 }
1359
1360 static clib_error_t *
1361 snat_det_close_session_out_fn (vlib_main_t * vm,
1362                                unformat_input_t * input,
1363                                vlib_cli_command_t * cmd)
1364 {
1365   snat_main_t *sm = &snat_main;
1366   unformat_input_t _line_input, *line_input = &_line_input;
1367   ip4_address_t out_addr, ext_addr, in_addr;
1368   u32 out_port, ext_port;
1369   snat_det_map_t *dm;
1370   snat_det_session_t *ses;
1371   snat_det_out_key_t key;
1372   clib_error_t *error = 0;
1373
1374   if (!sm->deterministic)
1375     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1376
1377   /* Get a line of input. */
1378   if (!unformat_user (input, unformat_line_input, line_input))
1379     return 0;
1380
1381   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1382     {
1383       if (unformat (line_input, "%U:%d %U:%d",
1384                     unformat_ip4_address, &out_addr, &out_port,
1385                     unformat_ip4_address, &ext_addr, &ext_port))
1386         ;
1387       else
1388         {
1389           error = clib_error_return (0, "unknown input '%U'",
1390                                      format_unformat_error, line_input);
1391           goto done;
1392         }
1393     }
1394
1395   unformat_free (line_input);
1396
1397   dm = snat_det_map_by_out (sm, &out_addr);
1398   if (!dm)
1399     vlib_cli_output (vm, "no match");
1400   else
1401     {
1402       snat_det_reverse (dm, &ext_addr, (u16) out_port, &in_addr);
1403       key.ext_host_addr = out_addr;
1404       key.ext_host_port = ntohs ((u16) ext_port);
1405       key.out_port = ntohs ((u16) out_port);
1406       ses = snat_det_get_ses_by_out (dm, &out_addr, key.as_u64);
1407       if (!ses)
1408         vlib_cli_output (vm, "no match");
1409       else
1410         snat_det_ses_close (dm, ses);
1411     }
1412
1413 done:
1414   unformat_free (line_input);
1415
1416   return error;
1417 }
1418
1419 static clib_error_t *
1420 snat_det_close_session_in_fn (vlib_main_t * vm,
1421                               unformat_input_t * input,
1422                               vlib_cli_command_t * cmd)
1423 {
1424   snat_main_t *sm = &snat_main;
1425   unformat_input_t _line_input, *line_input = &_line_input;
1426   ip4_address_t in_addr, ext_addr;
1427   u32 in_port, ext_port;
1428   snat_det_map_t *dm;
1429   snat_det_session_t *ses;
1430   snat_det_out_key_t key;
1431   clib_error_t *error = 0;
1432
1433   if (!sm->deterministic)
1434     return clib_error_return (0, SUPPORTED_ONLY_IN_DET_MODE_STR);
1435
1436   /* Get a line of input. */
1437   if (!unformat_user (input, unformat_line_input, line_input))
1438     return 0;
1439
1440   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1441     {
1442       if (unformat (line_input, "%U:%d %U:%d",
1443                     unformat_ip4_address, &in_addr, &in_port,
1444                     unformat_ip4_address, &ext_addr, &ext_port))
1445         ;
1446       else
1447         {
1448           error = clib_error_return (0, "unknown input '%U'",
1449                                      format_unformat_error, line_input);
1450           goto done;
1451         }
1452     }
1453
1454   unformat_free (line_input);
1455
1456   dm = snat_det_map_by_user (sm, &in_addr);
1457   if (!dm)
1458     vlib_cli_output (vm, "no match");
1459   else
1460     {
1461       key.ext_host_addr = ext_addr;
1462       key.ext_host_port = ntohs ((u16) ext_port);
1463       ses =
1464         snat_det_find_ses_by_in (dm, &in_addr, ntohs ((u16) in_port), key);
1465       if (!ses)
1466         vlib_cli_output (vm, "no match");
1467       else
1468         snat_det_ses_close (dm, ses);
1469     }
1470
1471 done:
1472   unformat_free (line_input);
1473
1474   return error;
1475 }
1476 /* *INDENT-OFF* */
1477
1478 /*?
1479  * @cliexpar
1480  * @cliexstart{set snat workers}
1481  * Set NAT workers if 2 or more workers available, use:
1482  *  vpp# set snat workers 0-2,5
1483  * @cliexend
1484 ?*/
1485 VLIB_CLI_COMMAND (set_workers_command, static) = {
1486   .path = "set nat workers",
1487   .function = set_workers_command_fn,
1488   .short_help = "set nat workers <workers-list>",
1489 };
1490
1491 /*?
1492  * @cliexpar
1493  * @cliexstart{show nat workers}
1494  * Show NAT workers.
1495  *  vpp# show nat workers:
1496  *  2 workers
1497  *    vpp_wk_0
1498  *    vpp_wk_1
1499  * @cliexend
1500 ?*/
1501 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
1502   .path = "show nat workers",
1503   .short_help = "show nat workers",
1504   .function = nat_show_workers_commnad_fn,
1505 };
1506
1507 /*?
1508  * @cliexpar
1509  * @cliexstart{snat ipfix logging}
1510  * To enable NAT IPFIX logging use:
1511  *  vpp# nat ipfix logging
1512  * To set IPFIX exporter use:
1513  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
1514  * @cliexend
1515 ?*/
1516 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
1517   .path = "nat ipfix logging",
1518   .function = snat_ipfix_logging_enable_disable_command_fn,
1519   .short_help = "nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]",
1520 };
1521
1522 /*?
1523  * @cliexpar
1524  * @cliexstart{nat addr-port-assignment-alg}
1525  * Set address and port assignment algorithm
1526  * For the MAP-E CE limit port choice based on PSID use:
1527  *  vpp# nat addr-port-assignment-alg map-e psid 10 psid-offset 6 psid-len 6
1528  * To set standard (default) address and port assignment algorithm use:
1529  *  vpp# nat addr-port-assignment-alg default
1530  * @cliexend
1531 ?*/
1532 VLIB_CLI_COMMAND (nat44_set_alloc_addr_and_port_alg_command, static) = {
1533     .path = "nat addr-port-assignment-alg",
1534     .short_help = "nat addr-port-assignment-alg <alg-name> [<alg-params>]",
1535     .function = nat44_set_alloc_addr_and_port_alg_command_fn,
1536 };
1537
1538 /*?
1539  * @cliexpar
1540  * @cliexstart{show nat44 hash tables}
1541  * Show NAT44 hash tables
1542  * @cliexend
1543 ?*/
1544 VLIB_CLI_COMMAND (nat44_show_hash, static) = {
1545   .path = "show nat44 hash tables",
1546   .short_help = "show nat44 hash tables [detail|verbose]",
1547   .function = nat44_show_hash_commnad_fn,
1548 };
1549
1550 /*?
1551  * @cliexpar
1552  * @cliexstart{nat44 add address}
1553  * Add/delete NAT44 pool address.
1554  * To add NAT44 pool address use:
1555  *  vpp# nat44 add address 172.16.1.3
1556  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
1557  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
1558  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
1559  * @cliexend
1560 ?*/
1561 VLIB_CLI_COMMAND (add_address_command, static) = {
1562   .path = "nat44 add address",
1563   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
1564                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
1565   .function = add_address_command_fn,
1566 };
1567
1568 /*?
1569  * @cliexpar
1570  * @cliexstart{show nat44 addresses}
1571  * Show NAT44 pool addresses.
1572  * vpp# show nat44 addresses
1573  * NAT44 pool addresses:
1574  * 172.16.2.2
1575  *   tenant VRF independent
1576  *   10 busy udp ports
1577  *   0 busy tcp ports
1578  *   0 busy icmp ports
1579  * 172.16.1.3
1580  *   tenant VRF: 10
1581  *   0 busy udp ports
1582  *   2 busy tcp ports
1583  *   0 busy icmp ports
1584  * NAT44 twice-nat pool addresses:
1585  * 10.20.30.72
1586  *   tenant VRF independent
1587  *   0 busy udp ports
1588  *   0 busy tcp ports
1589  *   0 busy icmp ports
1590  * @cliexend
1591 ?*/
1592 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
1593   .path = "show nat44 addresses",
1594   .short_help = "show nat44 addresses",
1595   .function = nat44_show_addresses_command_fn,
1596 };
1597
1598 /*?
1599  * @cliexpar
1600  * @cliexstart{set interface nat44}
1601  * Enable/disable NAT44 feature on the interface.
1602  * To enable NAT44 feature with local network interface use:
1603  *  vpp# set interface nat44 in GigabitEthernet0/8/0
1604  * To enable NAT44 feature with external network interface use:
1605  *  vpp# set interface nat44 out GigabitEthernet0/a/0
1606  * @cliexend
1607 ?*/
1608 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
1609   .path = "set interface nat44",
1610   .function = snat_feature_command_fn,
1611   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
1612                 "[del]",
1613 };
1614
1615 /*?
1616  * @cliexpar
1617  * @cliexstart{show nat44 interfaces}
1618  * Show interfaces with NAT44 feature.
1619  * vpp# show nat44 interfaces
1620  * NAT44 interfaces:
1621  *  GigabitEthernet0/8/0 in
1622  *  GigabitEthernet0/a/0 out
1623  * @cliexend
1624 ?*/
1625 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
1626   .path = "show nat44 interfaces",
1627   .short_help = "show nat44 interfaces",
1628   .function = nat44_show_interfaces_command_fn,
1629 };
1630
1631 /*?
1632  * @cliexpar
1633  * @cliexstart{nat44 add static mapping}
1634  * Static mapping allows hosts on the external network to initiate connection
1635  * to to the local network host.
1636  * To create static mapping between local host address 10.0.0.3 port 6303 and
1637  * external address 4.4.4.4 port 3606 for TCP protocol use:
1638  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
1639  * If not runnig "static mapping only" NAT plugin mode use before:
1640  *  vpp# nat44 add address 4.4.4.4
1641  * To create static mapping between local and external address use:
1642  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
1643  * @cliexend
1644 ?*/
1645 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
1646   .path = "nat44 add static mapping",
1647   .function = add_static_mapping_command_fn,
1648   .short_help =
1649     "nat44 add static mapping tcp|udp|icmp local <addr> [<port>] "
1650     "external <addr> [<port>] [vrf <table-id>] [twice-nat|self-twice-nat] "
1651     "[out2in-only] [del]",
1652 };
1653
1654 /*?
1655  * @cliexpar
1656  * @cliexstart{nat44 add identity mapping}
1657  * Identity mapping translate an IP address to itself.
1658  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
1659  * use:
1660  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
1661  * To create identity mapping for address 10.0.0.3 use:
1662  *  vpp# nat44 add identity mapping 10.0.0.3
1663  * To create identity mapping for DHCP addressed interface use:
1664  *  vpp# nat44 add identity mapping GigabitEthernet0/a/0 tcp 3606
1665  * @cliexend
1666 ?*/
1667 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
1668   .path = "nat44 add identity mapping",
1669   .function = add_identity_mapping_command_fn,
1670   .short_help = "nat44 add identity mapping <interface>|<ip4-addr> "
1671     "[<protocol> <port>] [vrf <table-id>] [del]",
1672 };
1673
1674 /*?
1675  * @cliexpar
1676  * @cliexstart{nat44 add load-balancing static mapping}
1677  * Service load balancing using NAT44
1678  * To add static mapping with load balancing for service with external IP
1679  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
1680  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
1681  *  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
1682  * @cliexend
1683 ?*/
1684 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
1685   .path = "nat44 add load-balancing static mapping",
1686   .function = add_lb_static_mapping_command_fn,
1687   .short_help =
1688     "nat44 add load-balancing static mapping protocol tcp|udp "
1689     "external <addr>:<port> local <addr>:<port> probability <n> "
1690     "[twice-nat|self-twice-nat] [vrf <table-id>] [out2in-only] [del]",
1691 };
1692
1693 /*?
1694  * @cliexpar
1695  * @cliexstart{show nat44 static mappings}
1696  * Show NAT44 static mappings.
1697  * vpp# show nat44 static mappings
1698  * NAT44 static mappings:
1699  *  local 10.0.0.3 external 4.4.4.4 vrf 0
1700  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
1701  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
1702  *   local 10.100.10.10:8080 probability 80
1703  *   local 10.100.10.20:8080 probability 20
1704  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
1705  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
1706  * @cliexend
1707 ?*/
1708 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
1709   .path = "show nat44 static mappings",
1710   .short_help = "show nat44 static mappings",
1711   .function = nat44_show_static_mappings_command_fn,
1712 };
1713
1714 /*?
1715  * @cliexpar
1716  * @cliexstart{nat44 add interface address}
1717  * Use NAT44 pool address from specific interfce
1718  * To add NAT44 pool address from specific interface use:
1719  *  vpp# nat44 add interface address GigabitEthernet0/8/0
1720  * @cliexend
1721 ?*/
1722 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
1723     .path = "nat44 add interface address",
1724     .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
1725     .function = snat_add_interface_address_command_fn,
1726 };
1727
1728 /*?
1729  * @cliexpar
1730  * @cliexstart{show nat44 interface address}
1731  * Show NAT44 pool address interfaces
1732  * vpp# show nat44 interface address
1733  * NAT44 pool address interfaces:
1734  *  GigabitEthernet0/a/0
1735  * NAT44 twice-nat pool address interfaces:
1736  *  GigabitEthernet0/8/0
1737  * @cliexend
1738 ?*/
1739 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
1740   .path = "show nat44 interface address",
1741   .short_help = "show nat44 interface address",
1742   .function = nat44_show_interface_address_command_fn,
1743 };
1744
1745 /*?
1746  * @cliexpar
1747  * @cliexstart{show nat44 sessions}
1748  * Show NAT44 sessions.
1749  * @cliexend
1750 ?*/
1751 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
1752   .path = "show nat44 sessions",
1753   .short_help = "show nat44 sessions [detail]",
1754   .function = nat44_show_sessions_command_fn,
1755 };
1756
1757 /*?
1758  * @cliexpar
1759  * @cliexstart{nat44 del session}
1760  * To administratively delete NAT44 session by inside address and port use:
1761  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
1762  * To administratively delete NAT44 session by outside address and port use:
1763  *  vpp# nat44 del session out 1.0.0.3:6033 udp
1764  * @cliexend
1765 ?*/
1766 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
1767     .path = "nat44 del session",
1768     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>] [external-host <addr>:<port>]",
1769     .function = nat44_del_session_command_fn,
1770 };
1771
1772 /*?
1773  * @cliexpar
1774  * @cliexstart{nat44 forwarding}
1775  * Enable or disable forwarding
1776  * Forward packets which don't match existing translation
1777  * or static mapping instead of dropping them.
1778  * To enable forwarding, use:
1779  *  vpp# nat44 forwarding enable
1780  * To disable forwarding, use:
1781  *  vpp# nat44 forwarding disable
1782  * @cliexend
1783 ?*/
1784 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
1785   .path = "nat44 forwarding",
1786   .short_help = "nat44 forwarding enable|disable",
1787   .function = snat_forwarding_set_command_fn,
1788 };
1789
1790 /*?
1791  * @cliexpar
1792  * @cliexstart{nat44 deterministic add}
1793  * Create bijective mapping of inside address to outside address and port range
1794  * pairs, with the purpose of enabling deterministic NAT to reduce logging in
1795  * CGN deployments.
1796  * To create deterministic mapping between inside network 10.0.0.0/18 and
1797  * outside network 1.1.1.0/30 use:
1798  * # vpp# nat44 deterministic add in 10.0.0.0/18 out 1.1.1.0/30
1799  * @cliexend
1800 ?*/
1801 VLIB_CLI_COMMAND (snat_det_map_command, static) = {
1802     .path = "nat44 deterministic add",
1803     .short_help = "nat44 deterministic add in <addr>/<plen> out <addr>/<plen> [del]",
1804     .function = snat_det_map_command_fn,
1805 };
1806
1807 /*?
1808  * @cliexpar
1809  * @cliexpstart{show nat44 deterministic mappings}
1810  * Show NAT44 deterministic mappings
1811  * vpp# show nat44 deterministic mappings
1812  * NAT44 deterministic mappings:
1813  *  in 10.0.0.0/24 out 1.1.1.1/32
1814  *   outside address sharing ratio: 256
1815  *   number of ports per inside host: 252
1816  *   sessions number: 0
1817  * @cliexend
1818 ?*/
1819 VLIB_CLI_COMMAND (nat44_det_show_mappings_command, static) = {
1820     .path = "show nat44 deterministic mappings",
1821     .short_help = "show nat44 deterministic mappings",
1822     .function = nat44_det_show_mappings_command_fn,
1823 };
1824
1825 /*?
1826  * @cliexpar
1827  * @cliexstart{nat44 deterministic forward}
1828  * Return outside address and port range from inside address for deterministic
1829  * NAT.
1830  * To obtain outside address and port of inside host use:
1831  *  vpp# nat44 deterministic forward 10.0.0.2
1832  *  1.1.1.0:<1054-1068>
1833  * @cliexend
1834 ?*/
1835 VLIB_CLI_COMMAND (snat_det_forward_command, static) = {
1836     .path = "nat44 deterministic forward",
1837     .short_help = "nat44 deterministic forward <addr>",
1838     .function = snat_det_forward_command_fn,
1839 };
1840
1841 /*?
1842  * @cliexpar
1843  * @cliexstart{nat44 deterministic reverse}
1844  * Return inside address from outside address and port for deterministic NAT.
1845  * To obtain inside host address from outside address and port use:
1846  *  #vpp nat44 deterministic reverse 1.1.1.1:1276
1847  *  10.0.16.16
1848  * @cliexend
1849 ?*/
1850 VLIB_CLI_COMMAND (snat_det_reverse_command, static) = {
1851     .path = "nat44 deterministic reverse",
1852     .short_help = "nat44 deterministic reverse <addr>:<port>",
1853     .function = snat_det_reverse_command_fn,
1854 };
1855
1856 /*?
1857  * @cliexpar
1858  * @cliexstart{set nat44 deterministic timeout}
1859  * Set values of timeouts for deterministic NAT (in seconds), use:
1860  *  vpp# set nat44 deterministic timeout udp 120 tcp-established 7500
1861  *  tcp-transitory 250 icmp 90
1862  * To reset default values use:
1863  *  vpp# set nat44 deterministic timeout reset
1864  * @cliexend
1865 ?*/
1866 VLIB_CLI_COMMAND (set_timeout_command, static) = {
1867   .path = "set nat44 deterministic timeout",
1868   .function = set_timeout_command_fn,
1869   .short_help =
1870     "set nat44 deterministic timeout [udp <sec> | tcp-established <sec> "
1871     "tcp-transitory <sec> | icmp <sec> | reset]",
1872 };
1873
1874 /*?
1875  * @cliexpar
1876  * @cliexstart{show nat44 deterministic timeouts}
1877  * Show values of timeouts for deterministic NAT.
1878  * vpp# show nat44 deterministic timeouts
1879  * udp timeout: 300sec
1880  * tcp-established timeout: 7440sec
1881  * tcp-transitory timeout: 240sec
1882  * icmp timeout: 60sec
1883  * @cliexend
1884 ?*/
1885 VLIB_CLI_COMMAND (nat44_det_show_timeouts_command, static) = {
1886   .path = "show nat44 deterministic timeouts",
1887   .short_help = "show nat44 deterministic timeouts",
1888   .function = nat44_det_show_timeouts_command_fn,
1889 };
1890
1891 /*?
1892  * @cliexpar
1893  * @cliexstart{show nat44 deterministic sessions}
1894  * Show NAT44 deterministic sessions.
1895  * vpp# show nat44 deterministic sessions
1896  * NAT44 deterministic sessions:
1897  *   in 10.0.0.3:3005 out 1.1.1.2:1146 external host 172.16.1.2:3006 state: udp-active expire: 306
1898  *   in 10.0.0.3:3000 out 1.1.1.2:1141 external host 172.16.1.2:3001 state: udp-active expire: 306
1899  *   in 10.0.0.4:3005 out 1.1.1.2:1177 external host 172.16.1.2:3006 state: udp-active expire: 306
1900  * @cliexend
1901 ?*/
1902 VLIB_CLI_COMMAND (nat44_det_show_sessions_command, static) = {
1903   .path = "show nat44 deterministic sessions",
1904   .short_help = "show nat44 deterministic sessions",
1905   .function = nat44_det_show_sessions_command_fn,
1906 };
1907
1908 /*?
1909  * @cliexpar
1910  * @cliexstart{nat44 deterministic close session out}
1911  * Close session using outside ip address and port
1912  * and external ip address and port, use:
1913  *  vpp# nat44 deterministic close session out 1.1.1.1:1276 2.2.2.2:2387
1914  * @cliexend
1915 ?*/
1916 VLIB_CLI_COMMAND (snat_det_close_sesion_out_command, static) = {
1917   .path = "nat44 deterministic close session out",
1918   .short_help = "nat44 deterministic close session out "
1919                 "<out_addr>:<out_port> <ext_addr>:<ext_port>",
1920   .function = snat_det_close_session_out_fn,
1921 };
1922
1923 /*?
1924  * @cliexpar
1925  * @cliexstart{nat44 deterministic close session in}
1926  * Close session using inside ip address and port
1927  * and external ip address and port, use:
1928  *  vpp# nat44 deterministic close session in 3.3.3.3:3487 2.2.2.2:2387
1929  * @cliexend
1930 ?*/
1931 VLIB_CLI_COMMAND (snat_det_close_session_in_command, static) = {
1932   .path = "nat44 deterministic close session in",
1933   .short_help = "nat44 deterministic close session in "
1934                 "<in_addr>:<in_port> <ext_addr>:<ext_port>",
1935   .function = snat_det_close_session_in_fn,
1936 };
1937
1938 /* *INDENT-ON* */
1939
1940 /*
1941  * fd.io coding-style-patch-verification: ON
1942  *
1943  * Local Variables:
1944  * eval: (c-set-style "gnu")
1945  * End:
1946  */