docs: Use newer Ubuntu LTS in tutorial
[vpp.git] / src / plugins / nat / nat44-ed / nat44_ed_api.c
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /**
17  * @file
18  * @brief NAT44 plugin API implementation
19  */
20
21 #include <vnet/ip/ip_types_api.h>
22 #include <vlibmemory/api.h>
23
24 #include <vnet/fib/fib_table.h>
25
26 #include <nat/lib/nat_inlines.h>
27 #include <nat/lib/ipfix_logging.h>
28
29 #include <nat/nat44-ed/nat44_ed.h>
30
31 #include <nat/nat44-ed/nat44_ed.api_enum.h>
32 #include <nat/nat44-ed/nat44_ed.api_types.h>
33
34 #include <nat/nat44-ed/nat44_ed_inlines.h>
35
36 #define REPLY_MSG_ID_BASE sm->msg_id_base
37 #include <vlibapi/api_helper_macros.h>
38
39 /* New API calls */
40
41 static void
42 vl_api_nat44_ed_plugin_enable_disable_t_handler (
43   vl_api_nat44_ed_plugin_enable_disable_t *mp)
44 {
45   snat_main_t *sm = &snat_main;
46   nat44_config_t c = { 0 };
47   vl_api_nat44_ed_plugin_enable_disable_reply_t *rmp;
48   int rv = 0;
49
50   if (mp->enable)
51     {
52       if ((mp->flags & NAT44_API_IS_STATIC_MAPPING_ONLY) ||
53           (mp->flags & NAT44_API_IS_CONNECTION_TRACKING))
54         {
55           rv = VNET_API_ERROR_UNSUPPORTED;
56         }
57       else
58         {
59           c.sessions = ntohl (mp->sessions);
60           c.inside_vrf = ntohl (mp->inside_vrf);
61           c.outside_vrf = ntohl (mp->outside_vrf);
62
63           rv = nat44_plugin_enable (c);
64         }
65     }
66   else
67     {
68       rv = nat44_plugin_disable ();
69     }
70
71   REPLY_MACRO (VL_API_NAT44_ED_PLUGIN_ENABLE_DISABLE_REPLY);
72 }
73
74 static void
75 vl_api_nat44_ed_set_fq_options_t_handler (vl_api_nat44_ed_set_fq_options_t *mp)
76 {
77   snat_main_t *sm = &snat_main;
78   vl_api_nat44_ed_set_fq_options_reply_t *rmp;
79   int rv = 0;
80   u32 frame_queue_nelts = ntohl (mp->frame_queue_nelts);
81   rv = nat44_ed_set_frame_queue_nelts (frame_queue_nelts);
82   REPLY_MACRO (VL_API_NAT44_ED_SET_FQ_OPTIONS_REPLY);
83 }
84
85 static void
86 vl_api_nat44_ed_show_fq_options_t_handler (
87   vl_api_nat44_ed_show_fq_options_t *mp)
88 {
89   snat_main_t *sm = &snat_main;
90   vl_api_nat44_ed_show_fq_options_reply_t *rmp;
91   int rv = 0;
92   /* clang-format off */
93   REPLY_MACRO2_ZERO (VL_API_NAT44_ED_SHOW_FQ_OPTIONS_REPLY,
94   ({
95     rmp->frame_queue_nelts = htonl (sm->frame_queue_nelts);
96   }));
97   /* clang-format on */
98 }
99
100 /* Old API calls hold back because of deprecation
101  * nat44_ed replacement should be used */
102
103 static void
104 vl_api_nat_set_workers_t_handler (vl_api_nat_set_workers_t * mp)
105 {
106   snat_main_t *sm = &snat_main;
107   vl_api_nat_set_workers_reply_t *rmp;
108   int rv = 0;
109   uword *bitmap = 0;
110   u64 mask;
111
112   mask = clib_net_to_host_u64 (mp->worker_mask);
113
114   if (sm->num_workers < 2)
115     {
116       rv = VNET_API_ERROR_FEATURE_DISABLED;
117       goto send_reply;
118     }
119
120   bitmap = clib_bitmap_set_multiple (bitmap, 0, mask, BITS (mask));
121   rv = snat_set_workers (bitmap);
122   clib_bitmap_free (bitmap);
123
124 send_reply:
125   REPLY_MACRO (VL_API_NAT_SET_WORKERS_REPLY);
126 }
127
128 static void
129 send_nat_worker_details (u32 worker_index, vl_api_registration_t * reg,
130                          u32 context)
131 {
132   vl_api_nat_worker_details_t *rmp;
133   snat_main_t *sm = &snat_main;
134   vlib_worker_thread_t *w =
135     vlib_worker_threads + worker_index + sm->first_worker_index;
136
137   rmp = vl_msg_api_alloc (sizeof (*rmp));
138   clib_memset (rmp, 0, sizeof (*rmp));
139   rmp->_vl_msg_id = ntohs (VL_API_NAT_WORKER_DETAILS + sm->msg_id_base);
140   rmp->context = context;
141   rmp->worker_index = htonl (worker_index);
142   rmp->lcore_id = htonl (w->cpu_id);
143   strncpy ((char *) rmp->name, (char *) w->name, ARRAY_LEN (rmp->name) - 1);
144
145   vl_api_send_msg (reg, (u8 *) rmp);
146 }
147
148 static void
149 vl_api_nat_worker_dump_t_handler (vl_api_nat_worker_dump_t * mp)
150 {
151   vl_api_registration_t *reg;
152   snat_main_t *sm = &snat_main;
153   u32 *worker_index;
154
155   reg = vl_api_client_index_to_registration (mp->client_index);
156   if (!reg)
157     return;
158
159   vec_foreach (worker_index, sm->workers)
160     {
161       send_nat_worker_details (*worker_index, reg, mp->context);
162     }
163 }
164
165 static void
166 vl_api_nat44_set_session_limit_t_handler (vl_api_nat44_set_session_limit_t *
167                                           mp)
168 {
169   snat_main_t *sm = &snat_main;
170   vl_api_nat44_set_session_limit_reply_t *rmp;
171   int rv = 0;
172
173   rv = nat44_set_session_limit
174     (ntohl (mp->session_limit), ntohl (mp->vrf_id));
175
176   REPLY_MACRO (VL_API_NAT44_SET_SESSION_LIMIT_REPLY);
177 }
178
179 static void
180 vl_api_nat_ipfix_enable_disable_t_handler (vl_api_nat_ipfix_enable_disable_t *
181                                            mp)
182 {
183   snat_main_t *sm = &snat_main;
184   vl_api_nat_ipfix_enable_disable_reply_t *rmp;
185   int rv = 0;
186
187   rv = nat_ipfix_logging_enable_disable (mp->enable,
188                                          clib_host_to_net_u32
189                                          (mp->domain_id),
190                                          clib_host_to_net_u16 (mp->src_port));
191
192   REPLY_MACRO (VL_API_NAT_IPFIX_ENABLE_DISABLE_REPLY);
193 }
194
195 static void
196 vl_api_nat_set_timeouts_t_handler (vl_api_nat_set_timeouts_t * mp)
197 {
198   snat_main_t *sm = &snat_main;
199   vl_api_nat_set_timeouts_reply_t *rmp;
200   int rv = 0;
201
202   sm->timeouts.udp = ntohl (mp->udp);
203   sm->timeouts.tcp.established = ntohl (mp->tcp_established);
204   sm->timeouts.tcp.transitory = ntohl (mp->tcp_transitory);
205   sm->timeouts.icmp = ntohl (mp->icmp);
206
207   REPLY_MACRO (VL_API_NAT_SET_TIMEOUTS_REPLY);
208 }
209
210 static void
211 vl_api_nat_set_mss_clamping_t_handler (vl_api_nat_set_mss_clamping_t * mp)
212 {
213   snat_main_t *sm = &snat_main;
214   vl_api_nat_set_mss_clamping_reply_t *rmp;
215   int rv = 0;
216
217   if (mp->enable)
218     sm->mss_clamping = ntohs (mp->mss_value);
219   else
220     sm->mss_clamping = 0;
221
222   REPLY_MACRO (VL_API_NAT_SET_MSS_CLAMPING_REPLY);
223 }
224
225 static void
226 vl_api_nat_get_mss_clamping_t_handler (vl_api_nat_get_mss_clamping_t * mp)
227 {
228   snat_main_t *sm = &snat_main;
229   vl_api_nat_get_mss_clamping_reply_t *rmp;
230   int rv = 0;
231
232   REPLY_MACRO2 (VL_API_NAT_GET_MSS_CLAMPING_REPLY,
233   ({
234     rmp->enable = sm->mss_clamping ? 1 : 0;
235     rmp->mss_value = htons (sm->mss_clamping);
236   }))
237 }
238
239 static void
240   vl_api_nat44_add_del_address_range_t_handler
241   (vl_api_nat44_add_del_address_range_t * mp)
242 {
243   snat_main_t *sm = &snat_main;
244   vl_api_nat44_add_del_address_range_reply_t *rmp;
245   ip4_address_t this_addr;
246   u8 is_add, twice_nat;
247   u32 start_host_order, end_host_order;
248   u32 vrf_id;
249   int i, count;
250   int rv = 0;
251   u32 *tmp;
252
253   is_add = mp->is_add;
254   twice_nat = mp->flags & NAT_API_IS_TWICE_NAT;
255
256   tmp = (u32 *) mp->first_ip_address;
257   start_host_order = clib_host_to_net_u32 (tmp[0]);
258   tmp = (u32 *) mp->last_ip_address;
259   end_host_order = clib_host_to_net_u32 (tmp[0]);
260
261   count = (end_host_order - start_host_order) + 1;
262
263   vrf_id = clib_host_to_net_u32 (mp->vrf_id);
264
265   if (count > 1024)
266     nat_log_info ("%U - %U, %d addresses...",
267                   format_ip4_address, mp->first_ip_address,
268                   format_ip4_address, mp->last_ip_address, count);
269
270   memcpy (&this_addr.as_u8, mp->first_ip_address, 4);
271
272   for (i = 0; i < count; i++)
273     {
274       if (is_add)
275         {
276           rv = nat44_ed_add_address (&this_addr, vrf_id, twice_nat);
277         }
278       else
279         {
280           rv = nat44_ed_del_address (this_addr, twice_nat);
281         }
282
283       if (rv)
284         goto send_reply;
285
286       increment_v4_address (&this_addr);
287     }
288
289 send_reply:
290   REPLY_MACRO (VL_API_NAT44_ADD_DEL_ADDRESS_RANGE_REPLY);
291 }
292
293 static void
294 send_nat44_address_details (snat_address_t * a,
295                             vl_api_registration_t * reg, u32 context,
296                             u8 twice_nat)
297 {
298   vl_api_nat44_address_details_t *rmp;
299   snat_main_t *sm = &snat_main;
300
301   rmp = vl_msg_api_alloc (sizeof (*rmp));
302   clib_memset (rmp, 0, sizeof (*rmp));
303   rmp->_vl_msg_id = ntohs (VL_API_NAT44_ADDRESS_DETAILS + sm->msg_id_base);
304   clib_memcpy (rmp->ip_address, &(a->addr), 4);
305   if (a->fib_index != ~0)
306     {
307       fib_table_t *fib = fib_table_get (a->fib_index, FIB_PROTOCOL_IP4);
308       rmp->vrf_id = ntohl (fib->ft_table_id);
309     }
310   else
311     rmp->vrf_id = ~0;
312   if (twice_nat)
313     rmp->flags |= NAT_API_IS_TWICE_NAT;
314   rmp->context = context;
315
316   vl_api_send_msg (reg, (u8 *) rmp);
317 }
318
319 static void
320 vl_api_nat44_address_dump_t_handler (vl_api_nat44_address_dump_t * mp)
321 {
322   vl_api_registration_t *reg;
323   snat_main_t *sm = &snat_main;
324   snat_address_t *a;
325
326   reg = vl_api_client_index_to_registration (mp->client_index);
327   if (!reg)
328     return;
329
330   vec_foreach (a, sm->addresses)
331     send_nat44_address_details (a, reg, mp->context, 0);
332   vec_foreach (a, sm->twice_nat_addresses)
333     send_nat44_address_details (a, reg, mp->context, 1);
334 }
335
336 static void
337   vl_api_nat44_interface_add_del_feature_t_handler
338   (vl_api_nat44_interface_add_del_feature_t * mp)
339 {
340   vl_api_nat44_interface_add_del_feature_reply_t *rmp;
341   snat_main_t *sm = &snat_main;
342   u32 sw_if_index;
343   u8 is_inside;
344   int rv = 0;
345
346   VALIDATE_SW_IF_INDEX (mp);
347
348   is_inside = mp->flags & NAT_API_IS_INSIDE;
349   sw_if_index = ntohl (mp->sw_if_index);
350
351   if (mp->is_add)
352     {
353       rv = nat44_ed_add_interface (sw_if_index, is_inside);
354     }
355   else
356     {
357       rv = nat44_ed_del_interface (sw_if_index, is_inside);
358     }
359
360   BAD_SW_IF_INDEX_LABEL;
361   REPLY_MACRO (VL_API_NAT44_INTERFACE_ADD_DEL_FEATURE_REPLY);
362 }
363
364 static void
365 send_nat44_interface_details (snat_interface_t * i,
366                               vl_api_registration_t * reg, u32 context)
367 {
368   vl_api_nat44_interface_details_t *rmp;
369   snat_main_t *sm = &snat_main;
370
371   rmp = vl_msg_api_alloc (sizeof (*rmp));
372   clib_memset (rmp, 0, sizeof (*rmp));
373   rmp->_vl_msg_id = ntohs (VL_API_NAT44_INTERFACE_DETAILS + sm->msg_id_base);
374   rmp->sw_if_index = ntohl (i->sw_if_index);
375
376   if (nat44_ed_is_interface_inside (i))
377     rmp->flags |= NAT_API_IS_INSIDE;
378   if (nat44_ed_is_interface_outside (i))
379     rmp->flags |= NAT_API_IS_OUTSIDE;
380
381   rmp->context = context;
382
383   vl_api_send_msg (reg, (u8 *) rmp);
384 }
385
386 static void
387 vl_api_nat44_interface_dump_t_handler (vl_api_nat44_interface_dump_t * mp)
388 {
389   vl_api_registration_t *reg;
390   snat_main_t *sm = &snat_main;
391   snat_interface_t *i;
392
393   reg = vl_api_client_index_to_registration (mp->client_index);
394   if (!reg)
395     return;
396
397   pool_foreach (i, sm->interfaces)
398     {
399       send_nat44_interface_details (i, reg, mp->context);
400     }
401 }
402
403 static void
404 vl_api_nat44_ed_add_del_output_interface_t_handler (
405   vl_api_nat44_ed_add_del_output_interface_t *mp)
406 {
407   vl_api_nat44_ed_add_del_output_interface_reply_t *rmp;
408   snat_main_t *sm = &snat_main;
409   int rv = 0;
410
411   VALIDATE_SW_IF_INDEX_END (mp);
412
413   if (mp->is_add)
414     {
415       rv = nat44_ed_add_output_interface (mp->sw_if_index);
416     }
417   else
418     {
419       rv = nat44_ed_del_output_interface (mp->sw_if_index);
420     }
421
422 bad_sw_if_index:
423   REPLY_MACRO_END (VL_API_NAT44_ED_ADD_DEL_OUTPUT_INTERFACE_REPLY);
424 }
425
426 #define vl_endianfun
427 #include <nat/nat44-ed/nat44_ed.api.h>
428 #undef vl_endianfun
429 static void
430 send_nat44_ed_output_interface_details (u32 index, vl_api_registration_t *rp,
431                                         u32 context)
432 {
433   snat_main_t *sm = &snat_main;
434   vl_api_nat44_ed_output_interface_details_t *rmp;
435   snat_interface_t *i =
436     pool_elt_at_index (sm->output_feature_interfaces, index);
437
438   /* Make sure every field is initiated (or don't skip the clib_memset()) */
439   REPLY_MACRO_DETAILS4 (
440     VL_API_NAT44_ED_OUTPUT_INTERFACE_DETAILS, rp, context, ({
441       rmp->sw_if_index = i->sw_if_index;
442
443       /* Endian hack until apigen registers _details
444        * endian functions */
445       vl_api_nat44_ed_output_interface_details_t_endian (rmp,
446                                                          1 /* to network */);
447       rmp->_vl_msg_id = htons (rmp->_vl_msg_id);
448       rmp->context = htonl (rmp->context);
449     }));
450 }
451
452 static void
453 vl_api_nat44_ed_output_interface_get_t_handler (
454   vl_api_nat44_ed_output_interface_get_t *mp)
455 {
456   vl_api_nat44_ed_output_interface_get_reply_t *rmp;
457   snat_main_t *sm = &snat_main;
458   i32 rv = 0;
459
460   if (pool_elts (sm->output_feature_interfaces) == 0)
461     {
462       REPLY_MACRO (VL_API_NAT44_ED_OUTPUT_INTERFACE_GET_REPLY);
463       return;
464     }
465
466   REPLY_AND_DETAILS_MACRO (
467     VL_API_NAT44_ED_OUTPUT_INTERFACE_GET_REPLY, sm->output_feature_interfaces,
468     ({ send_nat44_ed_output_interface_details (cursor, rp, mp->context); }));
469 }
470
471 static void
472   vl_api_nat44_add_del_static_mapping_t_handler
473   (vl_api_nat44_add_del_static_mapping_t * mp)
474 {
475   vl_api_nat44_add_del_static_mapping_reply_t *rmp;
476
477   snat_main_t *sm = &snat_main;
478   int rv = 0;
479
480   ip4_address_t l_addr, e_addr, pool_addr = { 0 };
481   u32 sw_if_index, flags = 0, vrf_id;
482   u16 l_port = 0, e_port = 0;
483   ip_protocol_t proto = 0;
484   u8 *tag = 0;
485
486   memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
487
488   if (mp->flags & NAT_API_IS_ADDR_ONLY)
489     {
490       flags |= NAT_SM_FLAG_ADDR_ONLY;
491     }
492   else
493     {
494       l_port = mp->local_port;
495       e_port = mp->external_port;
496       proto = mp->protocol;
497     }
498
499   if (mp->flags & NAT_API_IS_TWICE_NAT)
500     {
501       flags |= NAT_SM_FLAG_TWICE_NAT;
502     }
503
504   if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
505     {
506       flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
507     }
508
509   if (mp->flags & NAT_API_IS_OUT2IN_ONLY)
510     {
511       flags |= NAT_SM_FLAG_OUT2IN_ONLY;
512     }
513
514   sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
515   if (sw_if_index != ~0)
516     {
517       flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
518     }
519   else
520     {
521       memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
522     }
523
524   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
525
526   if (mp->is_add)
527     {
528       mp->tag[sizeof (mp->tag) - 1] = 0;
529       tag = format (0, "%s", mp->tag);
530       vec_terminate_c_string (tag);
531
532       rv = nat44_ed_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
533                                         vrf_id, sw_if_index, flags, pool_addr,
534                                         tag);
535       vec_free (tag);
536     }
537   else
538     {
539       rv = nat44_ed_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
540                                         vrf_id, sw_if_index, flags);
541     }
542   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_REPLY);
543 }
544
545 static void
546   vl_api_nat44_add_del_static_mapping_v2_t_handler
547   (vl_api_nat44_add_del_static_mapping_v2_t * mp)
548 {
549   vl_api_nat44_add_del_static_mapping_v2_reply_t *rmp;
550
551   snat_main_t *sm = &snat_main;
552   int rv = 0;
553
554   ip4_address_t l_addr, e_addr, pool_addr;
555   u32 sw_if_index, flags = 0, vrf_id;
556   u16 l_port = 0, e_port = 0;
557   ip_protocol_t proto;
558   u8 *tag = 0;
559
560   memcpy (&l_addr.as_u8, mp->local_ip_address, 4);
561   memcpy (&pool_addr.as_u8, mp->pool_ip_address, 4);
562
563   if (pool_addr.as_u32 != 0)
564     {
565       flags |= NAT_SM_FLAG_EXACT_ADDRESS;
566     }
567
568   if (mp->flags & NAT_API_IS_ADDR_ONLY)
569     {
570       flags |= NAT_SM_FLAG_ADDR_ONLY;
571     }
572   else
573     {
574       l_port = mp->local_port;
575       e_port = mp->external_port;
576     }
577
578   if (mp->flags & NAT_API_IS_TWICE_NAT)
579     {
580       flags |= NAT_SM_FLAG_TWICE_NAT;
581     }
582
583   if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
584     {
585       flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
586     }
587
588   if (mp->flags & NAT_API_IS_OUT2IN_ONLY)
589     {
590       flags |= NAT_SM_FLAG_OUT2IN_ONLY;
591     }
592
593   sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
594   if (sw_if_index != ~0)
595     {
596       flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
597     }
598   else
599     {
600       memcpy (&e_addr.as_u8, mp->external_ip_address, 4);
601     }
602
603   proto = mp->protocol;
604   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
605
606   if (mp->is_add)
607     {
608       mp->tag[sizeof (mp->tag) - 1] = 0;
609       tag = format (0, "%s", mp->tag);
610       vec_terminate_c_string (tag);
611
612       rv = nat44_ed_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
613                                         vrf_id, sw_if_index, flags, pool_addr,
614                                         tag);
615       vec_free (tag);
616     }
617   else
618     {
619       rv = nat44_ed_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
620                                         vrf_id, sw_if_index, flags);
621     }
622   REPLY_MACRO (VL_API_NAT44_ADD_DEL_STATIC_MAPPING_V2_REPLY);
623 }
624
625 static void
626 send_nat44_static_mapping_details (snat_static_mapping_t * m,
627                                    vl_api_registration_t * reg, u32 context)
628 {
629   vl_api_nat44_static_mapping_details_t *rmp;
630   snat_main_t *sm = &snat_main;
631   u32 len = sizeof (*rmp);
632
633   rmp = vl_msg_api_alloc (len);
634   clib_memset (rmp, 0, len);
635   rmp->_vl_msg_id =
636     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
637
638   clib_memcpy (rmp->local_ip_address, &(m->local_addr), 4);
639   clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
640   rmp->external_sw_if_index = ~0;
641   rmp->vrf_id = htonl (m->vrf_id);
642   rmp->context = context;
643
644   // convert these in new api
645
646   if (is_sm_self_twice_nat (m->flags))
647     {
648       rmp->flags |= NAT_API_IS_SELF_TWICE_NAT;
649     }
650
651   if (is_sm_out2in_only (m->flags))
652     {
653       rmp->flags |= NAT_API_IS_OUT2IN_ONLY;
654     }
655
656   if (is_sm_twice_nat (m->flags))
657     {
658       rmp->flags |= NAT_API_IS_TWICE_NAT;
659     }
660
661   if (is_sm_addr_only (m->flags))
662     {
663       rmp->flags |= NAT_API_IS_ADDR_ONLY;
664     }
665   else
666     {
667       rmp->protocol = m->proto;
668       rmp->external_port = m->external_port;
669       rmp->local_port = m->local_port;
670     }
671
672   if (m->tag)
673     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
674
675   vl_api_send_msg (reg, (u8 *) rmp);
676 }
677
678 static void
679 send_nat44_static_map_resolve_details (snat_static_mapping_resolve_t *m,
680                                        vl_api_registration_t *reg, u32 context)
681 {
682   vl_api_nat44_static_mapping_details_t *rmp;
683   snat_main_t *sm = &snat_main;
684
685   rmp = vl_msg_api_alloc (sizeof (*rmp));
686   clib_memset (rmp, 0, sizeof (*rmp));
687   rmp->_vl_msg_id =
688     ntohs (VL_API_NAT44_STATIC_MAPPING_DETAILS + sm->msg_id_base);
689   clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
690   rmp->external_sw_if_index = htonl (m->sw_if_index);
691   rmp->vrf_id = htonl (m->vrf_id);
692   rmp->context = context;
693
694   if (is_sm_twice_nat (m->flags))
695     {
696       rmp->flags |= NAT_API_IS_TWICE_NAT;
697     }
698
699   if (is_sm_addr_only (m->flags))
700     {
701       rmp->flags |= NAT_API_IS_ADDR_ONLY;
702     }
703   else
704     {
705       rmp->protocol = m->proto;
706       rmp->external_port = m->e_port;
707       rmp->local_port = m->l_port;
708     }
709
710   if (m->tag)
711     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
712
713   vl_api_send_msg (reg, (u8 *) rmp);
714 }
715
716 static void
717 vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t
718                                             * mp)
719 {
720   vl_api_registration_t *reg;
721   snat_main_t *sm = &snat_main;
722   snat_static_mapping_t *m;
723   snat_static_mapping_resolve_t *rp;
724   int j;
725
726   reg = vl_api_client_index_to_registration (mp->client_index);
727   if (!reg)
728     return;
729
730   pool_foreach (m, sm->static_mappings)
731    {
732      if (!is_sm_identity_nat (m->flags) && !is_sm_lb (m->flags))
733        send_nat44_static_mapping_details (m, reg, mp->context);
734   }
735
736   for (j = 0; j < vec_len (sm->sm_to_resolve); j++)
737     {
738       rp = sm->sm_to_resolve + j;
739       if (!is_sm_identity_nat (rp->flags))
740         send_nat44_static_map_resolve_details (rp, reg, mp->context);
741     }
742 }
743
744 static void
745   vl_api_nat44_add_del_identity_mapping_t_handler
746   (vl_api_nat44_add_del_identity_mapping_t * mp)
747 {
748   vl_api_nat44_add_del_identity_mapping_reply_t *rmp;
749
750   snat_main_t *sm = &snat_main;
751   int rv = 0;
752
753   ip4_address_t addr, pool_addr = { 0 };
754   u32 sw_if_index, flags, vrf_id;
755   ip_protocol_t proto = 0;
756   u16 port = 0;
757   u8 *tag = 0;
758
759   flags = NAT_SM_FLAG_IDENTITY_NAT;
760
761   if (mp->flags & NAT_API_IS_ADDR_ONLY)
762     {
763       flags |= NAT_SM_FLAG_ADDR_ONLY;
764     }
765   else
766     {
767       port = mp->port;
768       proto = mp->protocol;
769     }
770
771   sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
772   if (sw_if_index != ~0)
773     {
774       flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
775     }
776   else
777     {
778       memcpy (&addr.as_u8, mp->ip_address, 4);
779     }
780
781   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
782
783   if (mp->is_add)
784     {
785       mp->tag[sizeof (mp->tag) - 1] = 0;
786       tag = format (0, "%s", mp->tag);
787       vec_terminate_c_string (tag);
788
789       rv = nat44_ed_add_static_mapping (addr, addr, port, port, proto, vrf_id,
790                                         sw_if_index, flags, pool_addr, tag);
791       vec_free (tag);
792     }
793   else
794     {
795       rv = nat44_ed_del_static_mapping (addr, addr, port, port, proto, vrf_id,
796                                         sw_if_index, flags);
797     }
798   REPLY_MACRO (VL_API_NAT44_ADD_DEL_IDENTITY_MAPPING_REPLY);
799 }
800
801 static void
802 send_nat44_identity_mapping_details (snat_static_mapping_t * m, int index,
803                                      vl_api_registration_t * reg, u32 context)
804 {
805   vl_api_nat44_identity_mapping_details_t *rmp;
806   snat_main_t *sm = &snat_main;
807   nat44_lb_addr_port_t *local = pool_elt_at_index (m->locals, index);
808
809   rmp = vl_msg_api_alloc (sizeof (*rmp));
810   clib_memset (rmp, 0, sizeof (*rmp));
811   rmp->_vl_msg_id =
812     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
813
814   if (is_sm_addr_only (m->flags))
815     rmp->flags |= NAT_API_IS_ADDR_ONLY;
816
817   clib_memcpy (rmp->ip_address, &(m->local_addr), 4);
818   rmp->port = m->local_port;
819   rmp->sw_if_index = ~0;
820   rmp->vrf_id = htonl (local->vrf_id);
821   rmp->protocol = m->proto;
822   rmp->context = context;
823   if (m->tag)
824     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
825
826   vl_api_send_msg (reg, (u8 *) rmp);
827 }
828
829 static void
830 send_nat44_identity_map_resolve_details (snat_static_mapping_resolve_t *m,
831                                          vl_api_registration_t *reg,
832                                          u32 context)
833 {
834   vl_api_nat44_identity_mapping_details_t *rmp;
835   snat_main_t *sm = &snat_main;
836
837   rmp = vl_msg_api_alloc (sizeof (*rmp));
838   clib_memset (rmp, 0, sizeof (*rmp));
839   rmp->_vl_msg_id =
840     ntohs (VL_API_NAT44_IDENTITY_MAPPING_DETAILS + sm->msg_id_base);
841
842   if (is_sm_addr_only (m->flags))
843     rmp->flags = (vl_api_nat_config_flags_t) NAT_API_IS_ADDR_ONLY;
844
845   rmp->port = m->l_port;
846   rmp->sw_if_index = htonl (m->sw_if_index);
847   rmp->vrf_id = htonl (m->vrf_id);
848   rmp->protocol = m->proto;
849   rmp->context = context;
850   if (m->tag)
851     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
852
853   vl_api_send_msg (reg, (u8 *) rmp);
854 }
855
856 static void
857   vl_api_nat44_identity_mapping_dump_t_handler
858   (vl_api_nat44_identity_mapping_dump_t * mp)
859 {
860   vl_api_registration_t *reg;
861   snat_main_t *sm = &snat_main;
862   snat_static_mapping_t *m;
863   snat_static_mapping_resolve_t *rp;
864   int j;
865
866   reg = vl_api_client_index_to_registration (mp->client_index);
867   if (!reg)
868     return;
869
870   pool_foreach (m, sm->static_mappings)
871     {
872       if (is_sm_identity_nat (m->flags) && !is_sm_lb (m->flags))
873         {
874           pool_foreach_index (j, m->locals)
875             {
876               send_nat44_identity_mapping_details (m, j, reg, mp->context);
877             }
878         }
879     }
880
881   for (j = 0; j < vec_len (sm->sm_to_resolve); j++)
882     {
883       rp = sm->sm_to_resolve + j;
884       if (is_sm_identity_nat (rp->flags))
885         send_nat44_identity_map_resolve_details (rp, reg, mp->context);
886     }
887 }
888
889 static void
890   vl_api_nat44_add_del_interface_addr_t_handler
891   (vl_api_nat44_add_del_interface_addr_t * mp)
892 {
893   snat_main_t *sm = &snat_main;
894   vl_api_nat44_add_del_interface_addr_reply_t *rmp;
895   u32 sw_if_index = ntohl (mp->sw_if_index);
896   u8 twice_nat;
897   int rv = 0;
898
899   VALIDATE_SW_IF_INDEX (mp);
900
901   twice_nat = mp->flags & NAT_API_IS_TWICE_NAT;
902
903   if (mp->is_add)
904     {
905       rv = nat44_ed_add_interface_address (sw_if_index, twice_nat);
906     }
907   else
908     {
909       rv = nat44_ed_del_interface_address (sw_if_index, twice_nat);
910     }
911
912   BAD_SW_IF_INDEX_LABEL;
913
914   REPLY_MACRO (VL_API_NAT44_ADD_DEL_INTERFACE_ADDR_REPLY);
915 }
916
917 static void
918 send_nat44_interface_addr_details (u32 sw_if_index,
919                                    vl_api_registration_t * reg, u32 context,
920                                    u8 twice_nat)
921 {
922   vl_api_nat44_interface_addr_details_t *rmp;
923   snat_main_t *sm = &snat_main;
924
925   rmp = vl_msg_api_alloc (sizeof (*rmp));
926   clib_memset (rmp, 0, sizeof (*rmp));
927   rmp->_vl_msg_id =
928     ntohs (VL_API_NAT44_INTERFACE_ADDR_DETAILS + sm->msg_id_base);
929   rmp->sw_if_index = ntohl (sw_if_index);
930
931   if (twice_nat)
932     rmp->flags = (vl_api_nat_config_flags_t) NAT_API_IS_TWICE_NAT;
933   rmp->context = context;
934
935   vl_api_send_msg (reg, (u8 *) rmp);
936 }
937
938 static void
939 vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t
940                                             * mp)
941 {
942   snat_main_t *sm = &snat_main;
943   vl_api_registration_t *reg;
944   snat_address_resolve_t *ap;
945
946   reg = vl_api_client_index_to_registration (mp->client_index);
947   if (!reg)
948     return;
949
950   vec_foreach (ap, sm->addr_to_resolve)
951     {
952       send_nat44_interface_addr_details (ap->sw_if_index, reg, mp->context,
953                                          ap->is_twice_nat);
954     }
955 }
956
957 static nat44_lb_addr_port_t *
958 unformat_nat44_lb_addr_port (vl_api_nat44_lb_addr_port_t *addr_port_pairs,
959                              u32 addr_port_pair_num)
960 {
961   u8 i;
962   nat44_lb_addr_port_t *lb_addr_port_pairs = 0, lb_addr_port;
963   vl_api_nat44_lb_addr_port_t *ap;
964
965   for (i = 0; i < addr_port_pair_num; i++)
966     {
967       ap = &addr_port_pairs[i];
968       clib_memset (&lb_addr_port, 0, sizeof (lb_addr_port));
969       clib_memcpy (&lb_addr_port.addr, ap->addr, 4);
970       lb_addr_port.port = ap->port;
971       lb_addr_port.probability = ap->probability;
972       lb_addr_port.vrf_id = clib_net_to_host_u32 (ap->vrf_id);
973       vec_add1 (lb_addr_port_pairs, lb_addr_port);
974     }
975
976   return lb_addr_port_pairs;
977 }
978
979 static void
980 vl_api_nat44_add_del_lb_static_mapping_t_handler (
981   vl_api_nat44_add_del_lb_static_mapping_t *mp)
982 {
983   snat_main_t *sm = &snat_main;
984   vl_api_nat44_add_del_lb_static_mapping_reply_t *rmp;
985   nat44_lb_addr_port_t *locals = 0;
986   ip4_address_t e_addr;
987   ip_protocol_t proto;
988   u32 flags = 0;
989   u8 *tag = 0;
990   int rv = 0;
991
992   locals = unformat_nat44_lb_addr_port (mp->locals,
993                                         clib_net_to_host_u32 (mp->local_num));
994   clib_memcpy (&e_addr, mp->external_addr, 4);
995   proto = mp->protocol;
996
997   if (mp->flags & NAT_API_IS_TWICE_NAT)
998     {
999       flags |= NAT_SM_FLAG_TWICE_NAT;
1000     }
1001   else if (mp->flags & NAT_API_IS_SELF_TWICE_NAT)
1002     {
1003       flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
1004     }
1005
1006   if (mp->flags & NAT_API_IS_OUT2IN_ONLY)
1007     {
1008       flags |= NAT_SM_FLAG_OUT2IN_ONLY;
1009     }
1010
1011   if (mp->is_add)
1012     {
1013       mp->tag[sizeof (mp->tag) - 1] = 0;
1014       tag = format (0, "%s", mp->tag);
1015       vec_terminate_c_string (tag);
1016
1017       rv = nat44_ed_add_lb_static_mapping (
1018         e_addr, mp->external_port, proto, locals, flags, tag,
1019         clib_net_to_host_u32 (mp->affinity));
1020     }
1021   else
1022     {
1023       rv = nat44_ed_del_lb_static_mapping (e_addr, mp->external_port, proto,
1024                                            flags);
1025     }
1026
1027   vec_free (locals);
1028   vec_free (tag);
1029   REPLY_MACRO (VL_API_NAT44_ADD_DEL_LB_STATIC_MAPPING_REPLY);
1030 }
1031
1032 static void
1033 vl_api_nat44_lb_static_mapping_add_del_local_t_handler (
1034   vl_api_nat44_lb_static_mapping_add_del_local_t *mp)
1035 {
1036   snat_main_t *sm = &snat_main;
1037   vl_api_nat44_lb_static_mapping_add_del_local_reply_t *rmp;
1038   int rv = 0;
1039   ip4_address_t e_addr, l_addr;
1040   ip_protocol_t proto;
1041
1042   clib_memcpy (&e_addr, mp->external_addr, 4);
1043   clib_memcpy (&l_addr, mp->local.addr, 4);
1044   proto = mp->protocol;
1045
1046   rv = nat44_ed_add_del_lb_static_mapping_local (
1047     e_addr, mp->external_port, l_addr, mp->local.port, proto,
1048     clib_net_to_host_u32 (mp->local.vrf_id), mp->local.probability,
1049     mp->is_add);
1050
1051   REPLY_MACRO (VL_API_NAT44_LB_STATIC_MAPPING_ADD_DEL_LOCAL_REPLY);
1052 }
1053
1054 static void
1055 send_nat44_lb_static_mapping_details (snat_static_mapping_t *m,
1056                                       vl_api_registration_t *reg, u32 context)
1057 {
1058   vl_api_nat44_lb_static_mapping_details_t *rmp;
1059   snat_main_t *sm = &snat_main;
1060   nat44_lb_addr_port_t *ap;
1061   vl_api_nat44_lb_addr_port_t *locals;
1062   u32 local_num = 0;
1063
1064   rmp = vl_msg_api_alloc (
1065     sizeof (*rmp) + (pool_elts (m->locals) * sizeof (nat44_lb_addr_port_t)));
1066
1067   clib_memset (rmp, 0, sizeof (*rmp));
1068   rmp->_vl_msg_id =
1069     ntohs (VL_API_NAT44_LB_STATIC_MAPPING_DETAILS + sm->msg_id_base);
1070
1071   clib_memcpy (rmp->external_addr, &(m->external_addr), 4);
1072   rmp->external_port = m->external_port;
1073   rmp->protocol = m->proto;
1074   rmp->context = context;
1075
1076   if (is_sm_self_twice_nat (m->flags))
1077     {
1078       rmp->flags |= NAT_API_IS_SELF_TWICE_NAT;
1079     }
1080
1081   if (is_sm_out2in_only (m->flags))
1082     {
1083       rmp->flags |= NAT_API_IS_OUT2IN_ONLY;
1084     }
1085
1086   if (is_sm_twice_nat (m->flags))
1087     {
1088       rmp->flags |= NAT_API_IS_TWICE_NAT;
1089     }
1090
1091   if (m->tag)
1092     strncpy ((char *) rmp->tag, (char *) m->tag, vec_len (m->tag));
1093
1094   locals = (vl_api_nat44_lb_addr_port_t *) rmp->locals;
1095   pool_foreach (ap, m->locals)
1096     {
1097       clib_memcpy (locals->addr, &(ap->addr), 4);
1098       locals->port = ap->port;
1099       locals->probability = ap->probability;
1100       locals->vrf_id = ntohl (ap->vrf_id);
1101       locals++;
1102       local_num++;
1103     }
1104   rmp->local_num = ntohl (local_num);
1105
1106   vl_api_send_msg (reg, (u8 *) rmp);
1107 }
1108
1109 static void
1110 vl_api_nat44_lb_static_mapping_dump_t_handler (
1111   vl_api_nat44_lb_static_mapping_dump_t *mp)
1112 {
1113   vl_api_registration_t *reg;
1114   snat_main_t *sm = &snat_main;
1115   snat_static_mapping_t *m;
1116
1117   reg = vl_api_client_index_to_registration (mp->client_index);
1118   if (!reg)
1119     return;
1120
1121   pool_foreach (m, sm->static_mappings)
1122     {
1123       if (is_sm_lb (m->flags))
1124         send_nat44_lb_static_mapping_details (m, reg, mp->context);
1125     }
1126 }
1127
1128 static void
1129 vl_api_nat44_del_session_t_handler (vl_api_nat44_del_session_t *mp)
1130 {
1131   snat_main_t *sm = &snat_main;
1132   vl_api_nat44_del_session_reply_t *rmp;
1133   ip4_address_t addr, eh_addr;
1134   u16 port, eh_port;
1135   u32 vrf_id;
1136   int rv = 0;
1137   u8 is_in;
1138
1139   memcpy (&addr.as_u8, mp->address, 4);
1140   port = mp->port;
1141   vrf_id = clib_net_to_host_u32 (mp->vrf_id);
1142   memcpy (&eh_addr.as_u8, mp->ext_host_address, 4);
1143   eh_port = mp->ext_host_port;
1144
1145   is_in = mp->flags & NAT_API_IS_INSIDE;
1146
1147   rv = nat44_ed_del_session (sm, &addr, port, &eh_addr, eh_port, mp->protocol,
1148                              vrf_id, is_in);
1149
1150   REPLY_MACRO (VL_API_NAT44_DEL_SESSION_REPLY);
1151 }
1152
1153 static void
1154 vl_api_nat44_forwarding_enable_disable_t_handler (
1155   vl_api_nat44_forwarding_enable_disable_t *mp)
1156 {
1157   vl_api_nat44_forwarding_enable_disable_reply_t *rmp;
1158   snat_main_t *sm = &snat_main;
1159   int rv = 0;
1160   nat44_ed_forwarding_enable_disable (mp->enable);
1161   REPLY_MACRO (VL_API_NAT44_FORWARDING_ENABLE_DISABLE_REPLY);
1162 }
1163
1164 static void
1165 vl_api_nat44_show_running_config_t_handler (
1166   vl_api_nat44_show_running_config_t *mp)
1167 {
1168   vl_api_nat44_show_running_config_reply_t *rmp;
1169   snat_main_t *sm = &snat_main;
1170   nat44_config_t *rc = &sm->rconfig;
1171   int rv = 0;
1172
1173   REPLY_MACRO2_ZERO (
1174     VL_API_NAT44_SHOW_RUNNING_CONFIG_REPLY, ({
1175       rmp->inside_vrf = htonl (rc->inside_vrf);
1176       rmp->outside_vrf = htonl (rc->outside_vrf);
1177
1178       rmp->sessions = htonl (rc->sessions);
1179       rmp->translation_buckets = htonl (sm->translation_buckets);
1180
1181       // OBSOLETE
1182       rmp->users = 0;
1183       rmp->user_buckets = 0;
1184       rmp->user_sessions = 0;
1185
1186       rmp->timeouts.udp = htonl (sm->timeouts.udp);
1187       rmp->timeouts.tcp_established = htonl (sm->timeouts.tcp.established);
1188       rmp->timeouts.tcp_transitory = htonl (sm->timeouts.tcp.transitory);
1189       rmp->timeouts.icmp = htonl (sm->timeouts.icmp);
1190
1191       rmp->forwarding_enabled = sm->forwarding_enabled == 1;
1192       // consider how to split functionality between subplugins
1193       rmp->ipfix_logging_enabled = nat_ipfix_logging_enabled ();
1194       rmp->flags |= NAT44_IS_ENDPOINT_DEPENDENT;
1195     }));
1196 }
1197
1198 static void
1199 vl_api_nat44_ed_add_del_vrf_table_t_handler (
1200   vl_api_nat44_ed_add_del_vrf_table_t *mp)
1201 {
1202   snat_main_t *sm = &snat_main;
1203   vl_api_nat44_ed_add_del_vrf_table_reply_t *rmp;
1204   int rv = nat44_ed_add_del_vrf_table (clib_net_to_host_u32 (mp->table_vrf_id),
1205                                        mp->is_add);
1206   REPLY_MACRO (VL_API_NAT44_ED_ADD_DEL_VRF_TABLE_REPLY);
1207 }
1208
1209 static void
1210 vl_api_nat44_ed_add_del_vrf_route_t_handler (
1211   vl_api_nat44_ed_add_del_vrf_route_t *mp)
1212 {
1213   snat_main_t *sm = &snat_main;
1214   vl_api_nat44_ed_add_del_vrf_route_reply_t *rmp;
1215   int rv =
1216     nat44_ed_add_del_vrf_route (clib_net_to_host_u32 (mp->table_vrf_id),
1217                                 clib_net_to_host_u32 (mp->vrf_id), mp->is_add);
1218   REPLY_MACRO (VL_API_NAT44_ED_ADD_DEL_VRF_ROUTE_REPLY);
1219 }
1220
1221 static void
1222 nat44_ed_vrf_tables_send_details (vl_api_registration_t *rp, u32 context,
1223                                   vrf_table_t *t)
1224 {
1225   snat_main_t *sm = &snat_main;
1226   vl_api_nat44_ed_vrf_tables_details_t *mp;
1227
1228   u32 *vrf_ids = 0;
1229   vrf_route_t *r;
1230
1231   mp = vl_msg_api_alloc_zero (sizeof (*mp) +
1232                               sizeof (mp->vrf_ids[0]) * vec_len (t->routes));
1233   mp->_vl_msg_id =
1234     ntohs (VL_API_NAT44_ED_VRF_TABLES_DETAILS + sm->msg_id_base);
1235   mp->context = context;
1236   mp->n_vrf_ids = clib_host_to_net_u32 (vec_len (t->routes));
1237
1238   pool_foreach (r, t->routes)
1239     {
1240       vec_add1 (vrf_ids, r->vrf_id);
1241     }
1242
1243   // copy the records
1244   clib_memcpy (mp->vrf_ids, vrf_ids,
1245                sizeof (mp->vrf_ids[0]) * vec_len (t->routes));
1246
1247   vec_free (vrf_ids);
1248
1249   // send the message
1250   vl_api_send_msg (rp, (u8 *) mp);
1251 }
1252
1253 static void
1254 nat44_ed_vrf_tables_send_details_v2 (vl_api_registration_t *rp, u32 context,
1255                                      vrf_table_t *t)
1256 {
1257   snat_main_t *sm = &snat_main;
1258   vl_api_nat44_ed_vrf_tables_v2_details_t *mp;
1259
1260   u32 *vrf_ids = 0;
1261   vrf_route_t *r;
1262
1263   mp = vl_msg_api_alloc_zero (sizeof (*mp) +
1264                               sizeof (mp->vrf_ids[0]) * vec_len (t->routes));
1265   mp->_vl_msg_id = clib_net_to_host_u16 (VL_API_NAT44_ED_VRF_TABLES_DETAILS +
1266                                          sm->msg_id_base);
1267   mp->context = context;
1268   mp->n_vrf_ids = clib_net_to_host_u32 (vec_len (t->routes));
1269   mp->table_vrf_id = clib_net_to_host_u32 (t->table_vrf_id);
1270   pool_foreach (r, t->routes)
1271     {
1272       vec_add1 (vrf_ids, clib_net_to_host_u32 (r->vrf_id));
1273     }
1274
1275   // copy the records
1276   clib_memcpy (mp->vrf_ids, vrf_ids,
1277                sizeof (mp->vrf_ids[0]) * vec_len (t->routes));
1278
1279   vec_free (vrf_ids);
1280
1281   // send the message
1282   vl_api_send_msg (rp, (u8 *) mp);
1283 }
1284
1285 static void
1286 vl_api_nat44_ed_vrf_tables_dump_t_handler (
1287   vl_api_nat44_ed_vrf_tables_dump_t *mp)
1288 {
1289   snat_main_t *sm = &snat_main;
1290   vl_api_registration_t *rp;
1291   vrf_table_t *t;
1292
1293   rp = vl_api_client_index_to_registration (mp->client_index);
1294   if (rp == 0)
1295     return;
1296
1297   pool_foreach (t, sm->vrf_tables)
1298     {
1299       nat44_ed_vrf_tables_send_details (rp, mp->context, t);
1300     }
1301 }
1302
1303 static void
1304 vl_api_nat44_ed_vrf_tables_v2_dump_t_handler (
1305   vl_api_nat44_ed_vrf_tables_v2_dump_t *mp)
1306 {
1307   snat_main_t *sm = &snat_main;
1308   vl_api_registration_t *rp;
1309   vrf_table_t *t;
1310
1311   rp = vl_api_client_index_to_registration (mp->client_index);
1312   if (rp == 0)
1313     return;
1314
1315   pool_foreach (t, sm->vrf_tables)
1316     {
1317       nat44_ed_vrf_tables_send_details_v2 (rp, mp->context, t);
1318     }
1319 }
1320
1321 /* user (internal host) key */
1322 typedef struct
1323 {
1324   union
1325   {
1326     struct
1327     {
1328       ip4_address_t addr;
1329       u32 fib_index;
1330     };
1331     u64 as_u64;
1332   };
1333 } snat_user_key_t;
1334
1335 typedef struct
1336 {
1337   ip4_address_t addr;
1338   u32 fib_index;
1339   u32 nsessions;
1340   u32 nstaticsessions;
1341 } snat_user_t;
1342
1343 typedef struct
1344 {
1345   u32 user_buckets;
1346   snat_user_t *users;
1347   clib_bihash_8_8_t user_hash;
1348 } user_create_helper_t;
1349
1350 static void
1351 send_nat44_user_details (snat_user_t *u, vl_api_registration_t *reg,
1352                          u32 context)
1353 {
1354   vl_api_nat44_user_details_t *rmp;
1355   snat_main_t *sm = &snat_main;
1356   ip4_main_t *im = &ip4_main;
1357
1358   rmp = vl_msg_api_alloc (sizeof (*rmp));
1359   clib_memset (rmp, 0, sizeof (*rmp));
1360   rmp->_vl_msg_id = ntohs (VL_API_NAT44_USER_DETAILS + sm->msg_id_base);
1361
1362   if (!pool_is_free_index (im->fibs, u->fib_index))
1363     {
1364       fib_table_t *fib = fib_table_get (u->fib_index, FIB_PROTOCOL_IP4);
1365       rmp->vrf_id = ntohl (fib->ft_table_id);
1366     }
1367
1368   clib_memcpy (rmp->ip_address, &(u->addr), 4);
1369   rmp->nsessions = ntohl (u->nsessions);
1370   rmp->nstaticsessions = ntohl (u->nstaticsessions);
1371   rmp->context = context;
1372
1373   vl_api_send_msg (reg, (u8 *) rmp);
1374 }
1375
1376 static void
1377 nat_ed_user_create_helper (user_create_helper_t *uch, snat_session_t *s)
1378 {
1379   snat_user_key_t k;
1380   k.addr = s->in2out.addr;
1381   k.fib_index = s->in2out.fib_index;
1382   clib_bihash_kv_8_8_t key, value;
1383   key.key = k.as_u64;
1384   snat_user_t *u;
1385
1386   if (clib_bihash_search_8_8 (&uch->user_hash, &key, &value))
1387     {
1388       pool_get (uch->users, u);
1389       u->addr = k.addr;
1390       u->fib_index = k.fib_index;
1391       u->nsessions = 0;
1392       u->nstaticsessions = 0;
1393       key.value = u - uch->users;
1394       clib_bihash_add_del_8_8 (&uch->user_hash, &key, 1);
1395     }
1396   else
1397     {
1398       u = pool_elt_at_index (uch->users, value.value);
1399     }
1400   if (nat44_ed_is_session_static (s))
1401     {
1402       ++u->nstaticsessions;
1403     }
1404   else
1405     {
1406       ++u->nsessions;
1407     }
1408 }
1409
1410 u8 *
1411 format_user_kvp (u8 *s, va_list *args)
1412 {
1413   clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
1414   snat_user_key_t k;
1415   k.as_u64 = v->key;
1416   s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
1417               k.fib_index, v->value);
1418   return s;
1419 }
1420
1421 static void
1422 nat_ed_users_create (snat_main_per_thread_data_t *tsm,
1423                      user_create_helper_t *uch)
1424 {
1425   snat_session_t *s;
1426   clib_bihash_init_8_8 (&uch->user_hash, "users", uch->user_buckets, 0);
1427   clib_bihash_set_kvp_format_fn_8_8 (&uch->user_hash, format_user_kvp);
1428   pool_foreach (s, tsm->sessions)
1429     {
1430       nat_ed_user_create_helper (uch, s);
1431     }
1432 }
1433
1434 static void
1435 nat_ed_users_destroy (user_create_helper_t *uch)
1436 {
1437   pool_free (uch->users);
1438   clib_bihash_free_8_8 (&uch->user_hash);
1439 }
1440
1441 static void
1442 vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp)
1443 {
1444   user_create_helper_t uch;
1445   vl_api_registration_t *reg;
1446   snat_main_t *sm = &snat_main;
1447   snat_main_per_thread_data_t *tsm;
1448   snat_user_t *u;
1449
1450   clib_memset (&uch, 0, sizeof (uch));
1451
1452   uch.user_buckets = nat_calc_bihash_buckets (1024);
1453
1454   reg = vl_api_client_index_to_registration (mp->client_index);
1455   if (!reg)
1456     return;
1457
1458   vec_foreach (tsm, sm->per_thread_data)
1459     {
1460       nat_ed_users_create (tsm, &uch);
1461       pool_foreach (u, uch.users)
1462         {
1463           send_nat44_user_details (u, reg, mp->context);
1464         }
1465       nat_ed_users_destroy (&uch);
1466     }
1467 }
1468
1469 static void
1470 send_nat44_user_session_details (snat_session_t * s,
1471                                  vl_api_registration_t * reg, u32 context)
1472 {
1473   vl_api_nat44_user_session_details_t *rmp;
1474   snat_main_t *sm = &snat_main;
1475
1476   rmp = vl_msg_api_alloc (sizeof (*rmp));
1477   clib_memset (rmp, 0, sizeof (*rmp));
1478   rmp->_vl_msg_id =
1479     ntohs (VL_API_NAT44_USER_SESSION_DETAILS + sm->msg_id_base);
1480   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1481   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1482
1483   if (nat44_ed_is_session_static (s))
1484     rmp->flags |= NAT_API_IS_STATIC;
1485
1486   if (nat44_ed_is_twice_nat_session (s))
1487     rmp->flags |= NAT_API_IS_TWICE_NAT;
1488
1489   rmp->flags |= NAT_API_IS_EXT_HOST_VALID;
1490
1491   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1492   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1493   rmp->total_pkts = ntohl (s->total_pkts);
1494   rmp->context = context;
1495   rmp->outside_port = s->out2in.port;
1496   rmp->inside_port = s->in2out.port;
1497   rmp->protocol = clib_host_to_net_u16 (s->proto);
1498   clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1499   rmp->ext_host_port = s->ext_host_port;
1500   if (nat44_ed_is_twice_nat_session (s))
1501     {
1502       clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1503       rmp->ext_host_nat_port = s->ext_host_nat_port;
1504     }
1505
1506   vl_api_send_msg (reg, (u8 *) rmp);
1507 }
1508
1509 static void
1510 vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
1511                                           mp)
1512 {
1513   snat_main_per_thread_data_t *tsm;
1514   snat_main_t *sm = &snat_main;
1515   vl_api_registration_t *reg;
1516   snat_user_key_t ukey;
1517   snat_session_t *s;
1518   ip4_header_t ip;
1519
1520   reg = vl_api_client_index_to_registration (mp->client_index);
1521   if (!reg)
1522     return;
1523
1524   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1525   ip.src_address.as_u32 = ukey.addr.as_u32;
1526   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1527   if (sm->num_workers > 1)
1528     tsm = vec_elt_at_index (
1529       sm->per_thread_data,
1530       nat44_ed_get_in2out_worker_index (0, &ip, ukey.fib_index, 0));
1531   else
1532     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1533
1534       pool_foreach (s, tsm->sessions) {
1535         if (s->in2out.addr.as_u32 == ukey.addr.as_u32)
1536           {
1537             send_nat44_user_session_details (s, reg, mp->context);
1538           }
1539       }
1540 }
1541
1542 static void
1543 send_nat44_user_session_v2_details (snat_session_t *s,
1544                                     vl_api_registration_t *reg, u32 context)
1545 {
1546   vl_api_nat44_user_session_v2_details_t *rmp;
1547   snat_main_t *sm = &snat_main;
1548   vnet_main_t *vnm = vnet_get_main ();
1549   u64 now = vlib_time_now (vnm->vlib_main);
1550   u64 sess_timeout_time = 0;
1551
1552   rmp = vl_msg_api_alloc (sizeof (*rmp));
1553   clib_memset (rmp, 0, sizeof (*rmp));
1554   rmp->_vl_msg_id =
1555     ntohs (VL_API_NAT44_USER_SESSION_V2_DETAILS + sm->msg_id_base);
1556   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1557   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1558
1559   if (nat44_ed_is_session_static (s))
1560     rmp->flags |= NAT_API_IS_STATIC;
1561
1562   if (nat44_ed_is_twice_nat_session (s))
1563     rmp->flags |= NAT_API_IS_TWICE_NAT;
1564
1565   rmp->flags |= NAT_API_IS_EXT_HOST_VALID;
1566
1567   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1568   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1569   rmp->total_pkts = ntohl (s->total_pkts);
1570   rmp->context = context;
1571   rmp->outside_port = s->out2in.port;
1572   rmp->inside_port = s->in2out.port;
1573   rmp->protocol = clib_host_to_net_u16 (s->proto);
1574   clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1575   rmp->ext_host_port = s->ext_host_port;
1576   if (nat44_ed_is_twice_nat_session (s))
1577     {
1578       clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1579       rmp->ext_host_nat_port = s->ext_host_nat_port;
1580     }
1581
1582   sess_timeout_time = s->last_heard + nat44_session_get_timeout (sm, s);
1583   rmp->is_timed_out = (now >= sess_timeout_time);
1584
1585   vl_api_send_msg (reg, (u8 *) rmp);
1586 }
1587
1588 static void
1589 send_nat44_user_session_v3_details (snat_session_t *s,
1590                                     vl_api_registration_t *reg, u32 context)
1591 {
1592   vl_api_nat44_user_session_v3_details_t *rmp;
1593   snat_main_t *sm = &snat_main;
1594   u64 now = vlib_time_now (vlib_get_main ());
1595   u64 sess_timeout_time = 0;
1596
1597   rmp = vl_msg_api_alloc (sizeof (*rmp));
1598   clib_memset (rmp, 0, sizeof (*rmp));
1599   rmp->_vl_msg_id =
1600     ntohs (VL_API_NAT44_USER_SESSION_V3_DETAILS + sm->msg_id_base);
1601   clib_memcpy (rmp->outside_ip_address, (&s->out2in.addr), 4);
1602   clib_memcpy (rmp->inside_ip_address, (&s->in2out.addr), 4);
1603
1604   if (nat44_ed_is_session_static (s))
1605     rmp->flags |= NAT_API_IS_STATIC;
1606
1607   if (nat44_ed_is_twice_nat_session (s))
1608     rmp->flags |= NAT_API_IS_TWICE_NAT;
1609
1610   rmp->flags |= NAT_API_IS_EXT_HOST_VALID;
1611
1612   rmp->last_heard = clib_host_to_net_u64 ((u64) s->last_heard);
1613   rmp->time_since_last_heard =
1614     clib_host_to_net_u64 ((u64) (now - s->last_heard));
1615   rmp->total_bytes = clib_host_to_net_u64 (s->total_bytes);
1616   rmp->total_pkts = ntohl (s->total_pkts);
1617   rmp->context = context;
1618   rmp->outside_port = s->out2in.port;
1619   rmp->inside_port = s->in2out.port;
1620   rmp->protocol = clib_host_to_net_u16 (s->proto);
1621   clib_memcpy (rmp->ext_host_address, &s->ext_host_addr, 4);
1622   rmp->ext_host_port = s->ext_host_port;
1623   if (nat44_ed_is_twice_nat_session (s))
1624     {
1625       clib_memcpy (rmp->ext_host_nat_address, &s->ext_host_nat_addr, 4);
1626       rmp->ext_host_nat_port = s->ext_host_nat_port;
1627     }
1628
1629   sess_timeout_time = s->last_heard + nat44_session_get_timeout (sm, s);
1630   rmp->is_timed_out = (now >= sess_timeout_time);
1631
1632   vl_api_send_msg (reg, (u8 *) rmp);
1633 }
1634
1635 static void
1636 vl_api_nat44_user_session_v2_dump_t_handler (
1637   vl_api_nat44_user_session_v2_dump_t *mp)
1638 {
1639   snat_main_per_thread_data_t *tsm;
1640   snat_main_t *sm = &snat_main;
1641   vl_api_registration_t *reg;
1642   snat_user_key_t ukey;
1643   snat_session_t *s;
1644   ip4_header_t ip;
1645
1646   reg = vl_api_client_index_to_registration (mp->client_index);
1647   if (!reg)
1648     return;
1649
1650   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1651   ip.src_address.as_u32 = ukey.addr.as_u32;
1652   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1653   if (sm->num_workers > 1)
1654     tsm = vec_elt_at_index (
1655       sm->per_thread_data,
1656       nat44_ed_get_in2out_worker_index (0, &ip, ukey.fib_index, 0));
1657   else
1658     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1659
1660   pool_foreach (s, tsm->sessions)
1661     {
1662       if (s->in2out.addr.as_u32 == ukey.addr.as_u32)
1663         {
1664           send_nat44_user_session_v2_details (s, reg, mp->context);
1665         }
1666     }
1667 }
1668
1669 static void
1670 vl_api_nat44_user_session_v3_dump_t_handler (
1671   vl_api_nat44_user_session_v3_dump_t *mp)
1672 {
1673   snat_main_per_thread_data_t *tsm;
1674   snat_main_t *sm = &snat_main;
1675   vl_api_registration_t *reg;
1676   snat_user_key_t ukey;
1677   snat_session_t *s;
1678   ip4_header_t ip;
1679
1680   reg = vl_api_client_index_to_registration (mp->client_index);
1681   if (!reg)
1682     return;
1683
1684   clib_memcpy (&ukey.addr, mp->ip_address, 4);
1685   ip.src_address.as_u32 = ukey.addr.as_u32;
1686   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
1687   if (sm->num_workers > 1)
1688     tsm = vec_elt_at_index (
1689       sm->per_thread_data,
1690       nat44_ed_get_in2out_worker_index (0, &ip, ukey.fib_index, 0));
1691   else
1692     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
1693
1694   pool_foreach (s, tsm->sessions)
1695     {
1696       if (s->in2out.addr.as_u32 == ukey.addr.as_u32)
1697         {
1698           send_nat44_user_session_v3_details (s, reg, mp->context);
1699         }
1700     }
1701 }
1702
1703 /* API definitions */
1704 #include <vnet/format_fns.h>
1705 #include <nat/nat44-ed/nat44_ed.api.c>
1706
1707 /* Set up the API message handling tables */
1708 clib_error_t *
1709 nat44_api_hookup (vlib_main_t * vm)
1710 {
1711   snat_main_t *sm = &snat_main;
1712   sm->msg_id_base = setup_message_id_table ();
1713   return 0;
1714 }
1715
1716 /*
1717  * fd.io coding-style-patch-verification: ON
1718  *
1719  * Local Variables:
1720  * eval: (c-set-style "gnu")
1721  * End:
1722  */