hs-test: fixed timed out tests passing in the CI
[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   u32 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           l_port = clib_host_to_net_u16 (l_port);
1062           local.port = (u16) l_port;
1063           local.probability = (u8) probability;
1064           vec_add1 (locals, local);
1065         }
1066       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
1067                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
1068                          &probability))
1069         {
1070           clib_memset (&local, 0, sizeof (local));
1071           local.addr = l_addr;
1072           l_port = clib_host_to_net_u16 (l_port);
1073           local.port = (u16) l_port;
1074           local.probability = (u8) probability;
1075           local.vrf_id = vrf_id;
1076           vec_add1 (locals, local);
1077         }
1078       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
1079                          &e_addr, &e_port))
1080         {
1081           e_port = clib_host_to_net_u16 (e_port);
1082         }
1083       else if (unformat (line_input, "protocol %U", unformat_ip_protocol,
1084                          &proto))
1085         {
1086           proto_set = 1;
1087         }
1088       else if (unformat (line_input, "twice-nat"))
1089         {
1090           flags |= NAT_SM_FLAG_TWICE_NAT;
1091         }
1092       else if (unformat (line_input, "self-twice-nat"))
1093         {
1094           flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
1095         }
1096       else if (unformat (line_input, "out2in-only"))
1097         {
1098           flags |= NAT_SM_FLAG_OUT2IN_ONLY;
1099         }
1100       else if (unformat (line_input, "del"))
1101         {
1102           is_add = 0;
1103         }
1104       else if (unformat (line_input, "affinity %u", &affinity))
1105         ;
1106       else
1107         {
1108           error = clib_error_return (0, "unknown input: '%U'",
1109                                      format_unformat_error, line_input);
1110           goto done;
1111         }
1112     }
1113
1114   if (vec_len (locals) < 2)
1115     {
1116       error = clib_error_return (0, "at least two local must be set");
1117       goto done;
1118     }
1119
1120   if (!proto_set)
1121     {
1122       error = clib_error_return (0, "missing protocol");
1123       goto done;
1124     }
1125
1126   if (is_add)
1127     {
1128       rv = nat44_ed_add_lb_static_mapping (e_addr, (u16) e_port, proto, locals,
1129                                            flags, 0, affinity);
1130     }
1131   else
1132     {
1133       rv = nat44_ed_del_lb_static_mapping (e_addr, (u16) e_port, proto, flags);
1134     }
1135
1136   switch (rv)
1137     {
1138     case VNET_API_ERROR_INVALID_VALUE:
1139       error = clib_error_return (0, "External port already in use.");
1140       goto done;
1141     case VNET_API_ERROR_NO_SUCH_ENTRY:
1142       if (is_add)
1143         error = clib_error_return (0, "External address must be allocated.");
1144       else
1145         error = clib_error_return (0, "Mapping not exist.");
1146       goto done;
1147     case VNET_API_ERROR_VALUE_EXIST:
1148       error = clib_error_return (0, "Mapping already exist.");
1149       goto done;
1150     default:
1151       break;
1152     }
1153
1154 done:
1155   unformat_free (line_input);
1156   vec_free (locals);
1157
1158   return error;
1159 }
1160
1161 static clib_error_t *
1162 add_lb_backend_command_fn (vlib_main_t * vm,
1163                            unformat_input_t * input, vlib_cli_command_t * cmd)
1164 {
1165   unformat_input_t _line_input, *line_input = &_line_input;
1166   clib_error_t *error = 0;
1167   ip4_address_t l_addr, e_addr;
1168   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0;
1169   int is_add = 1;
1170   int rv;
1171   ip_protocol_t proto;
1172   u8 proto_set = 0;
1173
1174   if (!unformat_user (input, unformat_line_input, line_input))
1175     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
1176
1177   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1178     {
1179       if (unformat (line_input, "local %U:%u probability %u",
1180                     unformat_ip4_address, &l_addr, &l_port, &probability))
1181         ;
1182       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
1183                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
1184                          &probability))
1185         ;
1186       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
1187                          &e_addr, &e_port))
1188         ;
1189       else if (unformat (line_input, "protocol %U", unformat_ip_protocol,
1190                          &proto))
1191         proto_set = 1;
1192       else if (unformat (line_input, "del"))
1193         is_add = 0;
1194       else
1195         {
1196           error = clib_error_return (0, "unknown input: '%U'",
1197                                      format_unformat_error, line_input);
1198           goto done;
1199         }
1200     }
1201
1202   if (!l_port || !e_port)
1203     {
1204       error = clib_error_return (0, "local or external must be set");
1205       goto done;
1206     }
1207
1208   if (!proto_set)
1209     {
1210       error = clib_error_return (0, "missing protocol");
1211       goto done;
1212     }
1213
1214   rv = nat44_ed_add_del_lb_static_mapping_local (
1215     e_addr, (u16) e_port, l_addr, l_port, proto, vrf_id, probability, is_add);
1216
1217   switch (rv)
1218     {
1219     case VNET_API_ERROR_INVALID_VALUE:
1220       error = clib_error_return (0, "External is not load-balancing static "
1221                                  "mapping.");
1222       goto done;
1223     case VNET_API_ERROR_NO_SUCH_ENTRY:
1224       error = clib_error_return (0, "Mapping or back-end not exist.");
1225       goto done;
1226     case VNET_API_ERROR_VALUE_EXIST:
1227       error = clib_error_return (0, "Back-end already exist.");
1228       goto done;
1229     case VNET_API_ERROR_UNSPECIFIED:
1230       error = clib_error_return (0, "At least two back-ends must remain");
1231       goto done;
1232     default:
1233       break;
1234     }
1235
1236 done:
1237   unformat_free (line_input);
1238
1239   return error;
1240 }
1241
1242 static clib_error_t *
1243 nat44_show_static_mappings_command_fn (vlib_main_t * vm,
1244                                        unformat_input_t * input,
1245                                        vlib_cli_command_t * cmd)
1246 {
1247   snat_main_t *sm = &snat_main;
1248   snat_static_mapping_t *m;
1249   snat_static_mapping_resolve_t *rp;
1250
1251   vlib_cli_output (vm, "NAT44 static mappings:");
1252   pool_foreach (m, sm->static_mappings)
1253    {
1254     vlib_cli_output (vm, " %U", format_snat_static_mapping, m);
1255   }
1256   vec_foreach (rp, sm->sm_to_resolve)
1257     vlib_cli_output (vm, " %U", format_snat_static_map_to_resolve, rp);
1258
1259   return 0;
1260 }
1261
1262 static clib_error_t *
1263 snat_add_interface_address_command_fn (vlib_main_t * vm,
1264                                        unformat_input_t * input,
1265                                        vlib_cli_command_t * cmd)
1266 {
1267   unformat_input_t _line_input, *line_input = &_line_input;
1268   vnet_main_t *vnm = vnet_get_main ();
1269   clib_error_t *error = 0;
1270   int rv, is_del = 0;
1271   u8 twice_nat = 0;
1272   u32 sw_if_index;
1273
1274   sw_if_index = ~0;
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, vnm,
1282                     &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_del_interface_address (sw_if_index, twice_nat);
1303     }
1304   else
1305     {
1306       rv = nat44_ed_add_interface_address (sw_if_index, twice_nat);
1307     }
1308
1309   if (0 != rv)
1310     {
1311       error =
1312         clib_error_return (0, "%s %U address failed", is_del ? "del" : "add",
1313                            format_vnet_sw_if_index_name, vnm, sw_if_index);
1314       goto done;
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 plugin enable
1851  * To disable nat44-ed, use:
1852  *  vpp# nat44 plugin disable
1853  * To set inside-vrf outside-vrf, use:
1854  *  vpp# nat44 plugin enable inside-vrf <id> outside-vrf <id>
1855  * @cliexend
1856 ?*/
1857 VLIB_CLI_COMMAND (nat44_ed_enable_disable_command, static) = {
1858   .path = "nat44 plugin",
1859   .function = nat44_ed_enable_disable_command_fn,
1860   .short_help =
1861     "nat44 plugin <enable [sessions <max-number>] [inside-vrf <vrf-id>] "
1862     "[outside-vrf <vrf-id>]>|disable",
1863 };
1864
1865 /*?
1866  * @cliexpar
1867  * @cliexstart{set snat workers}
1868  * Set NAT workers if 2 or more workers available, use:
1869  *  vpp# set snat workers 0-2,5
1870  * @cliexend
1871 ?*/
1872 VLIB_CLI_COMMAND (set_workers_command, static) = {
1873   .path = "set nat workers",
1874   .function = set_workers_command_fn,
1875   .short_help = "set nat workers <workers-list>",
1876 };
1877
1878 /*?
1879  * @cliexpar
1880  * @cliexstart{show nat workers}
1881  * Show NAT workers.
1882  *  vpp# show nat workers:
1883  *  2 workers
1884  *    vpp_wk_0
1885  *    vpp_wk_1
1886  * @cliexend
1887 ?*/
1888 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
1889   .path = "show nat workers",
1890   .short_help = "show nat workers",
1891   .function = nat_show_workers_command_fn,
1892 };
1893
1894 /*?
1895  * @cliexpar
1896  * @cliexstart{set nat timeout}
1897  * Set values of timeouts for NAT sessions (in seconds), use:
1898  *  vpp# set nat timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90
1899  * To reset default values use:
1900  *  vpp# set nat timeout reset
1901  * @cliexend
1902 ?*/
1903 VLIB_CLI_COMMAND (set_timeout_command, static) = {
1904   .path = "set nat timeout",
1905   .function = set_timeout_command_fn,
1906   .short_help =
1907     "set nat timeout [udp <sec> | tcp-established <sec> "
1908     "tcp-transitory <sec> | icmp <sec> | reset]",
1909 };
1910
1911 /*?
1912  * @cliexpar
1913  * @cliexstart{show nat timeouts}
1914  * Show values of timeouts for NAT sessions.
1915  * vpp# show nat timeouts
1916  * udp timeout: 300sec
1917  * tcp-established timeout: 7440sec
1918  * tcp-transitory timeout: 240sec
1919  * icmp timeout: 60sec
1920  * @cliexend
1921 ?*/
1922 VLIB_CLI_COMMAND (nat_show_timeouts_command, static) = {
1923   .path = "show nat timeouts",
1924   .short_help = "show nat timeouts",
1925   .function = nat_show_timeouts_command_fn,
1926 };
1927
1928 /*?
1929  * @cliexpar
1930  * @cliexstart{set nat frame-queue-nelts}
1931  * Set number of worker handoff frame queue elements.
1932  * @cliexend
1933 ?*/
1934 VLIB_CLI_COMMAND (set_frame_queue_nelts_command, static) = {
1935   .path = "set nat frame-queue-nelts",
1936   .function = set_frame_queue_nelts_command_fn,
1937   .short_help = "set nat frame-queue-nelts <number>",
1938 };
1939
1940 /*?
1941  * @cliexpar
1942  * @cliexstart{nat set logging level}
1943  * To set NAT logging level use:
1944  * Set nat logging level
1945  * @cliexend
1946 ?*/
1947 VLIB_CLI_COMMAND (snat_set_log_level_command, static) = {
1948   .path = "nat set logging level",
1949   .function = snat_set_log_level_command_fn,
1950   .short_help = "nat set logging level <level>",
1951 };
1952
1953 /*?
1954  * @cliexpar
1955  * @cliexstart{snat ipfix logging}
1956  * To enable NAT IPFIX logging use:
1957  *  vpp# nat ipfix logging
1958  * To set IPFIX exporter use:
1959  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
1960  * @cliexend
1961 ?*/
1962 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
1963   .path = "nat ipfix logging",
1964   .function = snat_ipfix_logging_enable_disable_command_fn,
1965   .short_help = "nat ipfix logging disable|<enable [domain <domain-id>] "
1966                 "[src-port <port>]>",
1967 };
1968
1969 /*?
1970  * @cliexpar
1971  * @cliexstart{nat mss-clamping}
1972  * Set TCP MSS rewriting configuration
1973  * To enable TCP MSS rewriting use:
1974  *  vpp# nat mss-clamping 1452
1975  * To disbale TCP MSS rewriting use:
1976  *  vpp# nat mss-clamping disable
1977  * @cliexend
1978 ?*/
1979 VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = {
1980     .path = "nat mss-clamping",
1981     .short_help = "nat mss-clamping <mss-value>|disable",
1982     .function = nat_set_mss_clamping_command_fn,
1983 };
1984
1985 /*?
1986  * @cliexpar
1987  * @cliexstart{show nat mss-clamping}
1988  * Show TCP MSS rewriting configuration
1989  * @cliexend
1990 ?*/
1991 VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = {
1992     .path = "show nat mss-clamping",
1993     .short_help = "show nat mss-clamping",
1994     .function = nat_show_mss_clamping_command_fn,
1995 };
1996
1997 /*?
1998  * @cliexpar
1999  * @cliexstart{show nat44 hash tables}
2000  * Show NAT44 hash tables
2001  * @cliexend
2002 ?*/
2003 VLIB_CLI_COMMAND (nat44_show_hash, static) = {
2004   .path = "show nat44 hash tables",
2005   .short_help = "show nat44 hash tables [detail|verbose]",
2006   .function = nat44_show_hash_command_fn,
2007 };
2008
2009 /*?
2010  * @cliexpar
2011  * @cliexstart{nat44 add address}
2012  * Add/delete NAT44 pool address.
2013  * To add NAT44 pool address use:
2014  *  vpp# nat44 add address 172.16.1.3
2015  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
2016  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
2017  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
2018  * @cliexend
2019 ?*/
2020 VLIB_CLI_COMMAND (add_address_command, static) = {
2021   .path = "nat44 add address",
2022   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
2023                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
2024   .function = add_address_command_fn,
2025 };
2026
2027 /*?
2028  * @cliexpar
2029  * @cliexstart{show nat44 summary}
2030  * Show NAT44 summary
2031  * vpp# show nat44 summary
2032  * @cliexend
2033 ?*/
2034 VLIB_CLI_COMMAND (nat44_show_summary_command, static) = {
2035   .path = "show nat44 summary",
2036   .short_help = "show nat44 summary",
2037   .function = nat44_show_summary_command_fn,
2038 };
2039
2040 /*?
2041  * @cliexpar
2042  * @cliexstart{show nat44 addresses}
2043  * Show NAT44 pool addresses.
2044  * vpp# show nat44 addresses
2045  * NAT44 pool addresses:
2046  * 172.16.2.2
2047  *   tenant VRF independent
2048  *   10 busy udp ports
2049  *   0 busy tcp ports
2050  *   0 busy icmp ports
2051  * 172.16.1.3
2052  *   tenant VRF: 10
2053  *   0 busy udp ports
2054  *   2 busy tcp ports
2055  *   0 busy icmp ports
2056  * NAT44 twice-nat pool addresses:
2057  * 10.20.30.72
2058  *   tenant VRF independent
2059  *   0 busy udp ports
2060  *   0 busy tcp ports
2061  *   0 busy icmp ports
2062  * @cliexend
2063 ?*/
2064 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
2065   .path = "show nat44 addresses",
2066   .short_help = "show nat44 addresses",
2067   .function = nat44_show_addresses_command_fn,
2068 };
2069
2070 /*?
2071  * @cliexpar
2072  * @cliexstart{set interface nat44}
2073  * Enable/disable NAT44 feature on the interface.
2074  * To enable NAT44 feature with local network interface use:
2075  *  vpp# set interface nat44 in GigabitEthernet0/8/0
2076  * To enable NAT44 feature with external network interface use:
2077  *  vpp# set interface nat44 out GigabitEthernet0/a/0
2078  * @cliexend
2079 ?*/
2080 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
2081   .path = "set interface nat44",
2082   .function = snat_feature_command_fn,
2083   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
2084                 "[del]",
2085 };
2086
2087 /*?
2088  * @cliexpar
2089  * @cliexstart{show nat44 interfaces}
2090  * Show interfaces with NAT44 feature.
2091  * vpp# show nat44 interfaces
2092  * NAT44 interfaces:
2093  *  GigabitEthernet0/8/0 in
2094  *  GigabitEthernet0/a/0 out
2095  * @cliexend
2096 ?*/
2097 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
2098   .path = "show nat44 interfaces",
2099   .short_help = "show nat44 interfaces",
2100   .function = nat44_show_interfaces_command_fn,
2101 };
2102
2103 /*?
2104  * @cliexpar
2105  * @cliexstart{nat44 add static mapping}
2106  * Static mapping allows hosts on the external network to initiate connection
2107  * to to the local network host.
2108  * To create static mapping between local host address 10.0.0.3 port 6303 and
2109  * external address 4.4.4.4 port 3606 for TCP protocol use:
2110  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
2111  * If not runnig "static mapping only" NAT plugin mode use before:
2112  *  vpp# nat44 add address 4.4.4.4
2113  * To create address only static mapping between local and external address use:
2114  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
2115  * To create ICMP static mapping between local and external with ICMP echo
2116  * identifier 10 use:
2117  *  vpp# nat44 add static mapping icmp local 10.0.0.3 10 external 4.4.4.4 10
2118  * To force use of specific pool address, vrf independent
2119  *  vpp# nat44 add static mapping local 10.0.0.2 1234 external 10.0.2.2 1234 twice-nat exact 10.0.1.2
2120  * @cliexend
2121 ?*/
2122 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
2123   .path = "nat44 add static mapping",
2124   .function = add_static_mapping_command_fn,
2125   .short_help =
2126     "nat44 add static mapping tcp|udp|icmp local <addr> [<port|icmp-echo-id>] "
2127     "external <addr> [<port|icmp-echo-id>] [vrf <table-id>] [twice-nat|self-twice-nat] "
2128     "[out2in-only] [exact <pool-addr>] [del]",
2129 };
2130
2131 /*?
2132  * @cliexpar
2133  * @cliexstart{nat44 add identity mapping}
2134  * Identity mapping translate an IP address to itself.
2135  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
2136  * use:
2137  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
2138  * To create identity mapping for address 10.0.0.3 use:
2139  *  vpp# nat44 add identity mapping 10.0.0.3
2140  * To create identity mapping for DHCP addressed interface use:
2141  *  vpp# nat44 add identity mapping external GigabitEthernet0/a/0 tcp 3606
2142  * @cliexend
2143 ?*/
2144 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
2145   .path = "nat44 add identity mapping",
2146   .function = add_identity_mapping_command_fn,
2147   .short_help = "nat44 add identity mapping <ip4-addr>|external <interface> "
2148     "[<protocol> <port>] [vrf <table-id>] [del]",
2149 };
2150
2151 /*?
2152  * @cliexpar
2153  * @cliexstart{nat44 add load-balancing static mapping}
2154  * Service load balancing using NAT44
2155  * To add static mapping with load balancing for service with external IP
2156  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
2157  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
2158  *  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
2159  * @cliexend
2160 ?*/
2161 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
2162   .path = "nat44 add load-balancing static mapping",
2163   .function = add_lb_static_mapping_command_fn,
2164   .short_help =
2165     "nat44 add load-balancing static mapping protocol tcp|udp "
2166     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2167     "probability <n> [twice-nat|self-twice-nat] [out2in-only] "
2168     "[affinity <timeout-seconds>] [del]",
2169 };
2170
2171 /*?
2172  * @cliexpar
2173  * @cliexstart{nat44 add load-balancing static mapping}
2174  * Modify service load balancing using NAT44
2175  * To add new back-end server 10.100.10.30:8080 for service load balancing
2176  * static mapping with external IP address 1.2.3.4 and TCP port 80 use:
2177  *  vpp# nat44 add load-balancing back-end protocol tcp external 1.2.3.4:80 local 10.100.10.30:8080 probability 25
2178  * @cliexend
2179 ?*/
2180 VLIB_CLI_COMMAND (add_lb_backend_command, static) = {
2181   .path = "nat44 add load-balancing back-end",
2182   .function = add_lb_backend_command_fn,
2183   .short_help =
2184     "nat44 add load-balancing back-end protocol tcp|udp "
2185     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2186     "probability <n> [del]",
2187 };
2188
2189 /*?
2190  * @cliexpar
2191  * @cliexstart{show nat44 static mappings}
2192  * Show NAT44 static mappings.
2193  * vpp# show nat44 static mappings
2194  * NAT44 static mappings:
2195  *  local 10.0.0.3 external 4.4.4.4 vrf 0
2196  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
2197  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
2198  *   local 10.100.10.10:8080 probability 80
2199  *   local 10.100.10.20:8080 probability 20
2200  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
2201  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
2202  * @cliexend
2203 ?*/
2204 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
2205   .path = "show nat44 static mappings",
2206   .short_help = "show nat44 static mappings",
2207   .function = nat44_show_static_mappings_command_fn,
2208 };
2209
2210 /*?
2211  * @cliexpar
2212  * @cliexstart{nat44 add interface address}
2213  * Use NAT44 pool address from specific interfce
2214  * To add NAT44 pool address from specific interface use:
2215  *  vpp# nat44 add interface address GigabitEthernet0/8/0
2216  * @cliexend
2217 ?*/
2218 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
2219   .path = "nat44 add interface address",
2220   .function = snat_add_interface_address_command_fn,
2221   .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
2222 };
2223
2224 /*?
2225  * @cliexpar
2226  * @cliexstart{nat44 vrf table}
2227  * Add empty inter VRF routing table
2228  *  vpp# nat44 vrf table add 10
2229  * @cliexend
2230 ?*/
2231 VLIB_CLI_COMMAND (nat44_ed_add_del_vrf_table_command, static) = {
2232   .path = "nat44 vrf table",
2233   .short_help = "nat44 vrf table [add|del] <vrf-id>",
2234   .function = nat44_ed_add_del_vrf_table_command_fn,
2235 };
2236
2237 /*?
2238  * @cliexpar
2239  * @cliexstart{nat44 vrf route}
2240  * Add inter VRF route record to VRF routing table
2241  *  vpp# nat44 vrf route add table 10 20
2242  * @cliexend
2243 ?*/
2244 VLIB_CLI_COMMAND (nat44_ed_add_del_vrf_route_command, static) = {
2245   .path = "nat44 vrf route",
2246   .short_help = "nat44 vrf route [add|del] table <vrf-id> <vrf-id>",
2247   .function = nat44_ed_add_del_vrf_route_command_fn,
2248 };
2249
2250 /*?
2251  * @cliexpar
2252  * @cliexstart{show nat44 vrf tables}
2253  * Show inter VRF route tables
2254  *  vpp# show nat44 vrf tables
2255  * @cliexend
2256 ?*/
2257 VLIB_CLI_COMMAND (nat44_ed_show_vrf_tables_command, static) = {
2258   .path = "show nat44 vrf tables",
2259   .short_help = "show nat44 vrf tables",
2260   .function = nat44_ed_show_vrf_tables_command_fn,
2261 };
2262
2263 /*?
2264  * @cliexpar
2265  * @cliexstart{show nat44 interface address}
2266  * Show NAT44 pool address interfaces
2267  * vpp# show nat44 interface address
2268  * NAT44 pool address interfaces:
2269  *  GigabitEthernet0/a/0
2270  * NAT44 twice-nat pool address interfaces:
2271  *  GigabitEthernet0/8/0
2272  * @cliexend
2273 ?*/
2274 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
2275   .path = "show nat44 interface address",
2276   .short_help = "show nat44 interface address",
2277   .function = nat44_show_interface_address_command_fn,
2278 };
2279
2280 /*?
2281  * @cliexpar
2282  * @cliexstart{show nat44 sessions}
2283  * Show NAT44 sessions.
2284  * @cliexend
2285 ?*/
2286 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
2287   .path = "show nat44 sessions",
2288   .short_help = "show nat44 sessions [filter {i2o | o2i} {saddr <ip4-addr> "
2289                 "| sport <n> | daddr <ip4-addr> | dport <n> | proto <proto>} "
2290                 "[filter .. [..]]]",
2291   .function = nat44_show_sessions_command_fn,
2292 };
2293
2294 /*?
2295  * @cliexpar
2296  * @cliexstart{set nat44 session limit}
2297  * Set NAT44 session limit.
2298  * @cliexend
2299 ?*/
2300 VLIB_CLI_COMMAND (nat44_set_session_limit_command, static) = {
2301   .path = "set nat44 session limit",
2302   .short_help = "set nat44 session limit <limit> [vrf <table-id>]",
2303   .function = nat44_set_session_limit_command_fn,
2304 };
2305
2306 /*?
2307  * @cliexpar
2308  * @cliexstart{nat44 del session}
2309  * To administratively delete NAT44 session by inside address and port use:
2310  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
2311  * To administratively delete NAT44 session by outside address and port use:
2312  *  vpp# nat44 del session out 1.0.0.3:6033 udp
2313  * @cliexend
2314 ?*/
2315 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
2316     .path = "nat44 del session",
2317     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>] [external-host <addr>:<port>]",
2318     .function = nat44_del_session_command_fn,
2319 };
2320
2321 /*?
2322  * @cliexpar
2323  * @cliexstart{nat44 forwarding}
2324  * Enable or disable forwarding
2325  * Forward packets which don't match existing translation
2326  * or static mapping instead of dropping them.
2327  * To enable forwarding, use:
2328  *  vpp# nat44 forwarding enable
2329  * To disable forwarding, use:
2330  *  vpp# nat44 forwarding disable
2331  * @cliexend
2332 ?*/
2333 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
2334   .path = "nat44 forwarding",
2335   .short_help = "nat44 forwarding enable|disable",
2336   .function = snat_forwarding_set_command_fn,
2337 };
2338
2339 /*
2340  * fd.io coding-style-patch-verification: ON
2341  *
2342  * Local Variables:
2343  * eval: (c-set-style "gnu")
2344  * End:
2345  */