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