ipfix-export: refactor params to the callback fns
[vpp.git] / src / plugins / nat / lib / ipfix_logging.c
1 /*
2  * nat_ipfix_logging.c - NAT Events IPFIX logging
3  *
4  * Copyright (c) 2016 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <vnet/fib/fib_table.h>
19 #include <vnet/ipfix-export/flow_report.h>
20 #include <vnet/ip/ip4.h>
21 #include <vnet/udp/udp_local.h>
22 #include <vlibmemory/api.h>
23 #include <vppinfra/atomics.h>
24 #include <nat/lib/ipfix_logging.h>
25 #include <nat/lib/inlines.h>
26
27 vlib_node_registration_t nat_ipfix_flush_node;
28 nat_ipfix_logging_main_t nat_ipfix_logging_main;
29
30 #define NAT44_SESSION_CREATE_LEN 26
31 #define NAT_ADDRESSES_EXHAUTED_LEN 13
32 #define MAX_ENTRIES_PER_USER_LEN 21
33 #define MAX_SESSIONS_LEN 17
34 #define MAX_BIBS_LEN 17
35 #define MAX_FRAGMENTS_IP4_LEN 21
36 #define MAX_FRAGMENTS_IP6_LEN 33
37 #define NAT64_BIB_LEN 38
38 #define NAT64_SES_LEN 62
39
40 #define NAT44_SESSION_CREATE_FIELD_COUNT 8
41 #define NAT_ADDRESSES_EXHAUTED_FIELD_COUNT 3
42 #define MAX_ENTRIES_PER_USER_FIELD_COUNT 5
43 #define MAX_SESSIONS_FIELD_COUNT 4
44 #define MAX_BIBS_FIELD_COUNT 4
45 #define MAX_FRAGMENTS_FIELD_COUNT 5
46 #define NAT64_BIB_FIELD_COUNT 8
47 #define NAT64_SES_FIELD_COUNT 12
48
49 typedef struct
50 {
51   u8 nat_event;
52   u32 src_ip;
53   u32 nat_src_ip;
54   ip_protocol_t proto;
55   u16 src_port;
56   u16 nat_src_port;
57   u32 vrf_id;
58 } nat_ipfix_logging_nat44_ses_args_t;
59
60 typedef struct
61 {
62   u32 pool_id;
63 } nat_ipfix_logging_addr_exhausted_args_t;
64
65 typedef struct
66 {
67   u32 limit;
68   u32 src_ip;
69 } nat_ipfix_logging_max_entries_per_user_args_t;
70
71 typedef struct
72 {
73   u32 limit;
74 } nat_ipfix_logging_max_sessions_args_t;
75
76 typedef struct
77 {
78   u32 limit;
79 } nat_ipfix_logging_max_bibs_args_t;
80
81 typedef struct
82 {
83   u32 limit;
84   u32 src;
85 } nat_ipfix_logging_max_frags_ip4_args_t;
86
87 typedef struct
88 {
89   u32 limit;
90   u64 src[2];
91 } nat_ipfix_logging_max_frags_ip6_args_t;
92
93 typedef struct
94 {
95   u8 nat_event;
96   u64 src_ip[2];
97   u32 nat_src_ip;
98   u8 proto;
99   u16 src_port;
100   u16 nat_src_port;
101   u64 dst_ip[2];
102   u32 nat_dst_ip;
103   u32 vrf_id;
104   u16 dst_port;
105   u16 nat_dst_port;
106 } nat_ipfix_logging_nat64_ses_args_t;
107
108 typedef struct
109 {
110   u8 nat_event;
111   u64 src_ip[2];
112   u32 nat_src_ip;
113   u8 proto;
114   u16 src_port;
115   u16 nat_src_port;
116   u32 vrf_id;
117 } nat_ipfix_logging_nat64_bib_args_t;
118
119 #define skip_if_disabled()                                        \
120 do {                                                              \
121   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;     \
122   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))    \
123     return;                                                       \
124 } while (0)
125
126 #define update_template_id(old_id, new_id)                \
127 do {                                                      \
128   u16 template_id = clib_atomic_fetch_or(old_id, 0);      \
129   clib_atomic_cmp_and_swap(old_id, template_id, new_id);  \
130 } while (0)
131
132 /**
133  * @brief Create an IPFIX template packet rewrite string
134  *
135  * @param frm               flow report main
136  * @param fr                flow report
137  * @param collector_address collector address
138  * @param src_address       source address
139  * @param collector_port    collector
140  * @param event             NAT event ID
141  * @param quota_event       NAT quota exceeded event ID
142  *
143  * @returns template packet
144  */
145 static inline u8 *
146 nat_template_rewrite (ipfix_exporter_t *exp, flow_report_t *fr,
147                       u16 collector_port, nat_event_t event,
148                       quota_exceed_event_t quota_event)
149 {
150   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
151   ip4_header_t *ip;
152   udp_header_t *udp;
153   ipfix_message_header_t *h;
154   ipfix_set_header_t *s;
155   ipfix_template_header_t *t;
156   ipfix_field_specifier_t *f;
157   ipfix_field_specifier_t *first_field;
158   u8 *rewrite = 0;
159   ip4_ipfix_template_packet_t *tp;
160   u32 field_count = 0;
161   flow_report_stream_t *stream;
162   u32 stream_index;
163
164   stream = &exp->streams[fr->stream_index];
165
166   stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
167   clib_atomic_cmp_and_swap (&silm->stream_index,
168                             stream_index, fr->stream_index);
169
170   if (event == NAT_ADDRESSES_EXHAUTED)
171     {
172       field_count = NAT_ADDRESSES_EXHAUTED_FIELD_COUNT;
173
174       update_template_id(&silm->addr_exhausted_template_id,
175                          fr->template_id);
176     }
177   else if (event == NAT44_SESSION_CREATE)
178     {
179       field_count = NAT44_SESSION_CREATE_FIELD_COUNT;
180
181       update_template_id(&silm->nat44_session_template_id,
182                          fr->template_id);
183     }
184   else if (event == NAT64_BIB_CREATE)
185     {
186       field_count = NAT64_BIB_FIELD_COUNT;
187
188       update_template_id(&silm->nat64_bib_template_id,
189                          fr->template_id);
190     }
191   else if (event == NAT64_SESSION_CREATE)
192     {
193       field_count = NAT64_SES_FIELD_COUNT;
194
195       update_template_id(&silm->nat64_ses_template_id,
196                          fr->template_id);
197     }
198   else if (event == QUOTA_EXCEEDED)
199     {
200       if (quota_event == MAX_ENTRIES_PER_USER)
201         {
202           field_count = MAX_ENTRIES_PER_USER_FIELD_COUNT;
203
204           update_template_id(&silm->max_entries_per_user_template_id,
205                              fr->template_id);
206
207         }
208       else if (quota_event == MAX_SESSION_ENTRIES)
209         {
210           field_count = MAX_SESSIONS_FIELD_COUNT;
211
212           update_template_id(&silm->max_sessions_template_id,
213                              fr->template_id);
214         }
215       else if (quota_event == MAX_BIB_ENTRIES)
216         {
217           field_count = MAX_BIBS_FIELD_COUNT;
218
219           update_template_id(&silm->max_bibs_template_id,
220                              fr->template_id);
221         }
222     }
223
224   /* allocate rewrite space */
225   vec_validate_aligned (rewrite,
226                         sizeof (ip4_ipfix_template_packet_t)
227                         + field_count * sizeof (ipfix_field_specifier_t) - 1,
228                         CLIB_CACHE_LINE_BYTES);
229
230   tp = (ip4_ipfix_template_packet_t *) rewrite;
231   ip = (ip4_header_t *) & tp->ip4;
232   udp = (udp_header_t *) (ip + 1);
233   h = (ipfix_message_header_t *) (udp + 1);
234   s = (ipfix_set_header_t *) (h + 1);
235   t = (ipfix_template_header_t *) (s + 1);
236   first_field = f = (ipfix_field_specifier_t *) (t + 1);
237
238   ip->ip_version_and_header_length = 0x45;
239   ip->ttl = 254;
240   ip->protocol = IP_PROTOCOL_UDP;
241   ip->src_address.as_u32 = exp->src_address.as_u32;
242   ip->dst_address.as_u32 = exp->ipfix_collector.as_u32;
243   udp->src_port = clib_host_to_net_u16 (stream->src_port);
244   udp->dst_port = clib_host_to_net_u16 (collector_port);
245   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
246
247   /* FIXUP: message header export_time */
248   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
249
250   /* Add TLVs to the template */
251   if (event == NAT_ADDRESSES_EXHAUTED)
252     {
253       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
254       f++;
255       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
256       f++;
257       f->e_id_length = ipfix_e_id_length (0, natPoolId, 4);
258       f++;
259     }
260   else if (event == NAT44_SESSION_CREATE)
261     {
262       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
263       f++;
264       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
265       f++;
266       f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
267       f++;
268       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
269       f++;
270       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
271       f++;
272       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
273       f++;
274       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
275       f++;
276       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
277       f++;
278     }
279   else if (event == NAT64_BIB_CREATE)
280     {
281       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
282       f++;
283       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
284       f++;
285       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
286       f++;
287       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
288       f++;
289       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
290       f++;
291       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
292       f++;
293       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
294       f++;
295       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
296       f++;
297     }
298   else if (event == NAT64_SESSION_CREATE)
299     {
300       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
301       f++;
302       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
303       f++;
304       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
305       f++;
306       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
307       f++;
308       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
309       f++;
310       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
311       f++;
312       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
313       f++;
314       f->e_id_length = ipfix_e_id_length (0, destinationIPv6Address, 16);
315       f++;
316       f->e_id_length = ipfix_e_id_length (0, postNATDestinationIPv4Address, 4);
317       f++;
318       f->e_id_length = ipfix_e_id_length (0, destinationTransportPort, 2);
319       f++;
320       f->e_id_length = ipfix_e_id_length (0, postNAPTDestinationTransportPort,
321                                           2);
322       f++;
323       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
324       f++;
325     }
326   else if (event == QUOTA_EXCEEDED)
327     {
328       if (quota_event == MAX_ENTRIES_PER_USER)
329         {
330           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
331                                               8);
332           f++;
333           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
334           f++;
335           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
336           f++;
337           f->e_id_length = ipfix_e_id_length (0, maxEntriesPerUser, 4);
338           f++;
339           f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
340           f++;
341         }
342       else if (quota_event == MAX_SESSION_ENTRIES)
343         {
344           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
345                                               8);
346           f++;
347           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
348           f++;
349           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
350           f++;
351           f->e_id_length = ipfix_e_id_length (0, maxSessionEntries, 4);
352           f++;
353         }
354       else if (quota_event == MAX_BIB_ENTRIES)
355         {
356           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
357                                               8);
358           f++;
359           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
360           f++;
361           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
362           f++;
363           f->e_id_length = ipfix_e_id_length (0, maxBIBEntries, 4);
364           f++;
365         }
366     }
367
368   /* Back to the template packet... */
369   ip = (ip4_header_t *) & tp->ip4;
370   udp = (udp_header_t *) (ip + 1);
371
372   ASSERT (f - first_field);
373   /* Field count in this template */
374   t->id_count = ipfix_id_count (fr->template_id, f - first_field);
375
376   /* set length in octets */
377   s->set_id_length =
378     ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
379
380   /* message length in octets */
381   h->version_length = version_length ((u8 *) f - (u8 *) h);
382
383   ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
384   ip->checksum = ip4_header_checksum (ip);
385
386   return rewrite;
387 }
388
389 u8 *
390 nat_template_rewrite_addr_exhausted (ipfix_exporter_t *exp, flow_report_t *fr,
391                                      u16 collector_port,
392                                      ipfix_report_element_t *elts, u32 n_elts,
393                                      u32 *stream_index)
394 {
395   return nat_template_rewrite (exp, fr, collector_port, NAT_ADDRESSES_EXHAUTED,
396                                0);
397 }
398
399 u8 *
400 nat_template_rewrite_nat44_session (ipfix_exporter_t *exp, flow_report_t *fr,
401                                     u16 collector_port,
402                                     ipfix_report_element_t *elts, u32 n_elts,
403                                     u32 *stream_index)
404 {
405   return nat_template_rewrite (exp, fr, collector_port, NAT44_SESSION_CREATE,
406                                0);
407 }
408
409 u8 *
410 nat_template_rewrite_max_entries_per_usr (
411   ipfix_exporter_t *exp, flow_report_t *fr, ip4_address_t *collector_address,
412   ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts,
413   u32 n_elts, u32 *stream_index)
414 {
415   return nat_template_rewrite (exp, fr, collector_port, QUOTA_EXCEEDED,
416                                MAX_ENTRIES_PER_USER);
417 }
418
419 u8 *
420 nat_template_rewrite_max_sessions (ipfix_exporter_t *exp, flow_report_t *fr,
421                                    u16 collector_port,
422                                    ipfix_report_element_t *elts, u32 n_elts,
423                                    u32 *stream_index)
424 {
425   return nat_template_rewrite (exp, fr, collector_port, QUOTA_EXCEEDED,
426                                MAX_SESSION_ENTRIES);
427 }
428
429 u8 *
430 nat_template_rewrite_max_bibs (ipfix_exporter_t *exp, flow_report_t *fr,
431                                u16 collector_port,
432                                ipfix_report_element_t *elts, u32 n_elts,
433                                u32 *stream_index)
434 {
435   return nat_template_rewrite (exp, fr, collector_port, QUOTA_EXCEEDED,
436                                MAX_BIB_ENTRIES);
437 }
438
439 u8 *
440 nat_template_rewrite_nat64_bib (ipfix_exporter_t *exp, flow_report_t *fr,
441                                 u16 collector_port,
442                                 ipfix_report_element_t *elts, u32 n_elts,
443                                 u32 *stream_index)
444 {
445   return nat_template_rewrite (exp, fr, collector_port, NAT64_BIB_CREATE, 0);
446 }
447
448 u8 *
449 nat_template_rewrite_nat64_session (ipfix_exporter_t *exp, flow_report_t *fr,
450                                     u16 collector_port,
451                                     ipfix_report_element_t *elts, u32 n_elts,
452                                     u32 *stream_index)
453 {
454   return nat_template_rewrite (exp, fr, collector_port, NAT64_SESSION_CREATE,
455                                0);
456 }
457
458 static inline void
459 nat_ipfix_header_create (flow_report_main_t * frm,
460                           vlib_buffer_t * b0, u32 * offset)
461 {
462   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
463   flow_report_stream_t *stream;
464   ip4_ipfix_template_packet_t *tp;
465   ipfix_message_header_t *h = 0;
466   ipfix_set_header_t *s = 0;
467   u32 sequence_number;
468   u32 stream_index;
469   ip4_header_t *ip;
470   udp_header_t *udp;
471   vlib_main_t *vm = vlib_get_main ();
472   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
473
474   stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
475   stream = &exp->streams[stream_index];
476
477   b0->current_data = 0;
478   b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
479     sizeof (*s);
480   b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_FLOW_REPORT);
481   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
482   vnet_buffer (b0)->sw_if_index[VLIB_TX] = exp->fib_index;
483   tp = vlib_buffer_get_current (b0);
484   ip = (ip4_header_t *) & tp->ip4;
485   udp = (udp_header_t *) (ip + 1);
486   h = (ipfix_message_header_t *) (udp + 1);
487   s = (ipfix_set_header_t *) (h + 1);
488
489   ip->ip_version_and_header_length = 0x45;
490   ip->ttl = 254;
491   ip->protocol = IP_PROTOCOL_UDP;
492   ip->flags_and_fragment_offset = 0;
493   ip->src_address.as_u32 = exp->src_address.as_u32;
494   ip->dst_address.as_u32 = exp->ipfix_collector.as_u32;
495   udp->src_port = clib_host_to_net_u16 (stream->src_port);
496   udp->dst_port = clib_host_to_net_u16 (exp->collector_port);
497   udp->checksum = 0;
498
499   h->export_time = clib_host_to_net_u32 ((u32)
500                                          (((f64) frm->unix_time_0) +
501                                           (vlib_time_now (vm) -
502                                            frm->vlib_time_0)));
503
504   sequence_number = clib_atomic_fetch_add (&stream->sequence_number, 1);
505   h->sequence_number = clib_host_to_net_u32 (sequence_number);
506   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
507
508   *offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
509 }
510
511 static inline void
512 nat_ipfix_send (flow_report_main_t *frm, vlib_frame_t *f, vlib_buffer_t *b0,
513                 u16 template_id)
514 {
515   ip4_ipfix_template_packet_t *tp;
516   ipfix_message_header_t *h = 0;
517   ipfix_set_header_t *s = 0;
518   ip4_header_t *ip;
519   udp_header_t *udp;
520   vlib_main_t *vm = vlib_get_main ();
521   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
522
523   tp = vlib_buffer_get_current (b0);
524   ip = (ip4_header_t *) & tp->ip4;
525   udp = (udp_header_t *) (ip + 1);
526   h = (ipfix_message_header_t *) (udp + 1);
527   s = (ipfix_set_header_t *) (h + 1);
528
529   s->set_id_length = ipfix_set_id_length (template_id,
530                                           b0->current_length -
531                                           (sizeof (*ip) + sizeof (*udp) +
532                                            sizeof (*h)));
533   h->version_length = version_length (b0->current_length -
534                                       (sizeof (*ip) + sizeof (*udp)));
535
536   ip->length = clib_host_to_net_u16 (b0->current_length);
537   ip->checksum = ip4_header_checksum (ip);
538   udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
539
540   if (exp->udp_checksum)
541     {
542       udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
543       if (udp->checksum == 0)
544         udp->checksum = 0xffff;
545     }
546
547   ASSERT (ip4_header_checksum_is_valid (ip));
548
549   vlib_put_frame_to_node (vm, ip4_lookup_node.index, f);
550 }
551
552 static void
553 nat_ipfix_logging_nat44_ses (u32 thread_index, u8 nat_event, u32 src_ip,
554                              u32 nat_src_ip, ip_protocol_t proto, u16 src_port,
555                              u16 nat_src_port, u32 fib_index, int do_flush)
556 {
557   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
558   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
559   flow_report_main_t *frm = &flow_report_main;
560   vlib_frame_t *f;
561   vlib_buffer_t *b0 = 0;
562   u32 bi0 = ~0;
563   u32 offset;
564   vlib_main_t *vm = vlib_get_main ();
565   u64 now;
566   u16 template_id;
567   u32 vrf_id;
568   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
569
570   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
571   now += silm->milisecond_time_0;
572
573   b0 = sitd->nat44_session_buffer;
574
575   if (PREDICT_FALSE (b0 == 0))
576     {
577       if (do_flush)
578         return;
579
580       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
581         {
582           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
583           return;
584         }
585
586       b0 = sitd->nat44_session_buffer = vlib_get_buffer (vm, bi0);
587       offset = 0;
588     }
589   else
590     {
591       bi0 = vlib_get_buffer_index (vm, b0);
592       offset = sitd->nat44_session_next_record_offset;
593     }
594
595   f = sitd->nat44_session_frame;
596   if (PREDICT_FALSE (f == 0))
597     {
598       u32 *to_next;
599       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
600       sitd->nat44_session_frame = f;
601       to_next = vlib_frame_vector_args (f);
602       to_next[0] = bi0;
603       f->n_vectors = 1;
604     }
605
606   if (PREDICT_FALSE (offset == 0))
607     nat_ipfix_header_create (frm, b0, &offset);
608
609   if (PREDICT_TRUE (do_flush == 0))
610     {
611       u64 time_stamp = clib_host_to_net_u64 (now);
612       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
613       offset += sizeof (time_stamp);
614
615       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
616       offset += sizeof (nat_event);
617
618       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
619       offset += sizeof (src_ip);
620
621       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
622       offset += sizeof (nat_src_ip);
623
624       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
625       offset += sizeof (proto);
626
627       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
628       offset += sizeof (src_port);
629
630       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
631       offset += sizeof (nat_src_port);
632
633       vrf_id = fib_table_get_table_id (fib_index, FIB_PROTOCOL_IP4);
634       vrf_id = clib_host_to_net_u32 (vrf_id);
635       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
636       offset += sizeof (vrf_id);
637
638       b0->current_length += NAT44_SESSION_CREATE_LEN;
639     }
640
641   if (PREDICT_FALSE (do_flush ||
642                      (offset + NAT44_SESSION_CREATE_LEN) > exp->path_mtu))
643     {
644       template_id = clib_atomic_fetch_or (
645         &silm->nat44_session_template_id,
646         0);
647       nat_ipfix_send (frm, f, b0, template_id);
648       sitd->nat44_session_frame = 0;
649       sitd->nat44_session_buffer = 0;
650       offset = 0;
651     }
652   sitd->nat44_session_next_record_offset = offset;
653 }
654
655 static void
656 nat_ipfix_logging_addr_exhausted (u32 thread_index, u32 pool_id, int do_flush)
657 {
658   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
659   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
660   flow_report_main_t *frm = &flow_report_main;
661   vlib_frame_t *f;
662   vlib_buffer_t *b0 = 0;
663   u32 bi0 = ~0;
664   u32 offset;
665   vlib_main_t *vm = vlib_get_main ();
666   u64 now;
667   u8 nat_event = NAT_ADDRESSES_EXHAUTED;
668   u16 template_id;
669   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
670
671   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
672   now += silm->milisecond_time_0;
673
674   b0 = sitd->addr_exhausted_buffer;
675
676   if (PREDICT_FALSE (b0 == 0))
677     {
678       if (do_flush)
679         return;
680
681       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
682         {
683           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
684           return;
685         }
686
687       b0 = sitd->addr_exhausted_buffer = vlib_get_buffer (vm, bi0);
688       offset = 0;
689     }
690   else
691     {
692       bi0 = vlib_get_buffer_index (vm, b0);
693       offset = sitd->addr_exhausted_next_record_offset;
694     }
695
696   f = sitd->addr_exhausted_frame;
697   if (PREDICT_FALSE (f == 0))
698     {
699       u32 *to_next;
700       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
701       sitd->addr_exhausted_frame = f;
702       to_next = vlib_frame_vector_args (f);
703       to_next[0] = bi0;
704       f->n_vectors = 1;
705     }
706
707   if (PREDICT_FALSE (offset == 0))
708     nat_ipfix_header_create (frm, b0, &offset);
709
710   if (PREDICT_TRUE (do_flush == 0))
711     {
712       u64 time_stamp = clib_host_to_net_u64 (now);
713       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
714       offset += sizeof (time_stamp);
715
716       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
717       offset += sizeof (nat_event);
718
719       clib_memcpy_fast (b0->data + offset, &pool_id, sizeof (pool_id));
720       offset += sizeof (pool_id);
721
722       b0->current_length += NAT_ADDRESSES_EXHAUTED_LEN;
723     }
724
725   if (PREDICT_FALSE (do_flush ||
726                      (offset + NAT_ADDRESSES_EXHAUTED_LEN) > exp->path_mtu))
727     {
728       template_id = clib_atomic_fetch_or (
729           &silm->addr_exhausted_template_id,
730           0);
731       nat_ipfix_send (frm, f, b0, template_id);
732       sitd->addr_exhausted_frame = 0;
733       sitd->addr_exhausted_buffer = 0;
734       offset = 0;
735     }
736   sitd->addr_exhausted_next_record_offset = offset;
737 }
738
739 static void
740 nat_ipfix_logging_max_entries_per_usr (u32 thread_index,
741                                         u32 limit, u32 src_ip, int do_flush)
742 {
743   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
744   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
745   flow_report_main_t *frm = &flow_report_main;
746   vlib_frame_t *f;
747   vlib_buffer_t *b0 = 0;
748   u32 bi0 = ~0;
749   u32 offset;
750   vlib_main_t *vm = vlib_get_main ();
751   u64 now;
752   u8 nat_event = QUOTA_EXCEEDED;
753   u32 quota_event = clib_host_to_net_u32 (MAX_ENTRIES_PER_USER);
754   u16 template_id;
755   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
756
757   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
758   now += silm->milisecond_time_0;
759
760   b0 = sitd->max_entries_per_user_buffer;
761
762   if (PREDICT_FALSE (b0 == 0))
763     {
764       if (do_flush)
765         return;
766
767       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
768         {
769           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
770           return;
771         }
772
773       b0 = sitd->max_entries_per_user_buffer = vlib_get_buffer (vm, bi0);
774       offset = 0;
775     }
776   else
777     {
778       bi0 = vlib_get_buffer_index (vm, b0);
779       offset = sitd->max_entries_per_user_next_record_offset;
780     }
781
782   f = sitd->max_entries_per_user_frame;
783   if (PREDICT_FALSE (f == 0))
784     {
785       u32 *to_next;
786       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
787       sitd->max_entries_per_user_frame = f;
788       to_next = vlib_frame_vector_args (f);
789       to_next[0] = bi0;
790       f->n_vectors = 1;
791     }
792
793   if (PREDICT_FALSE (offset == 0))
794     nat_ipfix_header_create (frm, b0, &offset);
795
796   if (PREDICT_TRUE (do_flush == 0))
797     {
798       u64 time_stamp = clib_host_to_net_u64 (now);
799       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
800       offset += sizeof (time_stamp);
801
802       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
803       offset += sizeof (nat_event);
804
805       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
806       offset += sizeof (quota_event);
807
808       limit = clib_host_to_net_u32 (limit);
809       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
810       offset += sizeof (limit);
811
812       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
813       offset += sizeof (src_ip);
814
815       b0->current_length += MAX_ENTRIES_PER_USER_LEN;
816     }
817
818   if (PREDICT_FALSE (do_flush ||
819                      (offset + MAX_ENTRIES_PER_USER_LEN) > exp->path_mtu))
820     {
821       template_id = clib_atomic_fetch_or (
822           &silm->max_entries_per_user_template_id,
823           0);
824       nat_ipfix_send (frm, f, b0, template_id);
825       sitd->max_entries_per_user_frame = 0;
826       sitd->max_entries_per_user_buffer = 0;
827       offset = 0;
828     }
829   sitd->max_entries_per_user_next_record_offset = offset;
830 }
831
832 static void
833 nat_ipfix_logging_max_ses (u32 thread_index, u32 limit, int do_flush)
834 {
835   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
836   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
837   flow_report_main_t *frm = &flow_report_main;
838   vlib_frame_t *f;
839   vlib_buffer_t *b0 = 0;
840   u32 bi0 = ~0;
841   u32 offset;
842   vlib_main_t *vm = vlib_get_main ();
843   u64 now;
844   u8 nat_event = QUOTA_EXCEEDED;
845   u32 quota_event = clib_host_to_net_u32 (MAX_SESSION_ENTRIES);
846   u16 template_id;
847   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
848
849   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
850   now += silm->milisecond_time_0;
851
852   b0 = sitd->max_sessions_buffer;
853
854   if (PREDICT_FALSE (b0 == 0))
855     {
856       if (do_flush)
857         return;
858
859       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
860         {
861           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
862           return;
863         }
864
865       b0 = sitd->max_sessions_buffer = vlib_get_buffer (vm, bi0);
866       offset = 0;
867     }
868   else
869     {
870       bi0 = vlib_get_buffer_index (vm, b0);
871       offset = sitd->max_sessions_next_record_offset;
872     }
873
874   f = sitd->max_sessions_frame;
875   if (PREDICT_FALSE (f == 0))
876     {
877       u32 *to_next;
878       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
879       sitd->max_sessions_frame = f;
880       to_next = vlib_frame_vector_args (f);
881       to_next[0] = bi0;
882       f->n_vectors = 1;
883     }
884
885   if (PREDICT_FALSE (offset == 0))
886     nat_ipfix_header_create (frm, b0, &offset);
887
888   if (PREDICT_TRUE (do_flush == 0))
889     {
890       u64 time_stamp = clib_host_to_net_u64 (now);
891       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
892       offset += sizeof (time_stamp);
893
894       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
895       offset += sizeof (nat_event);
896
897       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
898       offset += sizeof (quota_event);
899
900       limit = clib_host_to_net_u32 (limit);
901       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
902       offset += sizeof (limit);
903
904       b0->current_length += MAX_SESSIONS_LEN;
905     }
906
907   if (PREDICT_FALSE (do_flush || (offset + MAX_SESSIONS_LEN) > exp->path_mtu))
908     {
909       template_id = clib_atomic_fetch_or (
910         &silm->max_sessions_template_id,
911         0);
912       nat_ipfix_send (frm, f, b0, template_id);
913       sitd->max_sessions_frame = 0;
914       sitd->max_sessions_buffer = 0;
915       offset = 0;
916     }
917   sitd->max_sessions_next_record_offset = offset;
918 }
919
920 static void
921 nat_ipfix_logging_max_bib (u32 thread_index, u32 limit, int do_flush)
922 {
923   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
924   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
925   flow_report_main_t *frm = &flow_report_main;
926   vlib_frame_t *f;
927   vlib_buffer_t *b0 = 0;
928   u32 bi0 = ~0;
929   u32 offset;
930   vlib_main_t *vm = vlib_get_main ();
931   u64 now;
932   u8 nat_event = QUOTA_EXCEEDED;
933   u32 quota_event = clib_host_to_net_u32 (MAX_BIB_ENTRIES);
934   u16 template_id;
935   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
936
937   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
938   now += silm->milisecond_time_0;
939
940   b0 = sitd->max_bibs_buffer;
941
942   if (PREDICT_FALSE (b0 == 0))
943     {
944       if (do_flush)
945         return;
946
947       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
948         {
949           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
950           return;
951         }
952
953       b0 = sitd->max_bibs_buffer = vlib_get_buffer (vm, bi0);
954       offset = 0;
955     }
956   else
957     {
958       bi0 = vlib_get_buffer_index (vm, b0);
959       offset = sitd->max_bibs_next_record_offset;
960     }
961
962   f = sitd->max_bibs_frame;
963   if (PREDICT_FALSE (f == 0))
964     {
965       u32 *to_next;
966       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
967       sitd->max_bibs_frame = f;
968       to_next = vlib_frame_vector_args (f);
969       to_next[0] = bi0;
970       f->n_vectors = 1;
971     }
972
973   if (PREDICT_FALSE (offset == 0))
974     nat_ipfix_header_create (frm, b0, &offset);
975
976   if (PREDICT_TRUE (do_flush == 0))
977     {
978       u64 time_stamp = clib_host_to_net_u64 (now);
979       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
980       offset += sizeof (time_stamp);
981
982       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
983       offset += sizeof (nat_event);
984
985       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
986       offset += sizeof (quota_event);
987
988       limit = clib_host_to_net_u32 (limit);
989       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
990       offset += sizeof (limit);
991
992       b0->current_length += MAX_BIBS_LEN;
993     }
994
995   if (PREDICT_FALSE (do_flush || (offset + MAX_BIBS_LEN) > exp->path_mtu))
996     {
997       template_id = clib_atomic_fetch_or (
998         &silm->max_bibs_template_id,
999         0);
1000       nat_ipfix_send (frm, f, b0, template_id);
1001       sitd->max_bibs_frame = 0;
1002       sitd->max_bibs_buffer = 0;
1003       offset = 0;
1004     }
1005   sitd->max_bibs_next_record_offset = offset;
1006 }
1007
1008 static void
1009 nat_ipfix_logging_nat64_bibe (u32 thread_index, u8 nat_event,
1010                               ip6_address_t * src_ip, u32 nat_src_ip,
1011                               u8 proto, u16 src_port, u16 nat_src_port,
1012                               u32 vrf_id, int do_flush)
1013 {
1014   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1015   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1016   flow_report_main_t *frm = &flow_report_main;
1017   vlib_frame_t *f;
1018   vlib_buffer_t *b0 = 0;
1019   u32 bi0 = ~0;
1020   u32 offset;
1021   vlib_main_t *vm = vlib_get_main ();
1022   u64 now;
1023   u16 template_id;
1024   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
1025
1026   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1027   now += silm->milisecond_time_0;
1028
1029   b0 = sitd->nat64_bib_buffer;
1030
1031   if (PREDICT_FALSE (b0 == 0))
1032     {
1033       if (do_flush)
1034         return;
1035
1036       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1037         {
1038           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1039           return;
1040         }
1041
1042       b0 = sitd->nat64_bib_buffer = vlib_get_buffer (vm, bi0);
1043       offset = 0;
1044     }
1045   else
1046     {
1047       bi0 = vlib_get_buffer_index (vm, b0);
1048       offset = sitd->nat64_bib_next_record_offset;
1049     }
1050
1051   f = sitd->nat64_bib_frame;
1052   if (PREDICT_FALSE (f == 0))
1053     {
1054       u32 *to_next;
1055       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1056       sitd->nat64_bib_frame = f;
1057       to_next = vlib_frame_vector_args (f);
1058       to_next[0] = bi0;
1059       f->n_vectors = 1;
1060     }
1061
1062   if (PREDICT_FALSE (offset == 0))
1063     nat_ipfix_header_create (frm, b0, &offset);
1064
1065   if (PREDICT_TRUE (do_flush == 0))
1066     {
1067       u64 time_stamp = clib_host_to_net_u64 (now);
1068       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1069       offset += sizeof (time_stamp);
1070
1071       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1072       offset += sizeof (nat_event);
1073
1074       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1075       offset += sizeof (ip6_address_t);
1076
1077       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1078       offset += sizeof (nat_src_ip);
1079
1080       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1081       offset += sizeof (proto);
1082
1083       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1084       offset += sizeof (src_port);
1085
1086       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1087       offset += sizeof (nat_src_port);
1088
1089       vrf_id = clib_host_to_net_u32 (vrf_id);
1090       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1091       offset += sizeof (vrf_id);
1092
1093       b0->current_length += NAT64_BIB_LEN;
1094     }
1095
1096   if (PREDICT_FALSE (do_flush || (offset + NAT64_BIB_LEN) > exp->path_mtu))
1097     {
1098       template_id = clib_atomic_fetch_or (
1099         &silm->nat64_bib_template_id,
1100         0);
1101       nat_ipfix_send (frm, f, b0, template_id);
1102       sitd->nat64_bib_frame = 0;
1103       sitd->nat64_bib_buffer = 0;
1104       offset = 0;
1105     }
1106   sitd->nat64_bib_next_record_offset = offset;
1107 }
1108
1109 static void
1110 nat_ipfix_logging_nat64_ses (u32 thread_index, u8 nat_event,
1111                              ip6_address_t * src_ip, u32 nat_src_ip,
1112                              u8 proto, u16 src_port, u16 nat_src_port,
1113                              ip6_address_t * dst_ip, u32 nat_dst_ip,
1114                              u16 dst_port, u16 nat_dst_port,
1115                              u32 vrf_id, int do_flush)
1116 {
1117   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1118   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1119   flow_report_main_t *frm = &flow_report_main;
1120   vlib_frame_t *f;
1121   vlib_buffer_t *b0 = 0;
1122   u32 bi0 = ~0;
1123   u32 offset;
1124   vlib_main_t *vm = vlib_get_main ();
1125   u64 now;
1126   u16 template_id;
1127   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
1128
1129   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1130   now += silm->milisecond_time_0;
1131
1132   b0 = sitd->nat64_ses_buffer;
1133
1134   if (PREDICT_FALSE (b0 == 0))
1135     {
1136       if (do_flush)
1137         return;
1138
1139       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1140         {
1141           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1142           return;
1143         }
1144
1145       b0 = sitd->nat64_ses_buffer = vlib_get_buffer (vm, bi0);
1146       offset = 0;
1147     }
1148   else
1149     {
1150       bi0 = vlib_get_buffer_index (vm, b0);
1151       offset = sitd->nat64_ses_next_record_offset;
1152     }
1153
1154   f = sitd->nat64_ses_frame;
1155   if (PREDICT_FALSE (f == 0))
1156     {
1157       u32 *to_next;
1158       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1159       sitd->nat64_ses_frame = f;
1160       to_next = vlib_frame_vector_args (f);
1161       to_next[0] = bi0;
1162       f->n_vectors = 1;
1163     }
1164
1165   if (PREDICT_FALSE (offset == 0))
1166     nat_ipfix_header_create (frm, b0, &offset);
1167
1168   if (PREDICT_TRUE (do_flush == 0))
1169     {
1170       u64 time_stamp = clib_host_to_net_u64 (now);
1171       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1172       offset += sizeof (time_stamp);
1173
1174       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1175       offset += sizeof (nat_event);
1176
1177       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1178       offset += sizeof (ip6_address_t);
1179
1180       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1181       offset += sizeof (nat_src_ip);
1182
1183       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1184       offset += sizeof (proto);
1185
1186       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1187       offset += sizeof (src_port);
1188
1189       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1190       offset += sizeof (nat_src_port);
1191
1192       clib_memcpy_fast (b0->data + offset, dst_ip, sizeof (ip6_address_t));
1193       offset += sizeof (ip6_address_t);
1194
1195       clib_memcpy_fast (b0->data + offset, &nat_dst_ip, sizeof (nat_dst_ip));
1196       offset += sizeof (nat_dst_ip);
1197
1198       clib_memcpy_fast (b0->data + offset, &dst_port, sizeof (dst_port));
1199       offset += sizeof (dst_port);
1200
1201       clib_memcpy_fast (b0->data + offset, &nat_dst_port, sizeof (nat_dst_port));
1202       offset += sizeof (nat_dst_port);
1203
1204       vrf_id = clib_host_to_net_u32 (vrf_id);
1205       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1206       offset += sizeof (vrf_id);
1207
1208       b0->current_length += NAT64_SES_LEN;
1209     }
1210
1211   if (PREDICT_FALSE (do_flush || (offset + NAT64_SES_LEN) > exp->path_mtu))
1212     {
1213       template_id = clib_atomic_fetch_or (
1214         &silm->nat64_ses_template_id,
1215         0);
1216       nat_ipfix_send (frm, f, b0, template_id);
1217       sitd->nat64_ses_frame = 0;
1218       sitd->nat64_ses_buffer = 0;
1219       offset = 0;
1220     }
1221   sitd->nat64_ses_next_record_offset = offset;
1222 }
1223
1224 void
1225 nat_ipfix_flush (u32 thread_index)
1226 {
1227   int do_flush = 1;
1228
1229   nat_ipfix_logging_nat44_ses (thread_index,
1230                                 0, 0, 0, 0, 0, 0, 0, do_flush);
1231   nat_ipfix_logging_addr_exhausted (thread_index, 0, do_flush);
1232   nat_ipfix_logging_max_entries_per_usr (thread_index, 0, 0, do_flush);
1233   nat_ipfix_logging_max_ses (thread_index, 0, do_flush);
1234   nat_ipfix_logging_max_bib (thread_index, 0, do_flush);
1235   nat_ipfix_logging_nat64_bibe (thread_index,
1236                                 0, 0, 0, 0, 0, 0, 0, do_flush);
1237   nat_ipfix_logging_nat64_ses (thread_index,
1238                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, do_flush);
1239 }
1240
1241 int
1242 nat_ipfix_logging_enabled ()
1243 {
1244   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1245   return !clib_atomic_fetch_or(&silm->enabled, 0);
1246 }
1247
1248 void
1249 nat_ipfix_flush_from_main (void)
1250 {
1251   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1252   vlib_main_t *worker_vm;
1253   int i;
1254
1255   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))
1256     return;
1257
1258   if (PREDICT_FALSE (!silm->worker_vms))
1259     {
1260       for (i = 1; i < vlib_get_n_threads (); i++)
1261         {
1262           worker_vm = vlib_get_main_by_index (i);
1263           if (worker_vm)
1264             vec_add1 (silm->worker_vms, worker_vm);
1265         }
1266     }
1267
1268   /* Trigger flush for each worker thread */
1269   for (i = 0; i < vec_len (silm->worker_vms); i++)
1270     {
1271       worker_vm = silm->worker_vms[i];
1272       if (worker_vm)
1273         vlib_node_set_interrupt_pending (worker_vm,
1274                                          nat_ipfix_flush_node.index);
1275     }
1276
1277   /* Finally flush main thread */
1278   nat_ipfix_flush (0);
1279 }
1280
1281 /**
1282  * @brief Generate NAT44 session create event
1283  */
1284 void
1285 nat_ipfix_logging_nat44_ses_create (u32 thread_index, u32 src_ip,
1286                                     u32 nat_src_ip, ip_protocol_t proto,
1287                                     u16 src_port, u16 nat_src_port,
1288                                     u32 fib_index)
1289 {
1290   skip_if_disabled ();
1291
1292   nat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_CREATE, src_ip,
1293                                nat_src_ip, proto, src_port, nat_src_port,
1294                                fib_index, 0);
1295 }
1296
1297 /**
1298  * @brief Generate NAT44 session delete event
1299  */
1300 void
1301 nat_ipfix_logging_nat44_ses_delete (u32 thread_index, u32 src_ip,
1302                                     u32 nat_src_ip, ip_protocol_t proto,
1303                                     u16 src_port, u16 nat_src_port,
1304                                     u32 fib_index)
1305 {
1306   skip_if_disabled ();
1307
1308   nat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_DELETE, src_ip,
1309                                nat_src_ip, proto, src_port, nat_src_port,
1310                                fib_index, 0);
1311 }
1312
1313 /**
1314  * @brief Generate NAT addresses exhausted event
1315  *
1316  * @param thread_index thread index
1317  * @param pool_id NAT pool ID
1318  */
1319 void
1320 nat_ipfix_logging_addresses_exhausted (u32 thread_index, u32 pool_id)
1321 {
1322   //TODO: This event SHOULD be rate limited
1323   skip_if_disabled ();
1324
1325   nat_ipfix_logging_addr_exhausted (thread_index, pool_id, 0);
1326 }
1327
1328 /**
1329  * @brief Generate maximum entries per user exceeded event
1330  *
1331  * @param thread_index thread index
1332  * @param limit maximum NAT entries that can be created per user
1333  * @param src_ip source IPv4 address
1334  */
1335 void
1336 nat_ipfix_logging_max_entries_per_user (u32 thread_index, u32 limit, u32 src_ip)
1337 {
1338   //TODO: This event SHOULD be rate limited
1339   skip_if_disabled ();
1340
1341   nat_ipfix_logging_max_entries_per_usr (thread_index, limit, src_ip, 0);
1342 }
1343
1344 vlib_frame_t *
1345 deterministic_nat_data_callback
1346 (flow_report_main_t * frm,
1347                                         flow_report_t * fr,
1348                                         vlib_frame_t * f,
1349                                         u32 * to_next, u32 node_index)
1350 {
1351   nat_ipfix_flush_from_main();
1352
1353   return f;
1354 }
1355
1356 /**
1357  * @brief Generate maximum session entries exceeded event
1358  *
1359  * @param thread_index thread index
1360  * @param limit configured limit
1361  */
1362 void
1363 nat_ipfix_logging_max_sessions (u32 thread_index, u32 limit)
1364 {
1365   //TODO: This event SHOULD be rate limited
1366   skip_if_disabled ();
1367
1368   nat_ipfix_logging_max_ses (thread_index, limit, 0);
1369 }
1370
1371 /**
1372  * @brief Generate maximum BIB entries exceeded event
1373  *
1374  * @param thread_index thread index
1375  * @param limit configured limit
1376  */
1377 void
1378 nat_ipfix_logging_max_bibs (u32 thread_index, u32 limit)
1379 {
1380   //TODO: This event SHOULD be rate limited
1381   skip_if_disabled ();
1382
1383   nat_ipfix_logging_max_bib (thread_index, limit, 0);
1384 }
1385
1386 /**
1387  * @brief Generate NAT64 BIB create and delete events
1388  *
1389  * @param thread_index thread index
1390  * @param src_ip       source IPv6 address
1391  * @param nat_src_ip   transaltes source IPv4 address
1392  * @param proto        L4 protocol
1393  * @param src_port     source port
1394  * @param nat_src_port translated source port
1395  * @param vrf_id       VRF ID
1396  * @param is_create    non-zero value if create event otherwise delete event
1397  */
1398 void
1399 nat_ipfix_logging_nat64_bib (u32 thread_index, ip6_address_t * src_ip,
1400                              ip4_address_t * nat_src_ip, u8 proto,
1401                              u16 src_port, u16 nat_src_port, u32 vrf_id,
1402                              u8 is_create)
1403 {
1404   u8 nat_event;
1405
1406   skip_if_disabled ();
1407
1408   nat_event = is_create ? NAT64_BIB_CREATE : NAT64_BIB_DELETE;
1409
1410   nat_ipfix_logging_nat64_bibe (thread_index, nat_event, src_ip,
1411                                 nat_src_ip->as_u32, proto, src_port,
1412                                 nat_src_port, vrf_id, 0);
1413 }
1414
1415 /**
1416  * @brief Generate NAT64 session create and delete events
1417  *
1418  * @param thread_index thread index
1419  * @param src_ip       source IPv6 address
1420  * @param nat_src_ip   transaltes source IPv4 address
1421  * @param proto        L4 protocol
1422  * @param src_port     source port
1423  * @param nat_src_port translated source port
1424  * @param dst_ip       destination IPv6 address
1425  * @param nat_dst_ip   destination IPv4 address
1426  * @param dst_port     destination port
1427  * @param nat_dst_port translated destination port
1428  * @param vrf_id       VRF ID
1429  * @param is_create    non-zero value if create event otherwise delete event
1430  */
1431 void
1432 nat_ipfix_logging_nat64_session (u32 thread_index,
1433                                  ip6_address_t * src_ip,
1434                                  ip4_address_t * nat_src_ip, u8 proto,
1435                                  u16 src_port, u16 nat_src_port,
1436                                  ip6_address_t * dst_ip,
1437                                  ip4_address_t * nat_dst_ip, u16 dst_port,
1438                                  u16 nat_dst_port, u32 vrf_id, u8 is_create)
1439 {
1440   u8 nat_event;
1441
1442   skip_if_disabled ();
1443
1444   nat_event = is_create ? NAT64_SESSION_CREATE : NAT64_SESSION_DELETE;
1445
1446   nat_ipfix_logging_nat64_ses (thread_index, nat_event, src_ip,
1447                                nat_src_ip->as_u32, proto, src_port,
1448                                nat_src_port, dst_ip, nat_dst_ip->as_u32,
1449                                dst_port, nat_dst_port, vrf_id, 0);
1450 }
1451
1452 vlib_frame_t *
1453 data_callback (flow_report_main_t *frm, ipfix_exporter_t *exp,
1454                flow_report_t *fr, vlib_frame_t *f, u32 *to_next,
1455                u32 node_index)
1456 {
1457   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1458
1459   if (PREDICT_FALSE (++silm->call_counter >= vec_len (exp->reports)))
1460     {
1461       nat_ipfix_flush_from_main();
1462       silm->call_counter = 0;
1463     }
1464
1465   return f;
1466 }
1467
1468 /**
1469  * @brief Enable/disable NAT plugin IPFIX logging
1470  *
1471  * @param enable    1 if enable, 0 if disable
1472  * @param domain_id observation domain ID
1473  * @param src_port  source port number
1474  *
1475  * @returns 0 if success
1476  */
1477 int
1478 nat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
1479 {
1480   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1481   ipfix_exporter_t *exp = &flow_report_main.exporters[0];
1482   vnet_flow_report_add_del_args_t a;
1483   int rv;
1484   u8 e = enable ? 1 : 0;
1485
1486   if (clib_atomic_cmp_and_swap (&silm->enabled, e ^ 1, e) == e)
1487     return 0;
1488
1489   clib_memset (&a, 0, sizeof (a));
1490   a.is_add = enable;
1491   a.domain_id = domain_id ? domain_id : 1;
1492   a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
1493   a.flow_data_callback = data_callback;
1494
1495   a.rewrite_callback = nat_template_rewrite_nat44_session;
1496   rv = vnet_flow_report_add_del (exp, &a, NULL);
1497   if (rv)
1498     {
1499       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1500       return -1;
1501     }
1502
1503   a.rewrite_callback = nat_template_rewrite_addr_exhausted;
1504   rv = vnet_flow_report_add_del (exp, &a, NULL);
1505   if (rv)
1506     {
1507       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1508       return -1;
1509     }
1510
1511   a.rewrite_callback = nat_template_rewrite_max_sessions;
1512   rv = vnet_flow_report_add_del (exp, &a, NULL);
1513   if (rv)
1514     {
1515       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1516       return -1;
1517     }
1518
1519   a.rewrite_callback = nat_template_rewrite_max_bibs;
1520   rv = vnet_flow_report_add_del (exp, &a, NULL);
1521   if (rv)
1522     {
1523       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1524       return -1;
1525     }
1526
1527   a.rewrite_callback = nat_template_rewrite_nat64_bib;
1528   rv = vnet_flow_report_add_del (exp, &a, NULL);
1529   if (rv)
1530     {
1531       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1532       return -1;
1533     }
1534
1535   a.rewrite_callback = nat_template_rewrite_nat64_session;
1536   rv = vnet_flow_report_add_del (exp, &a, NULL);
1537   if (rv)
1538     {
1539       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1540       return -1;
1541     }
1542
1543   // if endpoint dependent per user max entries is also required
1544   /*
1545   a.rewrite_callback = nat_template_rewrite_max_entries_per_usr;
1546   rv = vnet_flow_report_add_del (exp, &a, NULL);
1547   if (rv)
1548     {
1549       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1550       return -1;
1551     }
1552   */
1553
1554   return 0;
1555 }
1556
1557 /**
1558  * @brief Initialize NAT plugin IPFIX logging
1559  *
1560  * @param vm vlib main
1561  */
1562 void
1563 nat_ipfix_logging_init (vlib_main_t * vm)
1564 {
1565   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1566   vlib_thread_main_t *tm = vlib_get_thread_main ();
1567
1568   silm->enabled = 0;
1569   silm->worker_vms = 0;
1570   silm->call_counter = 0;
1571
1572   /* Set up time reference pair */
1573   silm->vlib_time_0 = vlib_time_now (vm);
1574   silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
1575
1576   vec_validate (silm->per_thread_data, tm->n_vlib_mains - 1);
1577 }
1578
1579 static uword
1580 ipfix_flush_process (vlib_main_t *vm,
1581                      vlib_node_runtime_t *rt,
1582                      vlib_frame_t *f)
1583 {
1584   nat_ipfix_flush(vm->thread_index);
1585   return 0;
1586 }
1587
1588 /* *INDENT-OFF* */
1589 VLIB_REGISTER_NODE (nat_ipfix_flush_node) = {
1590   .function = ipfix_flush_process,
1591   .name = "nat-ipfix-flush",
1592   .type = VLIB_NODE_TYPE_INPUT,
1593   .state = VLIB_NODE_STATE_INTERRUPT,
1594 };
1595 /* *INDENT-ON* */