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