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