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