cfd362786741f4910a398af15b496b715b1d4672
[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   u32 udp_sessions = 0;
482   u32 tcp_sessions = 0;
483   u32 icmp_sessions = 0;
484   u32 other_sessions = 0;
485
486   u32 timed_out = 0;
487   u32 transitory = 0;
488   u32 transitory_wait_closed = 0;
489   u32 transitory_closed = 0;
490   u32 established = 0;
491
492   u32 fib;
493
494   for (fib = 0; fib < vec_len (sm->max_translations_per_fib); fib++)
495     vlib_cli_output (vm, "max translations per thread: %u fib %u",
496                      sm->max_translations_per_fib[fib], fib);
497
498   if (sm->num_workers > 1)
499     {
500       vec_foreach (tsm, sm->per_thread_data)
501         {
502           pool_foreach (s, tsm->sessions)
503            {
504             sess_timeout_time = s->last_heard +
505               (f64) nat44_session_get_timeout (sm, s);
506             if (now >= sess_timeout_time)
507               timed_out++;
508
509             switch (s->proto)
510               {
511               case IP_PROTOCOL_ICMP:
512                 icmp_sessions++;
513                 break;
514               case IP_PROTOCOL_TCP:
515                 tcp_sessions++;
516                 if (s->state)
517                   {
518                     if (s->tcp_closed_timestamp)
519                       {
520                         if (now >= s->tcp_closed_timestamp)
521                           {
522                             ++transitory_closed;
523                           }
524                         else
525                           {
526                             ++transitory_wait_closed;
527                           }
528                       }
529                     transitory++;
530                   }
531                 else
532                   established++;
533                 break;
534               case IP_PROTOCOL_UDP:
535                 udp_sessions++;
536                 break;
537               default:
538                 ++other_sessions;
539                 break;
540               }
541            }
542           nat44_show_lru_summary (vm, tsm, now, sess_timeout_time);
543           count += pool_elts (tsm->sessions);
544         }
545     }
546   else
547     {
548       tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
549       pool_foreach (s, tsm->sessions)
550        {
551         sess_timeout_time = s->last_heard +
552             (f64) nat44_session_get_timeout (sm, s);
553         if (now >= sess_timeout_time)
554           timed_out++;
555
556         switch (s->proto)
557           {
558           case IP_PROTOCOL_ICMP:
559             icmp_sessions++;
560             break;
561           case IP_PROTOCOL_TCP:
562             tcp_sessions++;
563             if (s->state)
564               {
565                 if (s->tcp_closed_timestamp)
566                   {
567                     if (now >= s->tcp_closed_timestamp)
568                       {
569                         ++transitory_closed;
570                       }
571                     else
572                       {
573                         ++transitory_wait_closed;
574                       }
575                   }
576                 transitory++;
577               }
578             else
579               established++;
580             break;
581           case IP_PROTOCOL_UDP:
582             udp_sessions++;
583             break;
584           default:
585             ++other_sessions;
586             break;
587           }
588       }
589       nat44_show_lru_summary (vm, tsm, now, sess_timeout_time);
590       count = pool_elts (tsm->sessions);
591     }
592
593   vlib_cli_output (vm, "total timed out sessions: %u", timed_out);
594   vlib_cli_output (vm, "total sessions: %u", count);
595   vlib_cli_output (vm, "total tcp sessions: %u", tcp_sessions);
596   vlib_cli_output (vm, "total tcp established sessions: %u", established);
597   vlib_cli_output (vm, "total tcp transitory sessions: %u", transitory);
598   vlib_cli_output (vm, "total tcp transitory (WAIT-CLOSED) sessions: %u",
599                    transitory_wait_closed);
600   vlib_cli_output (vm, "total tcp transitory (CLOSED) sessions: %u",
601                    transitory_closed);
602   vlib_cli_output (vm, "total udp sessions: %u", udp_sessions);
603   vlib_cli_output (vm, "total icmp sessions: %u", icmp_sessions);
604   vlib_cli_output (vm, "total other sessions: %u", other_sessions);
605   return 0;
606 }
607
608 static clib_error_t *
609 nat44_show_addresses_command_fn (vlib_main_t * vm, unformat_input_t * input,
610                                  vlib_cli_command_t * cmd)
611 {
612   snat_main_t *sm = &snat_main;
613   snat_address_t *ap;
614
615   vlib_cli_output (vm, "NAT44 pool addresses:");
616   vec_foreach (ap, sm->addresses)
617     {
618       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
619       if (ap->fib_index != ~0)
620         vlib_cli_output (
621           vm, "  tenant VRF: %u",
622           fib_table_get (ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
623       else
624         vlib_cli_output (vm, "  tenant VRF independent");
625
626       if (ap->addr_len != ~0)
627         vlib_cli_output (vm, "  synced with interface address");
628     }
629   vlib_cli_output (vm, "NAT44 twice-nat pool addresses:");
630   vec_foreach (ap, sm->twice_nat_addresses)
631     {
632       vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
633       if (ap->fib_index != ~0)
634           vlib_cli_output (vm, "  tenant VRF: %u",
635             fib_table_get(ap->fib_index, FIB_PROTOCOL_IP4)->ft_table_id);
636       else
637         vlib_cli_output (vm, "  tenant VRF independent");
638
639       if (ap->addr_len != ~0)
640         vlib_cli_output (vm, "  synced with interface address");
641     }
642   return 0;
643 }
644
645 static clib_error_t *
646 snat_feature_command_fn (vlib_main_t * vm,
647                          unformat_input_t * input, vlib_cli_command_t * cmd)
648 {
649   unformat_input_t _line_input, *line_input = &_line_input;
650   vnet_main_t *vnm = vnet_get_main ();
651   clib_error_t *error = 0;
652   u32 sw_if_index;
653   u32 *inside_sw_if_indices = 0;
654   u32 *outside_sw_if_indices = 0;
655   u8 is_output_feature = 0;
656   int i, rv, is_del = 0;
657
658   sw_if_index = ~0;
659
660   /* Get a line of input. */
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   // TODO: specific pool_addr for both pool & twice nat pool ?
915
916   if (is_add)
917     {
918       rv =
919         nat44_ed_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
920                                      vrf_id, sw_if_index, flags, pool_addr, 0);
921     }
922   else
923     {
924       rv = nat44_ed_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
925                                         vrf_id, sw_if_index, flags);
926     }
927
928   // TODO: fix returns
929
930   switch (rv)
931     {
932     case VNET_API_ERROR_INVALID_VALUE:
933       error = clib_error_return (0, "External port already in use.");
934       goto done;
935     case VNET_API_ERROR_NO_SUCH_ENTRY:
936       if (is_add)
937         error = clib_error_return (0, "External address must be allocated.");
938       else
939         error = clib_error_return (0, "Mapping not exist.");
940       goto done;
941     case VNET_API_ERROR_NO_SUCH_FIB:
942       error = clib_error_return (0, "No such VRF id.");
943       goto done;
944     case VNET_API_ERROR_VALUE_EXIST:
945       error = clib_error_return (0, "Mapping already exist.");
946       goto done;
947     default:
948       break;
949     }
950
951 done:
952   unformat_free (line_input);
953
954   return error;
955 }
956
957 // TODO: either delete this bullshit or update it
958 static clib_error_t *
959 add_identity_mapping_command_fn (vlib_main_t * vm,
960                                  unformat_input_t * input,
961                                  vlib_cli_command_t * cmd)
962 {
963   unformat_input_t _line_input, *line_input = &_line_input;
964   vnet_main_t *vnm = vnet_get_main ();
965   clib_error_t *error = 0;
966
967   int rv, is_add = 1, port_set = 0;
968   u32 sw_if_index, port, flags, vrf_id = ~0;
969   ip_protocol_t proto = 0;
970   ip4_address_t addr;
971
972   flags = NAT_SM_FLAG_IDENTITY_NAT;
973
974   /* Get a line of input. */
975   if (!unformat_user (input, unformat_line_input, line_input))
976     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
977
978   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
979     {
980       if (unformat (line_input, "%U", unformat_ip4_address, &addr))
981         ;
982       else if (unformat (line_input, "external %U",
983                          unformat_vnet_sw_interface, vnm, &sw_if_index))
984         {
985           flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
986         }
987       else if (unformat (line_input, "vrf %u", &vrf_id))
988         ;
989       else if (unformat (line_input, "%U %u", unformat_ip_protocol, &proto,
990                          &port))
991         {
992           port_set = 1;
993         }
994       else if (unformat (line_input, "del"))
995         {
996           is_add = 0;
997         }
998       else
999         {
1000           error = clib_error_return (0, "unknown input: '%U'",
1001                                      format_unformat_error, line_input);
1002           goto done;
1003         }
1004     }
1005
1006   if (!port_set)
1007     {
1008       flags |= NAT_SM_FLAG_ADDR_ONLY;
1009     }
1010   else
1011     {
1012       port = clib_host_to_net_u16 (port);
1013     }
1014
1015   if (is_add)
1016     {
1017
1018       rv = nat44_ed_add_static_mapping (addr, addr, port, port, proto, vrf_id,
1019                                         sw_if_index, flags, addr, 0);
1020     }
1021   else
1022     {
1023       rv = nat44_ed_del_static_mapping (addr, addr, port, port, proto, vrf_id,
1024                                         sw_if_index, flags);
1025     }
1026
1027   // TODO: fix returns
1028
1029   switch (rv)
1030     {
1031     case VNET_API_ERROR_INVALID_VALUE:
1032       error = clib_error_return (0, "External port already in use.");
1033       goto done;
1034     case VNET_API_ERROR_NO_SUCH_ENTRY:
1035       if (is_add)
1036         error = clib_error_return (0, "External address must be allocated.");
1037       else
1038         error = clib_error_return (0, "Mapping not exist.");
1039       goto done;
1040     case VNET_API_ERROR_NO_SUCH_FIB:
1041       error = clib_error_return (0, "No such VRF id.");
1042       goto done;
1043     case VNET_API_ERROR_VALUE_EXIST:
1044       error = clib_error_return (0, "Mapping already exist.");
1045       goto done;
1046     default:
1047       break;
1048     }
1049
1050 done:
1051   unformat_free (line_input);
1052
1053   return error;
1054 }
1055
1056 static clib_error_t *
1057 add_lb_static_mapping_command_fn (vlib_main_t * vm,
1058                                   unformat_input_t * input,
1059                                   vlib_cli_command_t * cmd)
1060 {
1061   unformat_input_t _line_input, *line_input = &_line_input;
1062   clib_error_t *error = 0;
1063   ip4_address_t l_addr, e_addr;
1064   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0, affinity = 0;
1065   u8 proto_set = 0;
1066   ip_protocol_t proto;
1067   nat44_lb_addr_port_t *locals = 0, local;
1068   int rv, is_add = 1;
1069   u32 flags = 0;
1070
1071   /* Get a line of input. */
1072   if (!unformat_user (input, unformat_line_input, line_input))
1073     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
1074
1075   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1076     {
1077       if (unformat (line_input, "local %U:%u probability %u",
1078                     unformat_ip4_address, &l_addr, &l_port, &probability))
1079         {
1080           clib_memset (&local, 0, sizeof (local));
1081           local.addr = l_addr;
1082           local.port = (u16) l_port;
1083           local.probability = (u8) probability;
1084           vec_add1 (locals, local);
1085         }
1086       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
1087                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
1088                          &probability))
1089         {
1090           clib_memset (&local, 0, sizeof (local));
1091           local.addr = l_addr;
1092           local.port = (u16) l_port;
1093           local.probability = (u8) probability;
1094           local.vrf_id = vrf_id;
1095           vec_add1 (locals, local);
1096         }
1097       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
1098                          &e_addr, &e_port))
1099         ;
1100       else if (unformat (line_input, "protocol %U", unformat_ip_protocol,
1101                          &proto))
1102         {
1103           proto_set = 1;
1104         }
1105       else if (unformat (line_input, "twice-nat"))
1106         {
1107           flags |= NAT_SM_FLAG_TWICE_NAT;
1108         }
1109       else if (unformat (line_input, "self-twice-nat"))
1110         {
1111           flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
1112         }
1113       else if (unformat (line_input, "out2in-only"))
1114         {
1115           flags |= NAT_SM_FLAG_OUT2IN_ONLY;
1116         }
1117       else if (unformat (line_input, "del"))
1118         {
1119           is_add = 0;
1120         }
1121       else if (unformat (line_input, "affinity %u", &affinity))
1122         ;
1123       else
1124         {
1125           error = clib_error_return (0, "unknown input: '%U'",
1126                                      format_unformat_error, line_input);
1127           goto done;
1128         }
1129     }
1130
1131   if (vec_len (locals) < 2)
1132     {
1133       error = clib_error_return (0, "at least two local must be set");
1134       goto done;
1135     }
1136
1137   if (!proto_set)
1138     {
1139       error = clib_error_return (0, "missing protocol");
1140       goto done;
1141     }
1142
1143   if (is_add)
1144     {
1145       rv = nat44_ed_add_lb_static_mapping (e_addr, (u16) e_port, proto, locals,
1146                                            flags, 0, affinity);
1147     }
1148   else
1149     {
1150       rv = nat44_ed_del_lb_static_mapping (e_addr, (u16) e_port, proto, flags);
1151     }
1152
1153   switch (rv)
1154     {
1155     case VNET_API_ERROR_INVALID_VALUE:
1156       error = clib_error_return (0, "External port already in use.");
1157       goto done;
1158     case VNET_API_ERROR_NO_SUCH_ENTRY:
1159       if (is_add)
1160         error = clib_error_return (0, "External address must be allocated.");
1161       else
1162         error = clib_error_return (0, "Mapping not exist.");
1163       goto done;
1164     case VNET_API_ERROR_VALUE_EXIST:
1165       error = clib_error_return (0, "Mapping already exist.");
1166       goto done;
1167     default:
1168       break;
1169     }
1170
1171 done:
1172   unformat_free (line_input);
1173   vec_free (locals);
1174
1175   return error;
1176 }
1177
1178 static clib_error_t *
1179 add_lb_backend_command_fn (vlib_main_t * vm,
1180                            unformat_input_t * input, vlib_cli_command_t * cmd)
1181 {
1182   unformat_input_t _line_input, *line_input = &_line_input;
1183   clib_error_t *error = 0;
1184   ip4_address_t l_addr, e_addr;
1185   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0;
1186   int is_add = 1;
1187   int rv;
1188   ip_protocol_t proto;
1189   u8 proto_set = 0;
1190
1191   /* Get a line of input. */
1192   if (!unformat_user (input, unformat_line_input, line_input))
1193     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
1194
1195   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1196     {
1197       if (unformat (line_input, "local %U:%u probability %u",
1198                     unformat_ip4_address, &l_addr, &l_port, &probability))
1199         ;
1200       else if (unformat (line_input, "local %U:%u vrf %u probability %u",
1201                          unformat_ip4_address, &l_addr, &l_port, &vrf_id,
1202                          &probability))
1203         ;
1204       else if (unformat (line_input, "external %U:%u", unformat_ip4_address,
1205                          &e_addr, &e_port))
1206         ;
1207       else if (unformat (line_input, "protocol %U", unformat_ip_protocol,
1208                          &proto))
1209         proto_set = 1;
1210       else if (unformat (line_input, "del"))
1211         is_add = 0;
1212       else
1213         {
1214           error = clib_error_return (0, "unknown input: '%U'",
1215                                      format_unformat_error, line_input);
1216           goto done;
1217         }
1218     }
1219
1220   if (!l_port || !e_port)
1221     {
1222       error = clib_error_return (0, "local or external must be set");
1223       goto done;
1224     }
1225
1226   if (!proto_set)
1227     {
1228       error = clib_error_return (0, "missing protocol");
1229       goto done;
1230     }
1231
1232   rv = nat44_ed_add_del_lb_static_mapping_local (
1233     e_addr, (u16) e_port, l_addr, l_port, proto, vrf_id, probability, is_add);
1234
1235   switch (rv)
1236     {
1237     case VNET_API_ERROR_INVALID_VALUE:
1238       error = clib_error_return (0, "External is not load-balancing static "
1239                                  "mapping.");
1240       goto done;
1241     case VNET_API_ERROR_NO_SUCH_ENTRY:
1242       error = clib_error_return (0, "Mapping or back-end not exist.");
1243       goto done;
1244     case VNET_API_ERROR_VALUE_EXIST:
1245       error = clib_error_return (0, "Back-end already exist.");
1246       goto done;
1247     case VNET_API_ERROR_UNSPECIFIED:
1248       error = clib_error_return (0, "At least two back-ends must remain");
1249       goto done;
1250     default:
1251       break;
1252     }
1253
1254 done:
1255   unformat_free (line_input);
1256
1257   return error;
1258 }
1259
1260 static clib_error_t *
1261 nat44_show_static_mappings_command_fn (vlib_main_t * vm,
1262                                        unformat_input_t * input,
1263                                        vlib_cli_command_t * cmd)
1264 {
1265   snat_main_t *sm = &snat_main;
1266   snat_static_mapping_t *m;
1267   snat_static_mapping_resolve_t *rp;
1268
1269   vlib_cli_output (vm, "NAT44 static mappings:");
1270   pool_foreach (m, sm->static_mappings)
1271    {
1272     vlib_cli_output (vm, " %U", format_snat_static_mapping, m);
1273   }
1274   vec_foreach (rp, sm->sm_to_resolve)
1275     vlib_cli_output (vm, " %U", format_snat_static_map_to_resolve, rp);
1276
1277   return 0;
1278 }
1279
1280 static clib_error_t *
1281 snat_add_interface_address_command_fn (vlib_main_t * vm,
1282                                        unformat_input_t * input,
1283                                        vlib_cli_command_t * cmd)
1284 {
1285   unformat_input_t _line_input, *line_input = &_line_input;
1286   snat_main_t *sm = &snat_main;
1287   clib_error_t *error = 0;
1288   int rv, is_del = 0;
1289   u8 twice_nat = 0;
1290   u32 sw_if_index;
1291
1292   if (!unformat_user (input, unformat_line_input, line_input))
1293     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
1294
1295   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1296     {
1297       if (unformat (line_input, "%U", unformat_vnet_sw_interface,
1298                     sm->vnet_main, &sw_if_index))
1299         ;
1300       else if (unformat (line_input, "twice-nat"))
1301         {
1302           twice_nat = 1;
1303         }
1304       else if (unformat (line_input, "del"))
1305         {
1306           is_del = 1;
1307         }
1308       else
1309         {
1310           error = clib_error_return (0, "unknown input '%U'",
1311                                      format_unformat_error, line_input);
1312           goto done;
1313         }
1314     }
1315
1316   if (!is_del)
1317     {
1318       rv = nat44_ed_add_interface_address (sw_if_index, twice_nat);
1319       if (rv)
1320         {
1321           error = clib_error_return (0, "add address returned %d", rv);
1322         }
1323     }
1324   else
1325     {
1326       rv = nat44_ed_del_interface_address (sw_if_index, twice_nat);
1327       if (rv)
1328         {
1329           error = clib_error_return (0, "del address returned %d", rv);
1330         }
1331     }
1332
1333 done:
1334   unformat_free (line_input);
1335
1336   return error;
1337 }
1338
1339 static clib_error_t *
1340 nat44_show_interface_address_command_fn (vlib_main_t * vm,
1341                                          unformat_input_t * input,
1342                                          vlib_cli_command_t * cmd)
1343 {
1344   snat_main_t *sm = &snat_main;
1345   vnet_main_t *vnm = vnet_get_main ();
1346   snat_address_resolve_t *ap;
1347
1348   vlib_cli_output (vm, "NAT44 pool address interfaces:");
1349   vec_foreach (ap, sm->addr_to_resolve)
1350     {
1351       vlib_cli_output (vm, " %U%s", format_vnet_sw_if_index_name, vnm,
1352                        ap->sw_if_index, ap->is_twice_nat ? " twice-nat" : "");
1353     }
1354   return 0;
1355 }
1356
1357 static clib_error_t *
1358 nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
1359                                 vlib_cli_command_t * cmd)
1360 {
1361   unformat_input_t _line_input, *line_input = &_line_input;
1362   clib_error_t *error = 0;
1363   snat_main_per_thread_data_t *tsm;
1364   snat_main_t *sm = &snat_main;
1365   ip4_address_t i2o_sa, i2o_da, o2i_sa, o2i_da;
1366   u8 filter_i2o_sa = 0, filter_i2o_da = 0;
1367   u8 filter_o2i_sa = 0, filter_o2i_da = 0;
1368   u16 i2o_sp, i2o_dp, o2i_sp, o2i_dp;
1369   u8 filter_i2o_sp = 0, filter_i2o_dp = 0;
1370   u8 filter_o2i_sp = 0, filter_o2i_dp = 0;
1371   ip_protocol_t proto;
1372   u8 filter_proto = 0;
1373   u8 had_input = 1, filtering = 0;
1374   int i = 0, showed_sessions;
1375
1376   if (!unformat_user (input, unformat_line_input, line_input))
1377     {
1378       had_input = 0;
1379       goto print;
1380     }
1381
1382   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1383     {
1384       if (unformat (line_input, "filter i2o saddr %U", unformat_ip4_address,
1385                     &i2o_sa))
1386         filter_i2o_sa = filtering = 1;
1387       else if (unformat (line_input, "filter i2o daddr %U",
1388                          unformat_ip4_address, &i2o_da))
1389         filter_i2o_da = filtering = 1;
1390       else if (unformat (line_input, "filter o2i saddr %U",
1391                          unformat_ip4_address, &o2i_sa))
1392         filter_o2i_sa = filtering = 1;
1393       else if (unformat (line_input, "filter o2i daddr %U",
1394                          unformat_ip4_address, &o2i_da))
1395         filter_o2i_da = filtering = 1;
1396       else if (unformat (line_input, "filter i2o sport %u", &i2o_sp))
1397         filter_i2o_sp = filtering = 1;
1398       else if (unformat (line_input, "filter i2o dport %u", &i2o_dp))
1399         filter_i2o_dp = filtering = 1;
1400       else if (unformat (line_input, "filter o2i sport %u", &o2i_sp))
1401         filter_o2i_sp = filtering = 1;
1402       else if (unformat (line_input, "filter o2i dport %u", &o2i_dp))
1403         filter_o2i_dp = filtering = 1;
1404       else if (unformat (line_input, "filter i2o proto %U",
1405                          unformat_ip_protocol, &proto))
1406         filter_proto = filtering = 1;
1407       else if (unformat (line_input, "filter o2i proto %U",
1408                          unformat_ip_protocol, &proto))
1409         filter_proto = filtering = 1;
1410       else
1411         {
1412           error = clib_error_return (0, "unknown input '%U'",
1413                                      format_unformat_error, line_input);
1414           goto done;
1415         }
1416     }
1417
1418 print:
1419   vlib_cli_output (vm, "NAT44 ED sessions:");
1420
1421   vec_foreach_index (i, sm->per_thread_data)
1422     {
1423       tsm = vec_elt_at_index (sm->per_thread_data, i);
1424
1425       vlib_cli_output (vm, "-------- thread %d %s: %d sessions --------\n",
1426                        i, vlib_worker_threads[i].name,
1427                        pool_elts (tsm->sessions));
1428
1429       showed_sessions = 0;
1430       snat_session_t *s;
1431       pool_foreach (s, tsm->sessions)
1432         {
1433           if (filtering)
1434             {
1435               if (filter_i2o_sa && i2o_sa.as_u32 != s->i2o.match.saddr.as_u32)
1436                 continue;
1437               if (filter_i2o_da && i2o_da.as_u32 != s->i2o.match.daddr.as_u32)
1438                 continue;
1439               if (filter_o2i_sa && o2i_sa.as_u32 != s->o2i.match.saddr.as_u32)
1440                 continue;
1441               if (filter_o2i_da && o2i_da.as_u32 != s->o2i.match.daddr.as_u32)
1442                 continue;
1443               if (filter_i2o_sp &&
1444                   i2o_sp != clib_net_to_host_u16 (s->i2o.match.sport))
1445                 continue;
1446               if (filter_i2o_dp &&
1447                   i2o_dp != clib_net_to_host_u16 (s->i2o.match.dport))
1448                 continue;
1449               if (filter_o2i_sp &&
1450                   o2i_sp != clib_net_to_host_u16 (s->o2i.match.sport))
1451                 continue;
1452               if (filter_o2i_dp &&
1453                   o2i_dp != clib_net_to_host_u16 (s->o2i.match.dport))
1454                 continue;
1455               if (filter_proto && proto != s->proto)
1456                 continue;
1457               showed_sessions++;
1458             }
1459           vlib_cli_output (vm, "  %U\n", format_snat_session, tsm, s);
1460         }
1461       if (filtering)
1462         {
1463           vlib_cli_output (vm,
1464                            "Showed: %d, Filtered: %d of total %d "
1465                            "sessions of thread %d\n\n",
1466                            showed_sessions,
1467                            pool_elts (tsm->sessions) - showed_sessions,
1468                            pool_elts (tsm->sessions), i);
1469         }
1470     }
1471
1472 done:
1473   if (had_input)
1474     unformat_free (line_input);
1475   return error;
1476 }
1477
1478 static clib_error_t *
1479 nat44_set_session_limit_command_fn (vlib_main_t * vm,
1480                                     unformat_input_t * input,
1481                                     vlib_cli_command_t * cmd)
1482 {
1483   unformat_input_t _line_input, *line_input = &_line_input;
1484   clib_error_t *error = 0;
1485
1486   u32 session_limit = 0, vrf_id = 0;
1487
1488   if (!unformat_user (input, unformat_line_input, line_input))
1489     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
1490
1491   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1492     {
1493       if (unformat (line_input, "%u", &session_limit))
1494         ;
1495       else if (unformat (line_input, "vrf %u", &vrf_id))
1496         ;
1497       else
1498         {
1499           error = clib_error_return (0, "unknown input '%U'",
1500                                      format_unformat_error, line_input);
1501           goto done;
1502         }
1503     }
1504
1505   if (!session_limit)
1506     error = clib_error_return (0, "missing value of session limit");
1507   else if (nat44_update_session_limit (session_limit, vrf_id))
1508     error = clib_error_return (0, "nat44_set_session_limit failed");
1509
1510 done:
1511   unformat_free (line_input);
1512
1513   return error;
1514 }
1515
1516 static clib_error_t *
1517 nat44_del_session_command_fn (vlib_main_t * vm,
1518                               unformat_input_t * input,
1519                               vlib_cli_command_t * cmd)
1520 {
1521   snat_main_t *sm = &snat_main;
1522   unformat_input_t _line_input, *line_input = &_line_input;
1523   u32 port = 0, eh_port = 0, vrf_id = sm->outside_vrf_id;
1524   clib_error_t *error = 0;
1525   ip4_address_t addr, eh_addr;
1526   ip_protocol_t proto;
1527   int is_in = 0;
1528   int rv;
1529
1530   if (!unformat_user (input, unformat_line_input, line_input))
1531     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
1532
1533   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1534     {
1535       if (unformat (line_input, "%U:%u %U", unformat_ip4_address, &addr, &port,
1536                     unformat_ip_protocol, &proto))
1537         ;
1538       else if (unformat (line_input, "in"))
1539         {
1540           is_in = 1;
1541           vrf_id = sm->inside_vrf_id;
1542         }
1543       else if (unformat (line_input, "out"))
1544         {
1545           is_in = 0;
1546           vrf_id = sm->outside_vrf_id;
1547         }
1548       else if (unformat (line_input, "vrf %u", &vrf_id))
1549         ;
1550       else if (unformat (line_input, "external-host %U:%u",
1551                          unformat_ip4_address, &eh_addr, &eh_port))
1552         ;
1553       else
1554         {
1555           error = clib_error_return (0, "unknown input '%U'",
1556                                      format_unformat_error, line_input);
1557           goto done;
1558         }
1559     }
1560
1561   rv = nat44_ed_del_session (sm, &addr, clib_host_to_net_u16 (port), &eh_addr,
1562                              clib_host_to_net_u16 (eh_port), proto, vrf_id,
1563                              is_in);
1564
1565   switch (rv)
1566     {
1567     case 0:
1568       break;
1569
1570     default:
1571       error = clib_error_return (0, "nat44_del_session returned %d", rv);
1572       goto done;
1573     }
1574
1575 done:
1576   unformat_free (line_input);
1577
1578   return error;
1579 }
1580
1581 static clib_error_t *
1582 snat_forwarding_set_command_fn (vlib_main_t * vm,
1583                                 unformat_input_t * input,
1584                                 vlib_cli_command_t * cmd)
1585 {
1586   snat_main_t *sm = &snat_main;
1587   unformat_input_t _line_input, *line_input = &_line_input;
1588   clib_error_t *error = 0;
1589
1590   u8 enable_set = 0, enable = 0;
1591
1592   if (!unformat_user (input, unformat_line_input, line_input))
1593     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
1594
1595   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1596     {
1597       if (!enable_set)
1598         {
1599           enable_set = 1;
1600           if (unformat (line_input, "disable"))
1601             ;
1602           else if (unformat (line_input, "enable"))
1603             enable = 1;
1604         }
1605       else
1606         {
1607           error = clib_error_return (0, "unknown input '%U'",
1608                                      format_unformat_error, line_input);
1609           goto done;
1610         }
1611     }
1612
1613   if (!enable_set)
1614     error = clib_error_return (0, "expected enable | disable");
1615   else
1616     sm->forwarding_enabled = enable;
1617
1618 done:
1619   unformat_free (line_input);
1620   return error;
1621 }
1622
1623 static clib_error_t *
1624 set_timeout_command_fn (vlib_main_t * vm,
1625                         unformat_input_t * input, vlib_cli_command_t * cmd)
1626 {
1627   snat_main_t *sm = &snat_main;
1628   unformat_input_t _line_input, *line_input = &_line_input;
1629   clib_error_t *error = 0;
1630
1631   if (!unformat_user (input, unformat_line_input, line_input))
1632     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
1633
1634   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1635     {
1636       if (unformat (line_input, "udp %u", &sm->timeouts.udp));
1637       else if (unformat (line_input, "tcp-established %u",
1638                          &sm->timeouts.tcp.established));
1639       else if (unformat (line_input, "tcp-transitory %u",
1640                          &sm->timeouts.tcp.transitory));
1641       else if (unformat (line_input, "icmp %u", &sm->timeouts.icmp));
1642       else if (unformat (line_input, "reset"))
1643         nat_reset_timeouts (&sm->timeouts);
1644       else
1645         {
1646           error = clib_error_return (0, "unknown input '%U'",
1647                                      format_unformat_error, line_input);
1648           goto done;
1649         }
1650     }
1651 done:
1652   unformat_free (line_input);
1653   return error;
1654 }
1655
1656 static clib_error_t *
1657 nat_show_timeouts_command_fn (vlib_main_t * vm,
1658                               unformat_input_t * input,
1659                               vlib_cli_command_t * cmd)
1660 {
1661   snat_main_t *sm = &snat_main;
1662
1663   vlib_cli_output (vm, "udp timeout: %dsec", sm->timeouts.udp);
1664   vlib_cli_output (vm, "tcp-established timeout: %dsec",
1665                    sm->timeouts.tcp.established);
1666   vlib_cli_output (vm, "tcp-transitory timeout: %dsec",
1667                    sm->timeouts.tcp.transitory);
1668   vlib_cli_output (vm, "icmp timeout: %dsec", sm->timeouts.icmp);
1669
1670   return 0;
1671 }
1672
1673 static clib_error_t *
1674 set_frame_queue_nelts_command_fn (vlib_main_t *vm, unformat_input_t *input,
1675                                   vlib_cli_command_t *cmd)
1676 {
1677   unformat_input_t _line_input, *line_input = &_line_input;
1678   clib_error_t *error = 0;
1679   u32 frame_queue_nelts = 0;
1680
1681   if (!unformat_user (input, unformat_line_input, line_input))
1682     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
1683
1684   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1685     {
1686       if (unformat (line_input, "%u", &frame_queue_nelts))
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   if (!frame_queue_nelts)
1696     {
1697       error = clib_error_return (0, "frame_queue_nelts cannot be zero");
1698       goto done;
1699     }
1700   if (nat44_ed_set_frame_queue_nelts (frame_queue_nelts) != 0)
1701     {
1702       error = clib_error_return (0, "snat_set_frame_queue_nelts failed");
1703       goto done;
1704     }
1705 done:
1706   unformat_free (line_input);
1707   return error;
1708 }
1709
1710 /*?
1711  * @cliexpar
1712  * @cliexstart{nat44}
1713  * Enable nat44 plugin
1714  * To enable nat44-ed, use:
1715  *  vpp# nat44 enable
1716  * To disable nat44-ed, use:
1717  *  vpp# nat44 disable
1718  * To set inside-vrf outside-vrf, use:
1719  *  vpp# nat44 enable inside-vrf <id> outside-vrf <id>
1720  * @cliexend
1721 ?*/
1722 VLIB_CLI_COMMAND (nat44_ed_enable_disable_command, static) = {
1723   .path = "nat44",
1724   .short_help = "nat44 <enable [sessions <max-number>] [inside-vrf <vrf-id>] "
1725                 "[outside-vrf <vrf-id>]>|disable",
1726   .function = nat44_ed_enable_disable_command_fn,
1727 };
1728
1729 /*?
1730  * @cliexpar
1731  * @cliexstart{set snat workers}
1732  * Set NAT workers if 2 or more workers available, use:
1733  *  vpp# set snat workers 0-2,5
1734  * @cliexend
1735 ?*/
1736 VLIB_CLI_COMMAND (set_workers_command, static) = {
1737   .path = "set nat workers",
1738   .function = set_workers_command_fn,
1739   .short_help = "set nat workers <workers-list>",
1740 };
1741
1742 /*?
1743  * @cliexpar
1744  * @cliexstart{show nat workers}
1745  * Show NAT workers.
1746  *  vpp# show nat workers:
1747  *  2 workers
1748  *    vpp_wk_0
1749  *    vpp_wk_1
1750  * @cliexend
1751 ?*/
1752 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
1753   .path = "show nat workers",
1754   .short_help = "show nat workers",
1755   .function = nat_show_workers_command_fn,
1756 };
1757
1758 /*?
1759  * @cliexpar
1760  * @cliexstart{set nat timeout}
1761  * Set values of timeouts for NAT sessions (in seconds), use:
1762  *  vpp# set nat timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90
1763  * To reset default values use:
1764  *  vpp# set nat timeout reset
1765  * @cliexend
1766 ?*/
1767 VLIB_CLI_COMMAND (set_timeout_command, static) = {
1768   .path = "set nat timeout",
1769   .function = set_timeout_command_fn,
1770   .short_help =
1771     "set nat timeout [udp <sec> | tcp-established <sec> "
1772     "tcp-transitory <sec> | icmp <sec> | reset]",
1773 };
1774
1775 /*?
1776  * @cliexpar
1777  * @cliexstart{show nat timeouts}
1778  * Show values of timeouts for NAT sessions.
1779  * vpp# show nat timeouts
1780  * udp timeout: 300sec
1781  * tcp-established timeout: 7440sec
1782  * tcp-transitory timeout: 240sec
1783  * icmp timeout: 60sec
1784  * @cliexend
1785 ?*/
1786 VLIB_CLI_COMMAND (nat_show_timeouts_command, static) = {
1787   .path = "show nat timeouts",
1788   .short_help = "show nat timeouts",
1789   .function = nat_show_timeouts_command_fn,
1790 };
1791
1792 /*?
1793  * @cliexpar
1794  * @cliexstart{set nat frame-queue-nelts}
1795  * Set number of worker handoff frame queue elements.
1796  * @cliexend
1797 ?*/
1798 VLIB_CLI_COMMAND (set_frame_queue_nelts_command, static) = {
1799   .path = "set nat frame-queue-nelts",
1800   .function = set_frame_queue_nelts_command_fn,
1801   .short_help = "set nat frame-queue-nelts <number>",
1802 };
1803
1804 /*?
1805  * @cliexpar
1806  * @cliexstart{nat set logging level}
1807  * To set NAT logging level use:
1808  * Set nat logging level
1809  * @cliexend
1810 ?*/
1811 VLIB_CLI_COMMAND (snat_set_log_level_command, static) = {
1812   .path = "nat set logging level",
1813   .function = snat_set_log_level_command_fn,
1814   .short_help = "nat set logging level <level>",
1815 };
1816
1817 /*?
1818  * @cliexpar
1819  * @cliexstart{snat ipfix logging}
1820  * To enable NAT IPFIX logging use:
1821  *  vpp# nat ipfix logging
1822  * To set IPFIX exporter use:
1823  *  vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
1824  * @cliexend
1825 ?*/
1826 VLIB_CLI_COMMAND (snat_ipfix_logging_enable_disable_command, static) = {
1827   .path = "nat ipfix logging",
1828   .function = snat_ipfix_logging_enable_disable_command_fn,
1829   .short_help = "nat ipfix logging disable|<enable [domain <domain-id>] "
1830                 "[src-port <port>]>",
1831 };
1832
1833 /*?
1834  * @cliexpar
1835  * @cliexstart{nat mss-clamping}
1836  * Set TCP MSS rewriting configuration
1837  * To enable TCP MSS rewriting use:
1838  *  vpp# nat mss-clamping 1452
1839  * To disbale TCP MSS rewriting use:
1840  *  vpp# nat mss-clamping disable
1841  * @cliexend
1842 ?*/
1843 VLIB_CLI_COMMAND (nat_set_mss_clamping_command, static) = {
1844     .path = "nat mss-clamping",
1845     .short_help = "nat mss-clamping <mss-value>|disable",
1846     .function = nat_set_mss_clamping_command_fn,
1847 };
1848
1849 /*?
1850  * @cliexpar
1851  * @cliexstart{show nat mss-clamping}
1852  * Show TCP MSS rewriting configuration
1853  * @cliexend
1854 ?*/
1855 VLIB_CLI_COMMAND (nat_show_mss_clamping_command, static) = {
1856     .path = "show nat mss-clamping",
1857     .short_help = "show nat mss-clamping",
1858     .function = nat_show_mss_clamping_command_fn,
1859 };
1860
1861 /*?
1862  * @cliexpar
1863  * @cliexstart{show nat44 hash tables}
1864  * Show NAT44 hash tables
1865  * @cliexend
1866 ?*/
1867 VLIB_CLI_COMMAND (nat44_show_hash, static) = {
1868   .path = "show nat44 hash tables",
1869   .short_help = "show nat44 hash tables [detail|verbose]",
1870   .function = nat44_show_hash_command_fn,
1871 };
1872
1873 /*?
1874  * @cliexpar
1875  * @cliexstart{nat44 add address}
1876  * Add/delete NAT44 pool address.
1877  * To add NAT44 pool address use:
1878  *  vpp# nat44 add address 172.16.1.3
1879  *  vpp# nat44 add address 172.16.2.2 - 172.16.2.24
1880  * To add NAT44 pool address for specific tenant (identified by VRF id) use:
1881  *  vpp# nat44 add address 172.16.1.3 tenant-vrf 10
1882  * @cliexend
1883 ?*/
1884 VLIB_CLI_COMMAND (add_address_command, static) = {
1885   .path = "nat44 add address",
1886   .short_help = "nat44 add address <ip4-range-start> [- <ip4-range-end>] "
1887                 "[tenant-vrf <vrf-id>] [twice-nat] [del]",
1888   .function = add_address_command_fn,
1889 };
1890
1891 /*?
1892  * @cliexpar
1893  * @cliexstart{show nat44 summary}
1894  * Show NAT44 summary
1895  * vpp# show nat44 summary
1896  * @cliexend
1897 ?*/
1898 VLIB_CLI_COMMAND (nat44_show_summary_command, static) = {
1899   .path = "show nat44 summary",
1900   .short_help = "show nat44 summary",
1901   .function = nat44_show_summary_command_fn,
1902 };
1903
1904 /*?
1905  * @cliexpar
1906  * @cliexstart{show nat44 addresses}
1907  * Show NAT44 pool addresses.
1908  * vpp# show nat44 addresses
1909  * NAT44 pool addresses:
1910  * 172.16.2.2
1911  *   tenant VRF independent
1912  *   10 busy udp ports
1913  *   0 busy tcp ports
1914  *   0 busy icmp ports
1915  * 172.16.1.3
1916  *   tenant VRF: 10
1917  *   0 busy udp ports
1918  *   2 busy tcp ports
1919  *   0 busy icmp ports
1920  * NAT44 twice-nat pool addresses:
1921  * 10.20.30.72
1922  *   tenant VRF independent
1923  *   0 busy udp ports
1924  *   0 busy tcp ports
1925  *   0 busy icmp ports
1926  * @cliexend
1927 ?*/
1928 VLIB_CLI_COMMAND (nat44_show_addresses_command, static) = {
1929   .path = "show nat44 addresses",
1930   .short_help = "show nat44 addresses",
1931   .function = nat44_show_addresses_command_fn,
1932 };
1933
1934 /*?
1935  * @cliexpar
1936  * @cliexstart{set interface nat44}
1937  * Enable/disable NAT44 feature on the interface.
1938  * To enable NAT44 feature with local network interface use:
1939  *  vpp# set interface nat44 in GigabitEthernet0/8/0
1940  * To enable NAT44 feature with external network interface use:
1941  *  vpp# set interface nat44 out GigabitEthernet0/a/0
1942  * @cliexend
1943 ?*/
1944 VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
1945   .path = "set interface nat44",
1946   .function = snat_feature_command_fn,
1947   .short_help = "set interface nat44 in <intfc> out <intfc> [output-feature] "
1948                 "[del]",
1949 };
1950
1951 /*?
1952  * @cliexpar
1953  * @cliexstart{show nat44 interfaces}
1954  * Show interfaces with NAT44 feature.
1955  * vpp# show nat44 interfaces
1956  * NAT44 interfaces:
1957  *  GigabitEthernet0/8/0 in
1958  *  GigabitEthernet0/a/0 out
1959  * @cliexend
1960 ?*/
1961 VLIB_CLI_COMMAND (nat44_show_interfaces_command, static) = {
1962   .path = "show nat44 interfaces",
1963   .short_help = "show nat44 interfaces",
1964   .function = nat44_show_interfaces_command_fn,
1965 };
1966
1967 /*?
1968  * @cliexpar
1969  * @cliexstart{nat44 add static mapping}
1970  * Static mapping allows hosts on the external network to initiate connection
1971  * to to the local network host.
1972  * To create static mapping between local host address 10.0.0.3 port 6303 and
1973  * external address 4.4.4.4 port 3606 for TCP protocol use:
1974  *  vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
1975  * If not runnig "static mapping only" NAT plugin mode use before:
1976  *  vpp# nat44 add address 4.4.4.4
1977  * To create address only static mapping between local and external address use:
1978  *  vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4
1979  * To create ICMP static mapping between local and external with ICMP echo
1980  * identifier 10 use:
1981  *  vpp# nat44 add static mapping icmp local 10.0.0.3 10 external 4.4.4.4 10
1982  * To force use of specific pool address, vrf independent
1983  *  vpp# nat44 add static mapping local 10.0.0.2 1234 external 10.0.2.2 1234 twice-nat exact 10.0.1.2
1984  * @cliexend
1985 ?*/
1986 VLIB_CLI_COMMAND (add_static_mapping_command, static) = {
1987   .path = "nat44 add static mapping",
1988   .function = add_static_mapping_command_fn,
1989   .short_help =
1990     "nat44 add static mapping tcp|udp|icmp local <addr> [<port|icmp-echo-id>] "
1991     "external <addr> [<port|icmp-echo-id>] [vrf <table-id>] [twice-nat|self-twice-nat] "
1992     "[out2in-only] [exact <pool-addr>] [del]",
1993 };
1994
1995 /*?
1996  * @cliexpar
1997  * @cliexstart{nat44 add identity mapping}
1998  * Identity mapping translate an IP address to itself.
1999  * To create identity mapping for address 10.0.0.3 port 6303 for TCP protocol
2000  * use:
2001  *  vpp# nat44 add identity mapping 10.0.0.3 tcp 6303
2002  * To create identity mapping for address 10.0.0.3 use:
2003  *  vpp# nat44 add identity mapping 10.0.0.3
2004  * To create identity mapping for DHCP addressed interface use:
2005  *  vpp# nat44 add identity mapping external GigabitEthernet0/a/0 tcp 3606
2006  * @cliexend
2007 ?*/
2008 VLIB_CLI_COMMAND (add_identity_mapping_command, static) = {
2009   .path = "nat44 add identity mapping",
2010   .function = add_identity_mapping_command_fn,
2011   .short_help = "nat44 add identity mapping <ip4-addr>|external <interface> "
2012     "[<protocol> <port>] [vrf <table-id>] [del]",
2013 };
2014
2015 /*?
2016  * @cliexpar
2017  * @cliexstart{nat44 add load-balancing static mapping}
2018  * Service load balancing using NAT44
2019  * To add static mapping with load balancing for service with external IP
2020  * address 1.2.3.4 and TCP port 80 and mapped to 2 local servers
2021  * 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:
2022  *  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
2023  * @cliexend
2024 ?*/
2025 VLIB_CLI_COMMAND (add_lb_static_mapping_command, static) = {
2026   .path = "nat44 add load-balancing static mapping",
2027   .function = add_lb_static_mapping_command_fn,
2028   .short_help =
2029     "nat44 add load-balancing static mapping protocol tcp|udp "
2030     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2031     "probability <n> [twice-nat|self-twice-nat] [out2in-only] "
2032     "[affinity <timeout-seconds>] [del]",
2033 };
2034
2035 /*?
2036  * @cliexpar
2037  * @cliexstart{nat44 add load-balancing static mapping}
2038  * Modify service load balancing using NAT44
2039  * To add new back-end server 10.100.10.30:8080 for service load balancing
2040  * static mapping with external IP address 1.2.3.4 and TCP port 80 use:
2041  *  vpp# nat44 add load-balancing back-end protocol tcp external 1.2.3.4:80 local 10.100.10.30:8080 probability 25
2042  * @cliexend
2043 ?*/
2044 VLIB_CLI_COMMAND (add_lb_backend_command, static) = {
2045   .path = "nat44 add load-balancing back-end",
2046   .function = add_lb_backend_command_fn,
2047   .short_help =
2048     "nat44 add load-balancing back-end protocol tcp|udp "
2049     "external <addr>:<port> local <addr>:<port> [vrf <table-id>] "
2050     "probability <n> [del]",
2051 };
2052
2053 /*?
2054  * @cliexpar
2055  * @cliexstart{show nat44 static mappings}
2056  * Show NAT44 static mappings.
2057  * vpp# show nat44 static mappings
2058  * NAT44 static mappings:
2059  *  local 10.0.0.3 external 4.4.4.4 vrf 0
2060  *  tcp local 192.168.0.4:6303 external 4.4.4.3:3606 vrf 0
2061  *  tcp vrf 0 external 1.2.3.4:80  out2in-only
2062  *   local 10.100.10.10:8080 probability 80
2063  *   local 10.100.10.20:8080 probability 20
2064  *  tcp local 10.100.3.8:8080 external 169.10.10.1:80 vrf 0 twice-nat
2065  *  tcp local 10.0.0.10:3603 external GigabitEthernet0/a/0:6306 vrf 10
2066  * @cliexend
2067 ?*/
2068 VLIB_CLI_COMMAND (nat44_show_static_mappings_command, static) = {
2069   .path = "show nat44 static mappings",
2070   .short_help = "show nat44 static mappings",
2071   .function = nat44_show_static_mappings_command_fn,
2072 };
2073
2074 /*?
2075  * @cliexpar
2076  * @cliexstart{nat44 add interface address}
2077  * Use NAT44 pool address from specific interfce
2078  * To add NAT44 pool address from specific interface use:
2079  *  vpp# nat44 add interface address GigabitEthernet0/8/0
2080  * @cliexend
2081 ?*/
2082 VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
2083     .path = "nat44 add interface address",
2084     .short_help = "nat44 add interface address <interface> [twice-nat] [del]",
2085     .function = snat_add_interface_address_command_fn,
2086 };
2087
2088 /*?
2089  * @cliexpar
2090  * @cliexstart{show nat44 interface address}
2091  * Show NAT44 pool address interfaces
2092  * vpp# show nat44 interface address
2093  * NAT44 pool address interfaces:
2094  *  GigabitEthernet0/a/0
2095  * NAT44 twice-nat pool address interfaces:
2096  *  GigabitEthernet0/8/0
2097  * @cliexend
2098 ?*/
2099 VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
2100   .path = "show nat44 interface address",
2101   .short_help = "show nat44 interface address",
2102   .function = nat44_show_interface_address_command_fn,
2103 };
2104
2105 /*?
2106  * @cliexpar
2107  * @cliexstart{show nat44 sessions}
2108  * Show NAT44 sessions.
2109  * @cliexend
2110 ?*/
2111 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
2112   .path = "show nat44 sessions",
2113   .short_help = "show nat44 sessions [filter {i2o | o2i} {saddr <ip4-addr> "
2114                 "| sport <n> | daddr <ip4-addr> | dport <n> | proto <proto>} "
2115                 "[filter .. [..]]]",
2116   .function = nat44_show_sessions_command_fn,
2117 };
2118
2119 /*?
2120  * @cliexpar
2121  * @cliexstart{set nat44 session limit}
2122  * Set NAT44 session limit.
2123  * @cliexend
2124 ?*/
2125 VLIB_CLI_COMMAND (nat44_set_session_limit_command, static) = {
2126   .path = "set nat44 session limit",
2127   .short_help = "set nat44 session limit <limit> [vrf <table-id>]",
2128   .function = nat44_set_session_limit_command_fn,
2129 };
2130
2131 /*?
2132  * @cliexpar
2133  * @cliexstart{nat44 del session}
2134  * To administratively delete NAT44 session by inside address and port use:
2135  *  vpp# nat44 del session in 10.0.0.3:6303 tcp
2136  * To administratively delete NAT44 session by outside address and port use:
2137  *  vpp# nat44 del session out 1.0.0.3:6033 udp
2138  * @cliexend
2139 ?*/
2140 VLIB_CLI_COMMAND (nat44_del_session_command, static) = {
2141     .path = "nat44 del session",
2142     .short_help = "nat44 del session in|out <addr>:<port> tcp|udp|icmp [vrf <id>] [external-host <addr>:<port>]",
2143     .function = nat44_del_session_command_fn,
2144 };
2145
2146 /*?
2147  * @cliexpar
2148  * @cliexstart{nat44 forwarding}
2149  * Enable or disable forwarding
2150  * Forward packets which don't match existing translation
2151  * or static mapping instead of dropping them.
2152  * To enable forwarding, use:
2153  *  vpp# nat44 forwarding enable
2154  * To disable forwarding, use:
2155  *  vpp# nat44 forwarding disable
2156  * @cliexend
2157 ?*/
2158 VLIB_CLI_COMMAND (snat_forwarding_set_command, static) = {
2159   .path = "nat44 forwarding",
2160   .short_help = "nat44 forwarding enable|disable",
2161   .function = snat_forwarding_set_command_fn,
2162 };
2163
2164 /*
2165  * fd.io coding-style-patch-verification: ON
2166  *
2167  * Local Variables:
2168  * eval: (c-set-style "gnu")
2169  * End:
2170  */