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