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