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