c24c2372b541d1907278fde0e22be8270a0ff9e2
[vpp.git] / src / plugins / nat / nat_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/ipfix-export/flow_report.h>
19 #include <vlibmemory/api.h>
20 #include <nat/nat_inlines.h>
21 #include <nat/nat_ipfix_logging.h>
22 #include <vppinfra/atomics.h>
23
24 vlib_node_registration_t snat_ipfix_flush_node;
25 snat_ipfix_logging_main_t snat_ipfix_logging_main;
26
27 #define NAT44_SESSION_CREATE_LEN 26
28 #define NAT_ADDRESSES_EXHAUTED_LEN 13
29 #define MAX_ENTRIES_PER_USER_LEN 21
30 #define MAX_SESSIONS_LEN 17
31 #define MAX_BIBS_LEN 17
32 #define MAX_FRAGMENTS_IP4_LEN 21
33 #define MAX_FRAGMENTS_IP6_LEN 33
34 #define NAT64_BIB_LEN 38
35 #define NAT64_SES_LEN 62
36
37 #define NAT44_SESSION_CREATE_FIELD_COUNT 8
38 #define NAT_ADDRESSES_EXHAUTED_FIELD_COUNT 3
39 #define MAX_ENTRIES_PER_USER_FIELD_COUNT 5
40 #define MAX_SESSIONS_FIELD_COUNT 4
41 #define MAX_BIBS_FIELD_COUNT 4
42 #define MAX_FRAGMENTS_FIELD_COUNT 5
43 #define NAT64_BIB_FIELD_COUNT 8
44 #define NAT64_SES_FIELD_COUNT 12
45
46 typedef struct
47 {
48   u8 nat_event;
49   u32 src_ip;
50   u32 nat_src_ip;
51   snat_protocol_t snat_proto;
52   u16 src_port;
53   u16 nat_src_port;
54   u32 vrf_id;
55 } snat_ipfix_logging_nat44_ses_args_t;
56
57 typedef struct
58 {
59   u32 pool_id;
60 } snat_ipfix_logging_addr_exhausted_args_t;
61
62 typedef struct
63 {
64   u32 limit;
65   u32 src_ip;
66 } snat_ipfix_logging_max_entries_per_user_args_t;
67
68 typedef struct
69 {
70   u32 limit;
71 } nat_ipfix_logging_max_sessions_args_t;
72
73 typedef struct
74 {
75   u32 limit;
76 } nat_ipfix_logging_max_bibs_args_t;
77
78 typedef struct
79 {
80   u32 limit;
81   u32 src;
82 } nat_ipfix_logging_max_frags_ip4_args_t;
83
84 typedef struct
85 {
86   u32 limit;
87   u64 src[2];
88 } nat_ipfix_logging_max_frags_ip6_args_t;
89
90 typedef struct
91 {
92   u8 nat_event;
93   u64 src_ip[2];
94   u32 nat_src_ip;
95   u8 proto;
96   u16 src_port;
97   u16 nat_src_port;
98   u64 dst_ip[2];
99   u32 nat_dst_ip;
100   u32 vrf_id;
101   u16 dst_port;
102   u16 nat_dst_port;
103 } nat_ipfix_logging_nat64_ses_args_t;
104
105 typedef struct
106 {
107   u8 nat_event;
108   u64 src_ip[2];
109   u32 nat_src_ip;
110   u8 proto;
111   u16 src_port;
112   u16 nat_src_port;
113   u32 vrf_id;
114 } nat_ipfix_logging_nat64_bib_args_t;
115
116 #define skip_if_disabled()                                        \
117 do {                                                              \
118   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;     \
119   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))    \
120     return;                                                       \
121 } while (0)
122
123 #define update_template_id(old_id, new_id)                \
124 do {                                                      \
125   u16 template_id = clib_atomic_fetch_or(old_id, 0);      \
126   clib_atomic_cmp_and_swap(old_id, template_id, new_id);  \
127 } while (0)
128
129 /**
130  * @brief Create an IPFIX template packet rewrite string
131  *
132  * @param frm               flow report main
133  * @param fr                flow report
134  * @param collector_address collector address
135  * @param src_address       source address
136  * @param collector_port    collector
137  * @param event             NAT event ID
138  * @param quota_event       NAT quota exceeded event ID
139  *
140  * @returns template packet
141  */
142 static inline u8 *
143 snat_template_rewrite (flow_report_main_t * frm,
144                        flow_report_t * fr,
145                        ip4_address_t * collector_address,
146                        ip4_address_t * src_address,
147                        u16 collector_port,
148                        nat_event_t event, quota_exceed_event_t quota_event)
149 {
150   snat_ipfix_logging_main_t *silm = &snat_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 = &frm->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       else if (quota_event == MAX_FRAGMENTS_PENDING_REASSEMBLY)
223         {
224           field_count = MAX_FRAGMENTS_FIELD_COUNT;
225
226           update_template_id(&silm->max_frags_ip4_template_id,
227                              fr->template_id);
228         }
229       else if (quota_event == MAX_FRAGMENTS_PENDING_REASSEMBLY_IP6)
230         {
231           field_count = MAX_FRAGMENTS_FIELD_COUNT;
232
233           update_template_id(&silm->max_frags_ip6_template_id,
234                              fr->template_id);
235         }
236     }
237
238   /* allocate rewrite space */
239   vec_validate_aligned (rewrite,
240                         sizeof (ip4_ipfix_template_packet_t)
241                         + field_count * sizeof (ipfix_field_specifier_t) - 1,
242                         CLIB_CACHE_LINE_BYTES);
243
244   tp = (ip4_ipfix_template_packet_t *) rewrite;
245   ip = (ip4_header_t *) & tp->ip4;
246   udp = (udp_header_t *) (ip + 1);
247   h = (ipfix_message_header_t *) (udp + 1);
248   s = (ipfix_set_header_t *) (h + 1);
249   t = (ipfix_template_header_t *) (s + 1);
250   first_field = f = (ipfix_field_specifier_t *) (t + 1);
251
252   ip->ip_version_and_header_length = 0x45;
253   ip->ttl = 254;
254   ip->protocol = IP_PROTOCOL_UDP;
255   ip->src_address.as_u32 = src_address->as_u32;
256   ip->dst_address.as_u32 = collector_address->as_u32;
257   udp->src_port = clib_host_to_net_u16 (stream->src_port);
258   udp->dst_port = clib_host_to_net_u16 (collector_port);
259   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
260
261   /* FIXUP: message header export_time */
262   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
263
264   /* Add TLVs to the template */
265   if (event == NAT_ADDRESSES_EXHAUTED)
266     {
267       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
268       f++;
269       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
270       f++;
271       f->e_id_length = ipfix_e_id_length (0, natPoolId, 4);
272       f++;
273     }
274   else if (event == NAT44_SESSION_CREATE)
275     {
276       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
277       f++;
278       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
279       f++;
280       f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
281       f++;
282       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
283       f++;
284       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
285       f++;
286       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
287       f++;
288       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
289       f++;
290       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
291       f++;
292     }
293   else if (event == NAT64_BIB_CREATE)
294     {
295       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
296       f++;
297       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
298       f++;
299       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
300       f++;
301       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
302       f++;
303       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
304       f++;
305       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
306       f++;
307       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
308       f++;
309       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
310       f++;
311     }
312   else if (event == NAT64_SESSION_CREATE)
313     {
314       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
315       f++;
316       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
317       f++;
318       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
319       f++;
320       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
321       f++;
322       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
323       f++;
324       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
325       f++;
326       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
327       f++;
328       f->e_id_length = ipfix_e_id_length (0, destinationIPv6Address, 16);
329       f++;
330       f->e_id_length = ipfix_e_id_length (0, postNATDestinationIPv4Address, 4);
331       f++;
332       f->e_id_length = ipfix_e_id_length (0, destinationTransportPort, 2);
333       f++;
334       f->e_id_length = ipfix_e_id_length (0, postNAPTDestinationTransportPort,
335                                           2);
336       f++;
337       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
338       f++;
339     }
340   else if (event == QUOTA_EXCEEDED)
341     {
342       if (quota_event == MAX_ENTRIES_PER_USER)
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, maxEntriesPerUser, 4);
352           f++;
353           f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
354           f++;
355         }
356       else if (quota_event == MAX_SESSION_ENTRIES)
357         {
358           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
359                                               8);
360           f++;
361           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
362           f++;
363           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
364           f++;
365           f->e_id_length = ipfix_e_id_length (0, maxSessionEntries, 4);
366           f++;
367         }
368       else if (quota_event == MAX_BIB_ENTRIES)
369         {
370           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
371                                               8);
372           f++;
373           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
374           f++;
375           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
376           f++;
377           f->e_id_length = ipfix_e_id_length (0, maxBIBEntries, 4);
378           f++;
379         }
380       else if (quota_event == MAX_FRAGMENTS_PENDING_REASSEMBLY)
381         {
382           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
383                                               8);
384           f++;
385           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
386           f++;
387           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
388           f++;
389           f->e_id_length = ipfix_e_id_length (0, maxFragmentsPendingReassembly,
390                                               4);
391           f++;
392           f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
393           f++;
394         }
395       else if (quota_event == MAX_FRAGMENTS_PENDING_REASSEMBLY_IP6)
396         {
397           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
398                                               8);
399           f++;
400           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
401           f++;
402           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
403           f++;
404           f->e_id_length = ipfix_e_id_length (0, maxFragmentsPendingReassembly,
405                                               4);
406           f++;
407           f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
408           f++;
409         }
410     }
411
412   /* Back to the template packet... */
413   ip = (ip4_header_t *) & tp->ip4;
414   udp = (udp_header_t *) (ip + 1);
415
416   ASSERT (f - first_field);
417   /* Field count in this template */
418   t->id_count = ipfix_id_count (fr->template_id, f - first_field);
419
420   /* set length in octets */
421   s->set_id_length =
422     ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
423
424   /* message length in octets */
425   h->version_length = version_length ((u8 *) f - (u8 *) h);
426
427   ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
428   ip->checksum = ip4_header_checksum (ip);
429
430   return rewrite;
431 }
432
433 u8 *
434 snat_template_rewrite_addr_exhausted (flow_report_main_t * frm,
435                                       flow_report_t * fr,
436                                       ip4_address_t * collector_address,
437                                       ip4_address_t * src_address,
438                                       u16 collector_port,
439                                       ipfix_report_element_t *elts,
440                                       u32 n_elts, u32 *stream_index)
441 {
442   return snat_template_rewrite (frm, fr, collector_address, src_address,
443                                 collector_port, NAT_ADDRESSES_EXHAUTED, 0);
444 }
445
446 u8 *
447 snat_template_rewrite_nat44_session (flow_report_main_t * frm,
448                                      flow_report_t * fr,
449                                      ip4_address_t * collector_address,
450                                      ip4_address_t * src_address,
451                                      u16 collector_port,
452                                      ipfix_report_element_t *elts,
453                                      u32 n_elts, u32 *stream_index)
454 {
455   return snat_template_rewrite (frm, fr, collector_address, src_address,
456                                 collector_port, NAT44_SESSION_CREATE, 0);
457 }
458
459 u8 *
460 snat_template_rewrite_max_entries_per_usr (flow_report_main_t * frm,
461                                            flow_report_t * fr,
462                                            ip4_address_t * collector_address,
463                                            ip4_address_t * src_address,
464                                            u16 collector_port,
465                                            ipfix_report_element_t *elts,
466                                            u32 n_elts, u32 *stream_index)
467 {
468   return snat_template_rewrite (frm, fr, collector_address, src_address,
469                                 collector_port, QUOTA_EXCEEDED,
470                                 MAX_ENTRIES_PER_USER);
471 }
472
473 u8 *
474 nat_template_rewrite_max_sessions (flow_report_main_t * frm,
475                                    flow_report_t * fr,
476                                    ip4_address_t * collector_address,
477                                    ip4_address_t * src_address,
478                                    u16 collector_port,
479                                    ipfix_report_element_t *elts,
480                                    u32 n_elts, u32 *stream_index)
481 {
482   return snat_template_rewrite (frm, fr, collector_address, src_address,
483                                 collector_port, QUOTA_EXCEEDED,
484                                 MAX_SESSION_ENTRIES);
485 }
486
487 u8 *
488 nat_template_rewrite_max_bibs (flow_report_main_t * frm,
489                                flow_report_t * fr,
490                                ip4_address_t * collector_address,
491                                ip4_address_t * src_address,
492                                u16 collector_port,
493                                ipfix_report_element_t *elts,
494                                u32 n_elts, u32 *stream_index)
495 {
496   return snat_template_rewrite (frm, fr, collector_address, src_address,
497                                 collector_port, QUOTA_EXCEEDED,
498                                 MAX_BIB_ENTRIES);
499 }
500
501 u8 *
502 nat_template_rewrite_max_frags_ip4 (flow_report_main_t * frm,
503                                     flow_report_t * fr,
504                                     ip4_address_t * collector_address,
505                                     ip4_address_t * src_address,
506                                     u16 collector_port,
507                                     ipfix_report_element_t *elts,
508                                     u32 n_elts, u32 *stream_index)
509 {
510   return snat_template_rewrite (frm, fr, collector_address, src_address,
511                                 collector_port, QUOTA_EXCEEDED,
512                                 MAX_FRAGMENTS_PENDING_REASSEMBLY);
513 }
514
515 u8 *
516 nat_template_rewrite_max_frags_ip6 (flow_report_main_t * frm,
517                                     flow_report_t * fr,
518                                     ip4_address_t * collector_address,
519                                     ip4_address_t * src_address,
520                                     u16 collector_port,
521                                     ipfix_report_element_t *elts,
522                                     u32 n_elts, u32 *stream_index)
523 {
524   return snat_template_rewrite (frm, fr, collector_address, src_address,
525                                 collector_port, QUOTA_EXCEEDED,
526                                 MAX_FRAGMENTS_PENDING_REASSEMBLY_IP6);
527 }
528
529 u8 *
530 nat_template_rewrite_nat64_bib (flow_report_main_t * frm,
531                                 flow_report_t * fr,
532                                 ip4_address_t * collector_address,
533                                 ip4_address_t * src_address,
534                                 u16 collector_port,
535                                 ipfix_report_element_t *elts,
536                                 u32 n_elts, u32 *stream_index)
537 {
538   return snat_template_rewrite (frm, fr, collector_address, src_address,
539                                 collector_port, NAT64_BIB_CREATE, 0);
540 }
541
542 u8 *
543 nat_template_rewrite_nat64_session (flow_report_main_t * frm,
544                                     flow_report_t * fr,
545                                     ip4_address_t * collector_address,
546                                     ip4_address_t * src_address,
547                                     u16 collector_port,
548                                     ipfix_report_element_t *elts,
549                                     u32 n_elts, u32 *stream_index)
550 {
551   return snat_template_rewrite (frm, fr, collector_address, src_address,
552                                 collector_port, NAT64_SESSION_CREATE, 0);
553 }
554
555 static inline void
556 snat_ipfix_header_create (flow_report_main_t * frm,
557                           vlib_buffer_t * b0, u32 * offset)
558 {
559   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
560   flow_report_stream_t *stream;
561   ip4_ipfix_template_packet_t *tp;
562   ipfix_message_header_t *h = 0;
563   ipfix_set_header_t *s = 0;
564   u32 sequence_number;
565   u32 stream_index;
566   ip4_header_t *ip;
567   udp_header_t *udp;
568   
569   stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
570   stream = &frm->streams[stream_index];
571
572   b0->current_data = 0;
573   b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
574     sizeof (*s);
575   b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_FLOW_REPORT);
576   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
577   vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
578   tp = vlib_buffer_get_current (b0);
579   ip = (ip4_header_t *) & tp->ip4;
580   udp = (udp_header_t *) (ip + 1);
581   h = (ipfix_message_header_t *) (udp + 1);
582   s = (ipfix_set_header_t *) (h + 1);
583
584   ip->ip_version_and_header_length = 0x45;
585   ip->ttl = 254;
586   ip->protocol = IP_PROTOCOL_UDP;
587   ip->flags_and_fragment_offset = 0;
588   ip->src_address.as_u32 = frm->src_address.as_u32;
589   ip->dst_address.as_u32 = frm->ipfix_collector.as_u32;
590   udp->src_port = clib_host_to_net_u16 (stream->src_port);
591   udp->dst_port = clib_host_to_net_u16 (frm->collector_port);
592   udp->checksum = 0;
593
594   h->export_time = clib_host_to_net_u32 ((u32)
595                                          (((f64) frm->unix_time_0) +
596                                           (vlib_time_now (frm->vlib_main) -
597                                            frm->vlib_time_0)));
598
599   sequence_number = clib_atomic_fetch_add (&stream->sequence_number, 1);
600   h->sequence_number = clib_host_to_net_u32 (sequence_number);
601   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
602
603   *offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
604 }
605
606 static inline void
607 snat_ipfix_send (flow_report_main_t * frm,
608                  vlib_frame_t * f, vlib_buffer_t * b0, u16 template_id)
609 {
610   ip4_ipfix_template_packet_t *tp;
611   ipfix_message_header_t *h = 0;
612   ipfix_set_header_t *s = 0;
613   ip4_header_t *ip;
614   udp_header_t *udp;
615   vlib_main_t *vm = frm->vlib_main;
616
617   tp = vlib_buffer_get_current (b0);
618   ip = (ip4_header_t *) & tp->ip4;
619   udp = (udp_header_t *) (ip + 1);
620   h = (ipfix_message_header_t *) (udp + 1);
621   s = (ipfix_set_header_t *) (h + 1);
622
623   s->set_id_length = ipfix_set_id_length (template_id,
624                                           b0->current_length -
625                                           (sizeof (*ip) + sizeof (*udp) +
626                                            sizeof (*h)));
627   h->version_length = version_length (b0->current_length -
628                                       (sizeof (*ip) + sizeof (*udp)));
629
630   ip->length = clib_host_to_net_u16 (b0->current_length);
631   ip->checksum = ip4_header_checksum (ip);
632   udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
633
634   if (frm->udp_checksum)
635     {
636       udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
637       if (udp->checksum == 0)
638         udp->checksum = 0xffff;
639     }
640
641   ASSERT (ip->checksum == ip4_header_checksum (ip));
642
643   vlib_put_frame_to_node (vm, ip4_lookup_node.index, f);
644 }
645
646 static void
647 snat_ipfix_logging_nat44_ses (u32 thread_index, u8 nat_event, u32 src_ip,
648                               u32 nat_src_ip, snat_protocol_t snat_proto,
649                               u16 src_port, u16 nat_src_port, u32 vrf_id,
650                               int do_flush)
651 {
652   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
653   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
654   flow_report_main_t *frm = &flow_report_main;
655   vlib_frame_t *f;
656   vlib_buffer_t *b0 = 0;
657   u32 bi0 = ~0;
658   u32 offset;
659   vlib_main_t *vm = frm->vlib_main;
660   u64 now;
661   u8 proto = ~0;
662   u16 template_id;
663
664   proto = snat_proto_to_ip_proto (snat_proto);
665
666   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
667   now += silm->milisecond_time_0;
668
669   b0 = sitd->nat44_session_buffer;
670
671   if (PREDICT_FALSE (b0 == 0))
672     {
673       if (do_flush)
674         return;
675
676       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
677         {
678           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
679           return;
680         }
681
682       b0 = sitd->nat44_session_buffer = vlib_get_buffer (vm, bi0);
683       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
684       offset = 0;
685     }
686   else
687     {
688       bi0 = vlib_get_buffer_index (vm, b0);
689       offset = sitd->nat44_session_next_record_offset;
690     }
691
692   f = sitd->nat44_session_frame;
693   if (PREDICT_FALSE (f == 0))
694     {
695       u32 *to_next;
696       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
697       sitd->nat44_session_frame = f;
698       to_next = vlib_frame_vector_args (f);
699       to_next[0] = bi0;
700       f->n_vectors = 1;
701     }
702
703   if (PREDICT_FALSE (offset == 0))
704     snat_ipfix_header_create (frm, b0, &offset);
705
706   if (PREDICT_TRUE (do_flush == 0))
707     {
708       u64 time_stamp = clib_host_to_net_u64 (now);
709       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
710       offset += sizeof (time_stamp);
711
712       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
713       offset += sizeof (nat_event);
714
715       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
716       offset += sizeof (src_ip);
717
718       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
719       offset += sizeof (nat_src_ip);
720
721       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
722       offset += sizeof (proto);
723
724       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
725       offset += sizeof (src_port);
726
727       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
728       offset += sizeof (nat_src_port);
729
730       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
731       offset += sizeof (vrf_id);
732
733       b0->current_length += NAT44_SESSION_CREATE_LEN;
734     }
735
736   if (PREDICT_FALSE
737       (do_flush || (offset + NAT44_SESSION_CREATE_LEN) > frm->path_mtu))
738     {
739       template_id = clib_atomic_fetch_or (
740         &silm->nat44_session_template_id,
741         0);
742       snat_ipfix_send (frm, f, b0, template_id);
743       sitd->nat44_session_frame = 0;
744       sitd->nat44_session_buffer = 0;
745       offset = 0;
746     }
747   sitd->nat44_session_next_record_offset = offset;
748 }
749
750 static void
751 snat_ipfix_logging_addr_exhausted (u32 thread_index, u32 pool_id, int do_flush)
752 {
753   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
754   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
755   flow_report_main_t *frm = &flow_report_main;
756   vlib_frame_t *f;
757   vlib_buffer_t *b0 = 0;
758   u32 bi0 = ~0;
759   u32 offset;
760   vlib_main_t *vm = frm->vlib_main;
761   u64 now;
762   u8 nat_event = NAT_ADDRESSES_EXHAUTED;
763   u16 template_id;
764
765   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
766   now += silm->milisecond_time_0;
767
768   b0 = sitd->addr_exhausted_buffer;
769
770   if (PREDICT_FALSE (b0 == 0))
771     {
772       if (do_flush)
773         return;
774
775       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
776         {
777           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
778           return;
779         }
780
781       b0 = sitd->addr_exhausted_buffer = vlib_get_buffer (vm, bi0);
782       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
783       offset = 0;
784     }
785   else
786     {
787       bi0 = vlib_get_buffer_index (vm, b0);
788       offset = sitd->addr_exhausted_next_record_offset;
789     }
790
791   f = sitd->addr_exhausted_frame;
792   if (PREDICT_FALSE (f == 0))
793     {
794       u32 *to_next;
795       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
796       sitd->addr_exhausted_frame = f;
797       to_next = vlib_frame_vector_args (f);
798       to_next[0] = bi0;
799       f->n_vectors = 1;
800     }
801
802   if (PREDICT_FALSE (offset == 0))
803     snat_ipfix_header_create (frm, b0, &offset);
804
805   if (PREDICT_TRUE (do_flush == 0))
806     {
807       u64 time_stamp = clib_host_to_net_u64 (now);
808       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
809       offset += sizeof (time_stamp);
810
811       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
812       offset += sizeof (nat_event);
813
814       clib_memcpy_fast (b0->data + offset, &pool_id, sizeof (pool_id));
815       offset += sizeof (pool_id);
816
817       b0->current_length += NAT_ADDRESSES_EXHAUTED_LEN;
818     }
819
820   if (PREDICT_FALSE
821       (do_flush || (offset + NAT_ADDRESSES_EXHAUTED_LEN) > frm->path_mtu))
822     {
823       template_id = clib_atomic_fetch_or (
824           &silm->addr_exhausted_template_id,
825           0);
826       snat_ipfix_send (frm, f, b0, template_id);
827       sitd->addr_exhausted_frame = 0;
828       sitd->addr_exhausted_buffer = 0;
829       offset = 0;
830     }
831   sitd->addr_exhausted_next_record_offset = offset;
832 }
833
834 static void
835 snat_ipfix_logging_max_entries_per_usr (u32 thread_index,
836                                         u32 limit, u32 src_ip, int do_flush)
837 {
838   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
839   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
840   flow_report_main_t *frm = &flow_report_main;
841   vlib_frame_t *f;
842   vlib_buffer_t *b0 = 0;
843   u32 bi0 = ~0;
844   u32 offset;
845   vlib_main_t *vm = frm->vlib_main;
846   u64 now;
847   u8 nat_event = QUOTA_EXCEEDED;
848   u32 quota_event = MAX_ENTRIES_PER_USER;
849   u16 template_id;
850
851   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
852   now += silm->milisecond_time_0;
853
854   b0 = sitd->max_entries_per_user_buffer;
855
856   if (PREDICT_FALSE (b0 == 0))
857     {
858       if (do_flush)
859         return;
860
861       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
862         {
863           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
864           return;
865         }
866
867       b0 = sitd->max_entries_per_user_buffer = vlib_get_buffer (vm, bi0);
868       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
869       offset = 0;
870     }
871   else
872     {
873       bi0 = vlib_get_buffer_index (vm, b0);
874       offset = sitd->max_entries_per_user_next_record_offset;
875     }
876
877   f = sitd->max_entries_per_user_frame;
878   if (PREDICT_FALSE (f == 0))
879     {
880       u32 *to_next;
881       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
882       sitd->max_entries_per_user_frame = f;
883       to_next = vlib_frame_vector_args (f);
884       to_next[0] = bi0;
885       f->n_vectors = 1;
886     }
887
888   if (PREDICT_FALSE (offset == 0))
889     snat_ipfix_header_create (frm, b0, &offset);
890
891   if (PREDICT_TRUE (do_flush == 0))
892     {
893       u64 time_stamp = clib_host_to_net_u64 (now);
894       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
895       offset += sizeof (time_stamp);
896
897       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
898       offset += sizeof (nat_event);
899
900       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
901       offset += sizeof (quota_event);
902
903       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
904       offset += sizeof (limit);
905
906       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
907       offset += sizeof (src_ip);
908
909       b0->current_length += MAX_ENTRIES_PER_USER_LEN;
910     }
911
912   if (PREDICT_FALSE
913       (do_flush || (offset + MAX_ENTRIES_PER_USER_LEN) > frm->path_mtu))
914     {
915       template_id = clib_atomic_fetch_or (
916           &silm->max_entries_per_user_template_id,
917           0);
918       snat_ipfix_send (frm, f, b0, template_id);
919       sitd->max_entries_per_user_frame = 0;
920       sitd->max_entries_per_user_buffer = 0;
921       offset = 0;
922     }
923   sitd->max_entries_per_user_next_record_offset = offset;
924 }
925
926 static void
927 nat_ipfix_logging_max_ses (u32 thread_index, u32 limit, int do_flush)
928 {
929   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
930   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
931   flow_report_main_t *frm = &flow_report_main;
932   vlib_frame_t *f;
933   vlib_buffer_t *b0 = 0;
934   u32 bi0 = ~0;
935   u32 offset;
936   vlib_main_t *vm = frm->vlib_main;
937   u64 now;
938   u8 nat_event = QUOTA_EXCEEDED;
939   u32 quota_event = MAX_SESSION_ENTRIES;
940   u16 template_id;
941
942   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
943   now += silm->milisecond_time_0;
944
945   b0 = sitd->max_sessions_buffer;
946
947   if (PREDICT_FALSE (b0 == 0))
948     {
949       if (do_flush)
950         return;
951
952       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
953         {
954           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
955           return;
956         }
957
958       b0 = sitd->max_sessions_buffer = vlib_get_buffer (vm, bi0);
959       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
960       offset = 0;
961     }
962   else
963     {
964       bi0 = vlib_get_buffer_index (vm, b0);
965       offset = sitd->max_sessions_next_record_offset;
966     }
967
968   f = sitd->max_sessions_frame;
969   if (PREDICT_FALSE (f == 0))
970     {
971       u32 *to_next;
972       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
973       sitd->max_sessions_frame = f;
974       to_next = vlib_frame_vector_args (f);
975       to_next[0] = bi0;
976       f->n_vectors = 1;
977     }
978
979   if (PREDICT_FALSE (offset == 0))
980     snat_ipfix_header_create (frm, b0, &offset);
981
982   if (PREDICT_TRUE (do_flush == 0))
983     {
984       u64 time_stamp = clib_host_to_net_u64 (now);
985       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
986       offset += sizeof (time_stamp);
987
988       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
989       offset += sizeof (nat_event);
990
991       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
992       offset += sizeof (quota_event);
993
994       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
995       offset += sizeof (limit);
996
997       b0->current_length += MAX_SESSIONS_LEN;
998     }
999
1000   if (PREDICT_FALSE
1001       (do_flush || (offset + MAX_SESSIONS_LEN) > frm->path_mtu))
1002     {
1003       template_id = clib_atomic_fetch_or (
1004         &silm->max_sessions_template_id,
1005         0);
1006       snat_ipfix_send (frm, f, b0, template_id);
1007       sitd->max_sessions_frame = 0;
1008       sitd->max_sessions_buffer = 0;
1009       offset = 0;
1010     }
1011   sitd->max_sessions_next_record_offset = offset;
1012 }
1013
1014 static void
1015 nat_ipfix_logging_max_bib (u32 thread_index, u32 limit, int do_flush)
1016 {
1017   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1018   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1019   flow_report_main_t *frm = &flow_report_main;
1020   vlib_frame_t *f;
1021   vlib_buffer_t *b0 = 0;
1022   u32 bi0 = ~0;
1023   u32 offset;
1024   vlib_main_t *vm = frm->vlib_main;
1025   u64 now;
1026   u8 nat_event = QUOTA_EXCEEDED;
1027   u32 quota_event = MAX_BIB_ENTRIES;
1028   u16 template_id;
1029
1030   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1031   now += silm->milisecond_time_0;
1032
1033   b0 = sitd->max_bibs_buffer;
1034
1035   if (PREDICT_FALSE (b0 == 0))
1036     {
1037       if (do_flush)
1038         return;
1039
1040       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1041         {
1042           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1043           return;
1044         }
1045
1046       b0 = sitd->max_bibs_buffer = vlib_get_buffer (vm, bi0);
1047       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1048       offset = 0;
1049     }
1050   else
1051     {
1052       bi0 = vlib_get_buffer_index (vm, b0);
1053       offset = sitd->max_bibs_next_record_offset;
1054     }
1055
1056   f = sitd->max_bibs_frame;
1057   if (PREDICT_FALSE (f == 0))
1058     {
1059       u32 *to_next;
1060       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1061       sitd->max_bibs_frame = f;
1062       to_next = vlib_frame_vector_args (f);
1063       to_next[0] = bi0;
1064       f->n_vectors = 1;
1065     }
1066
1067   if (PREDICT_FALSE (offset == 0))
1068     snat_ipfix_header_create (frm, b0, &offset);
1069
1070   if (PREDICT_TRUE (do_flush == 0))
1071     {
1072       u64 time_stamp = clib_host_to_net_u64 (now);
1073       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1074       offset += sizeof (time_stamp);
1075
1076       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1077       offset += sizeof (nat_event);
1078
1079       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1080       offset += sizeof (quota_event);
1081
1082       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
1083       offset += sizeof (limit);
1084
1085       b0->current_length += MAX_BIBS_LEN;
1086     }
1087
1088   if (PREDICT_FALSE
1089       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1090     {
1091       template_id = clib_atomic_fetch_or (
1092         &silm->max_bibs_template_id,
1093         0);
1094       snat_ipfix_send (frm, f, b0, template_id);
1095       sitd->max_bibs_frame = 0;
1096       sitd->max_bibs_buffer = 0;
1097       offset = 0;
1098     }
1099   sitd->max_bibs_next_record_offset = offset;
1100 }
1101
1102 static void
1103 nat_ipfix_logging_max_frag_ip4 (u32 thread_index,
1104                                 u32 limit, u32 src, int do_flush)
1105 {
1106   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1107   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1108   flow_report_main_t *frm = &flow_report_main;
1109   vlib_frame_t *f;
1110   vlib_buffer_t *b0 = 0;
1111   u32 bi0 = ~0;
1112   u32 offset;
1113   vlib_main_t *vm = frm->vlib_main;
1114   u64 now;
1115   u8 nat_event = QUOTA_EXCEEDED;
1116   u32 quota_event = MAX_FRAGMENTS_PENDING_REASSEMBLY;
1117   u16 template_id;
1118
1119   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1120   now += silm->milisecond_time_0;
1121
1122   b0 = sitd->max_frags_ip4_buffer;
1123
1124   if (PREDICT_FALSE (b0 == 0))
1125     {
1126       if (do_flush)
1127         return;
1128
1129       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1130         {
1131           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1132           return;
1133         }
1134
1135       b0 = sitd->max_frags_ip4_buffer = vlib_get_buffer (vm, bi0);
1136       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1137       offset = 0;
1138     }
1139   else
1140     {
1141       bi0 = vlib_get_buffer_index (vm, b0);
1142       offset = sitd->max_frags_ip4_next_record_offset;
1143     }
1144
1145   f = sitd->max_frags_ip4_frame;
1146   if (PREDICT_FALSE (f == 0))
1147     {
1148       u32 *to_next;
1149       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1150       sitd->max_frags_ip4_frame = f;
1151       to_next = vlib_frame_vector_args (f);
1152       to_next[0] = bi0;
1153       f->n_vectors = 1;
1154     }
1155
1156   if (PREDICT_FALSE (offset == 0))
1157     snat_ipfix_header_create (frm, b0, &offset);
1158
1159   if (PREDICT_TRUE (do_flush == 0))
1160     {
1161       u64 time_stamp = clib_host_to_net_u64 (now);
1162       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1163       offset += sizeof (time_stamp);
1164
1165       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1166       offset += sizeof (nat_event);
1167
1168       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1169       offset += sizeof (quota_event);
1170
1171       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
1172       offset += sizeof (limit);
1173
1174       clib_memcpy_fast (b0->data + offset, &src, sizeof (src));
1175       offset += sizeof (src);
1176
1177       b0->current_length += MAX_FRAGMENTS_IP4_LEN;
1178     }
1179
1180   if (PREDICT_FALSE
1181       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1182     {
1183       template_id = clib_atomic_fetch_or (
1184         &silm->max_frags_ip4_template_id,
1185         0);
1186       snat_ipfix_send (frm, f, b0, template_id);
1187       sitd->max_frags_ip4_frame = 0;
1188       sitd->max_frags_ip4_buffer = 0;
1189       offset = 0;
1190     }
1191   sitd->max_frags_ip4_next_record_offset = offset;
1192 }
1193
1194 static void
1195 nat_ipfix_logging_max_frag_ip6 (u32 thread_index,
1196                                 u32 limit, ip6_address_t * src, int do_flush)
1197 {
1198   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1199   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1200   flow_report_main_t *frm = &flow_report_main;
1201   vlib_frame_t *f;
1202   vlib_buffer_t *b0 = 0;
1203   u32 bi0 = ~0;
1204   u32 offset;
1205   vlib_main_t *vm = frm->vlib_main;
1206   u64 now;
1207   u8 nat_event = QUOTA_EXCEEDED;
1208   u32 quota_event = MAX_FRAGMENTS_PENDING_REASSEMBLY;
1209   u16 template_id;
1210
1211   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1212   now += silm->milisecond_time_0;
1213
1214   b0 = sitd->max_frags_ip6_buffer;
1215
1216   if (PREDICT_FALSE (b0 == 0))
1217     {
1218       if (do_flush)
1219         return;
1220
1221       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1222         {
1223           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1224           return;
1225         }
1226
1227       b0 = sitd->max_frags_ip6_buffer = vlib_get_buffer (vm, bi0);
1228       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1229       offset = 0;
1230     }
1231   else
1232     {
1233       bi0 = vlib_get_buffer_index (vm, b0);
1234       offset = sitd->max_frags_ip6_next_record_offset;
1235     }
1236
1237   f = sitd->max_frags_ip6_frame;
1238   if (PREDICT_FALSE (f == 0))
1239     {
1240       u32 *to_next;
1241       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1242       sitd->max_frags_ip6_frame = f;
1243       to_next = vlib_frame_vector_args (f);
1244       to_next[0] = bi0;
1245       f->n_vectors = 1;
1246     }
1247
1248   if (PREDICT_FALSE (offset == 0))
1249     snat_ipfix_header_create (frm, b0, &offset);
1250
1251   if (PREDICT_TRUE (do_flush == 0))
1252     {
1253       u64 time_stamp = clib_host_to_net_u64 (now);
1254       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1255       offset += sizeof (time_stamp);
1256
1257       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1258       offset += sizeof (nat_event);
1259
1260       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1261       offset += sizeof (quota_event);
1262
1263       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
1264       offset += sizeof (limit);
1265
1266       clib_memcpy_fast (b0->data + offset, src, sizeof (ip6_address_t));
1267       offset += sizeof (ip6_address_t);
1268
1269       b0->current_length += MAX_FRAGMENTS_IP6_LEN;
1270     }
1271
1272   if (PREDICT_FALSE
1273       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1274     {
1275       template_id = clib_atomic_fetch_or (
1276         &silm->max_frags_ip6_template_id,
1277         0);
1278       snat_ipfix_send (frm, f, b0, template_id);
1279       sitd->max_frags_ip6_frame = 0;
1280       sitd->max_frags_ip6_buffer = 0;
1281       offset = 0;
1282     }
1283   sitd->max_frags_ip6_next_record_offset = offset;
1284 }
1285
1286 static void
1287 nat_ipfix_logging_nat64_bibe (u32 thread_index, u8 nat_event,
1288                               ip6_address_t * src_ip, u32 nat_src_ip,
1289                               u8 proto, u16 src_port, u16 nat_src_port,
1290                               u32 vrf_id, int do_flush)
1291 {
1292   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1293   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1294   flow_report_main_t *frm = &flow_report_main;
1295   vlib_frame_t *f;
1296   vlib_buffer_t *b0 = 0;
1297   u32 bi0 = ~0;
1298   u32 offset;
1299   vlib_main_t *vm = frm->vlib_main;
1300   u64 now;
1301   u16 template_id;
1302
1303   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1304   now += silm->milisecond_time_0;
1305
1306   b0 = sitd->nat64_bib_buffer;
1307
1308   if (PREDICT_FALSE (b0 == 0))
1309     {
1310       if (do_flush)
1311         return;
1312
1313       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1314         {
1315           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1316           return;
1317         }
1318
1319       b0 = sitd->nat64_bib_buffer = vlib_get_buffer (vm, bi0);
1320       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1321       offset = 0;
1322     }
1323   else
1324     {
1325       bi0 = vlib_get_buffer_index (vm, b0);
1326       offset = sitd->nat64_bib_next_record_offset;
1327     }
1328
1329   f = sitd->nat64_bib_frame;
1330   if (PREDICT_FALSE (f == 0))
1331     {
1332       u32 *to_next;
1333       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1334       sitd->nat64_bib_frame = f;
1335       to_next = vlib_frame_vector_args (f);
1336       to_next[0] = bi0;
1337       f->n_vectors = 1;
1338     }
1339
1340   if (PREDICT_FALSE (offset == 0))
1341     snat_ipfix_header_create (frm, b0, &offset);
1342
1343   if (PREDICT_TRUE (do_flush == 0))
1344     {
1345       u64 time_stamp = clib_host_to_net_u64 (now);
1346       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1347       offset += sizeof (time_stamp);
1348
1349       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1350       offset += sizeof (nat_event);
1351
1352       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1353       offset += sizeof (ip6_address_t);
1354
1355       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1356       offset += sizeof (nat_src_ip);
1357
1358       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1359       offset += sizeof (proto);
1360
1361       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1362       offset += sizeof (src_port);
1363
1364       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1365       offset += sizeof (nat_src_port);
1366
1367       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1368       offset += sizeof (vrf_id);
1369
1370       b0->current_length += NAT64_BIB_LEN;
1371     }
1372
1373   if (PREDICT_FALSE
1374       (do_flush || (offset + NAT64_BIB_LEN) > frm->path_mtu))
1375     {
1376       template_id = clib_atomic_fetch_or (
1377         &silm->nat64_bib_template_id,
1378         0);
1379       snat_ipfix_send (frm, f, b0, template_id);
1380       sitd->nat64_bib_frame = 0;
1381       sitd->nat64_bib_buffer = 0;
1382       offset = 0;
1383     }
1384   sitd->nat64_bib_next_record_offset = offset;
1385 }
1386
1387 static void
1388 nat_ipfix_logging_nat64_ses (u32 thread_index, u8 nat_event,
1389                              ip6_address_t * src_ip, u32 nat_src_ip,
1390                              u8 proto, u16 src_port, u16 nat_src_port,
1391                              ip6_address_t * dst_ip, u32 nat_dst_ip,
1392                              u16 dst_port, u16 nat_dst_port,
1393                              u32 vrf_id, int do_flush)
1394 {
1395   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1396   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1397   flow_report_main_t *frm = &flow_report_main;
1398   vlib_frame_t *f;
1399   vlib_buffer_t *b0 = 0;
1400   u32 bi0 = ~0;
1401   u32 offset;
1402   vlib_main_t *vm = frm->vlib_main;
1403   u64 now;
1404   u16 template_id;
1405
1406   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1407   now += silm->milisecond_time_0;
1408
1409   b0 = sitd->nat64_ses_buffer;
1410
1411   if (PREDICT_FALSE (b0 == 0))
1412     {
1413       if (do_flush)
1414         return;
1415
1416       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1417         {
1418           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1419           return;
1420         }
1421
1422       b0 = sitd->nat64_ses_buffer = vlib_get_buffer (vm, bi0);
1423       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1424       offset = 0;
1425     }
1426   else
1427     {
1428       bi0 = vlib_get_buffer_index (vm, b0);
1429       offset = sitd->nat64_ses_next_record_offset;
1430     }
1431
1432   f = sitd->nat64_ses_frame;
1433   if (PREDICT_FALSE (f == 0))
1434     {
1435       u32 *to_next;
1436       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1437       sitd->nat64_ses_frame = f;
1438       to_next = vlib_frame_vector_args (f);
1439       to_next[0] = bi0;
1440       f->n_vectors = 1;
1441     }
1442
1443   if (PREDICT_FALSE (offset == 0))
1444     snat_ipfix_header_create (frm, b0, &offset);
1445
1446   if (PREDICT_TRUE (do_flush == 0))
1447     {
1448       u64 time_stamp = clib_host_to_net_u64 (now);
1449       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1450       offset += sizeof (time_stamp);
1451
1452       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1453       offset += sizeof (nat_event);
1454
1455       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1456       offset += sizeof (ip6_address_t);
1457
1458       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1459       offset += sizeof (nat_src_ip);
1460
1461       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1462       offset += sizeof (proto);
1463
1464       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1465       offset += sizeof (src_port);
1466
1467       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1468       offset += sizeof (nat_src_port);
1469
1470       clib_memcpy_fast (b0->data + offset, dst_ip, sizeof (ip6_address_t));
1471       offset += sizeof (ip6_address_t);
1472
1473       clib_memcpy_fast (b0->data + offset, &nat_dst_ip, sizeof (nat_dst_ip));
1474       offset += sizeof (nat_dst_ip);
1475
1476       clib_memcpy_fast (b0->data + offset, &dst_port, sizeof (dst_port));
1477       offset += sizeof (dst_port);
1478
1479       clib_memcpy_fast (b0->data + offset, &nat_dst_port, sizeof (nat_dst_port));
1480       offset += sizeof (nat_dst_port);
1481
1482       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1483       offset += sizeof (vrf_id);
1484
1485       b0->current_length += NAT64_SES_LEN;
1486     }
1487
1488   if (PREDICT_FALSE
1489       (do_flush || (offset + NAT64_SES_LEN) > frm->path_mtu))
1490     {
1491       template_id = clib_atomic_fetch_or (
1492         &silm->nat64_ses_template_id,
1493         0);
1494       snat_ipfix_send (frm, f, b0, template_id);
1495       sitd->nat64_ses_frame = 0;
1496       sitd->nat64_ses_buffer = 0;
1497       offset = 0;
1498     }
1499   sitd->nat64_ses_next_record_offset = offset;
1500 }
1501
1502 void
1503 snat_ipfix_flush (u32 thread_index)
1504 {
1505   int do_flush = 1;
1506
1507   snat_ipfix_logging_nat44_ses (thread_index,
1508                                 0, 0, 0, 0, 0, 0, 0, do_flush);
1509   snat_ipfix_logging_addr_exhausted (thread_index, 0, do_flush);
1510   snat_ipfix_logging_max_entries_per_usr (thread_index, 0, 0, do_flush);
1511   nat_ipfix_logging_max_ses (thread_index, 0, do_flush);
1512   nat_ipfix_logging_max_bib (thread_index, 0, do_flush);
1513   nat_ipfix_logging_max_frag_ip4 (thread_index, 0, 0, do_flush);
1514   nat_ipfix_logging_max_frag_ip6 (thread_index, 0, 0, do_flush);
1515   nat_ipfix_logging_nat64_bibe (thread_index,
1516                                 0, 0, 0, 0, 0, 0, 0, do_flush);
1517   nat_ipfix_logging_nat64_ses (thread_index,
1518                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, do_flush);
1519 }
1520
1521 void
1522 snat_ipfix_flush_from_main (void)
1523 {
1524   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1525   vlib_main_t *worker_vm;
1526   int i;
1527
1528   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))
1529     return;
1530
1531   if (PREDICT_FALSE (!silm->worker_vms))
1532     {
1533       for (i = 1; i < vec_len (vlib_mains); i++)
1534         {
1535           worker_vm = vlib_mains[i];
1536           if (worker_vm)
1537             vec_add1 (silm->worker_vms, worker_vm);
1538         }
1539     }
1540
1541   /* Trigger flush for each worker thread */
1542   for (i = 0; i < vec_len (silm->worker_vms); i++)
1543     {
1544       worker_vm = silm->worker_vms[i];
1545       if (worker_vm)
1546         vlib_node_set_interrupt_pending (worker_vm,
1547                                          snat_ipfix_flush_node.index);
1548     }
1549
1550   /* Finally flush main thread */
1551   snat_ipfix_flush (0);
1552 }
1553
1554 /**
1555  * @brief Generate NAT44 session create event
1556  *
1557  * @param thread_index thread index
1558  * @param src_ip       source IPv4 address
1559  * @param nat_src_ip   transaltes source IPv4 address
1560  * @param snat_proto   NAT transport protocol
1561  * @param src_port     source port
1562  * @param nat_src_port translated source port
1563  * @param vrf_id       VRF ID
1564  */
1565 void
1566 snat_ipfix_logging_nat44_ses_create (u32 thread_index,
1567                                      u32 src_ip,
1568                                      u32 nat_src_ip,
1569                                      snat_protocol_t snat_proto,
1570                                      u16 src_port,
1571                                      u16 nat_src_port, u32 vrf_id)
1572 {
1573   skip_if_disabled ();
1574
1575   snat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_CREATE, src_ip,
1576                                 nat_src_ip, snat_proto, src_port, nat_src_port,
1577                                 vrf_id, 0);
1578 }
1579
1580 /**
1581  * @brief Generate NAT44 session delete event
1582  *
1583  * @param thread_index thread index
1584  * @param src_ip       source IPv4 address
1585  * @param nat_src_ip   transaltes source IPv4 address
1586  * @param snat_proto   NAT transport protocol
1587  * @param src_port     source port
1588  * @param nat_src_port translated source port
1589  * @param vrf_id       VRF ID
1590  */
1591 void
1592 snat_ipfix_logging_nat44_ses_delete (u32 thread_index,
1593                                      u32 src_ip,
1594                                      u32 nat_src_ip,
1595                                      snat_protocol_t snat_proto,
1596                                      u16 src_port,
1597                                      u16 nat_src_port, u32 vrf_id)
1598 {
1599   skip_if_disabled ();
1600
1601   snat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_DELETE, src_ip,
1602                                 nat_src_ip, snat_proto, src_port, nat_src_port,
1603                                 vrf_id, 0);
1604 }
1605
1606 /**
1607  * @brief Generate NAT addresses exhausted event
1608  *
1609  * @param thread_index thread index
1610  * @param pool_id NAT pool ID
1611  */
1612 void
1613 snat_ipfix_logging_addresses_exhausted (u32 thread_index, u32 pool_id)
1614 {
1615   //TODO: This event SHOULD be rate limited
1616   skip_if_disabled ();
1617
1618   snat_ipfix_logging_addr_exhausted (thread_index, pool_id, 0);
1619 }
1620
1621 /**
1622  * @brief Generate maximum entries per user exceeded event
1623  *
1624  * @param thread_index thread index
1625  * @param limit maximum NAT entries that can be created per user
1626  * @param src_ip source IPv4 address
1627  */
1628 void
1629 snat_ipfix_logging_max_entries_per_user (u32 thread_index, u32 limit, u32 src_ip)
1630 {
1631   //TODO: This event SHOULD be rate limited
1632   skip_if_disabled ();
1633
1634   snat_ipfix_logging_max_entries_per_usr (thread_index, limit, src_ip, 0);
1635 }
1636
1637 vlib_frame_t *
1638 deterministic_nat_data_callback
1639 (flow_report_main_t * frm,
1640                                         flow_report_t * fr,
1641                                         vlib_frame_t * f,
1642                                         u32 * to_next, u32 node_index)
1643 {
1644   snat_ipfix_flush_from_main();
1645
1646   return f;
1647 }
1648
1649 /**
1650  * @brief Generate maximum session entries exceeded event
1651  *
1652  * @param thread_index thread index
1653  * @param limit configured limit
1654  */
1655 void
1656 nat_ipfix_logging_max_sessions (u32 thread_index, u32 limit)
1657 {
1658   //TODO: This event SHOULD be rate limited
1659   skip_if_disabled ();
1660
1661   nat_ipfix_logging_max_ses (thread_index, limit, 0);
1662 }
1663
1664 /**
1665  * @brief Generate maximum BIB entries exceeded event
1666  *
1667  * @param thread_index thread index
1668  * @param limit configured limit
1669  */
1670 void
1671 nat_ipfix_logging_max_bibs (u32 thread_index, u32 limit)
1672 {
1673   //TODO: This event SHOULD be rate limited
1674   skip_if_disabled ();
1675
1676   nat_ipfix_logging_max_bib (thread_index, limit, 0);
1677 }
1678
1679 /**
1680  * @brief Generate maximum IPv4 fragments pending reassembly exceeded event
1681  *
1682  * @param thread_index thread index
1683  * @param limit configured limit
1684  * @param src source IPv4 address
1685  */
1686 void
1687 nat_ipfix_logging_max_fragments_ip4 (u32 thread_index,
1688                                      u32 limit, ip4_address_t * src)
1689 {
1690   //TODO: This event SHOULD be rate limited
1691   skip_if_disabled ();
1692
1693   nat_ipfix_logging_max_frag_ip4 (thread_index, limit, src->as_u32, 0);
1694 }
1695
1696 /**
1697  * @brief Generate maximum IPv6 fragments pending reassembly exceeded event
1698  *
1699  * @param thread_index thread index
1700  * @param limit configured limit
1701  * @param src source IPv6 address
1702  */
1703 void
1704 nat_ipfix_logging_max_fragments_ip6 (u32 thread_index,
1705                                      u32 limit, ip6_address_t * src)
1706 {
1707   //TODO: This event SHOULD be rate limited
1708   skip_if_disabled ();
1709
1710   nat_ipfix_logging_max_frag_ip6 (thread_index, limit, src, 0);
1711 }
1712
1713 /**
1714  * @brief Generate NAT64 BIB create and delete events
1715  *
1716  * @param thread_index thread index
1717  * @param src_ip       source IPv6 address
1718  * @param nat_src_ip   transaltes source IPv4 address
1719  * @param proto        L4 protocol
1720  * @param src_port     source port
1721  * @param nat_src_port translated source port
1722  * @param vrf_id       VRF ID
1723  * @param is_create    non-zero value if create event otherwise delete event
1724  */
1725 void
1726 nat_ipfix_logging_nat64_bib (u32 thread_index, ip6_address_t * src_ip,
1727                              ip4_address_t * nat_src_ip, u8 proto,
1728                              u16 src_port, u16 nat_src_port, u32 vrf_id,
1729                              u8 is_create)
1730 {
1731   u8 nat_event;
1732
1733   skip_if_disabled ();
1734
1735   nat_event = is_create ? NAT64_BIB_CREATE : NAT64_BIB_DELETE;
1736
1737   nat_ipfix_logging_nat64_bibe (thread_index, nat_event, src_ip,
1738                                 nat_src_ip->as_u32, proto, src_port,
1739                                 nat_src_port, vrf_id, 0);
1740 }
1741
1742 /**
1743  * @brief Generate NAT64 session create and delete events
1744  *
1745  * @param thread_index thread index
1746  * @param src_ip       source IPv6 address
1747  * @param nat_src_ip   transaltes source IPv4 address
1748  * @param proto        L4 protocol
1749  * @param src_port     source port
1750  * @param nat_src_port translated source port
1751  * @param dst_ip       destination IPv6 address
1752  * @param nat_dst_ip   destination IPv4 address
1753  * @param dst_port     destination port
1754  * @param nat_dst_port translated destination port
1755  * @param vrf_id       VRF ID
1756  * @param is_create    non-zero value if create event otherwise delete event
1757  */
1758 void
1759 nat_ipfix_logging_nat64_session (u32 thread_index,
1760                                  ip6_address_t * src_ip,
1761                                  ip4_address_t * nat_src_ip, u8 proto,
1762                                  u16 src_port, u16 nat_src_port,
1763                                  ip6_address_t * dst_ip,
1764                                  ip4_address_t * nat_dst_ip, u16 dst_port,
1765                                  u16 nat_dst_port, u32 vrf_id, u8 is_create)
1766 {
1767   u8 nat_event;
1768
1769   skip_if_disabled ();
1770
1771   nat_event = is_create ? NAT64_SESSION_CREATE : NAT64_SESSION_DELETE;
1772
1773   nat_ipfix_logging_nat64_ses (thread_index, nat_event, src_ip,
1774                                nat_src_ip->as_u32, proto, src_port,
1775                                nat_src_port, dst_ip, nat_dst_ip->as_u32,
1776                                dst_port, nat_dst_port, vrf_id, 0);
1777 }
1778
1779 vlib_frame_t *
1780 data_callback (flow_report_main_t * frm, flow_report_t * fr,
1781                vlib_frame_t * f, u32 * to_next, u32 node_index)
1782 {
1783   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1784
1785   if (PREDICT_FALSE (++silm->call_counter >= vec_len (frm->reports)))
1786     {
1787       snat_ipfix_flush_from_main();
1788       silm->call_counter = 0;
1789     }
1790
1791   return f;
1792 }
1793
1794 /**
1795  * @brief Enable/disable NAT plugin IPFIX logging
1796  *
1797  * @param enable    1 if enable, 0 if disable
1798  * @param domain_id observation domain ID
1799  * @param src_port  source port number
1800  *
1801  * @returns 0 if success
1802  */
1803 int
1804 snat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
1805 {
1806   snat_main_t *sm = &snat_main;
1807   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1808   flow_report_main_t *frm = &flow_report_main;
1809   vnet_flow_report_add_del_args_t a;
1810   int rv;
1811   u8 e = enable ? 1 : 0;
1812
1813   if (clib_atomic_cmp_and_swap (&silm->enabled, e ^ 1, e) == e)
1814     return 0;
1815
1816   clib_memset (&a, 0, sizeof (a));
1817   a.is_add = enable;
1818   a.domain_id = domain_id ? domain_id : 1;
1819   a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
1820   a.flow_data_callback = data_callback;
1821
1822   if (sm->deterministic)
1823     {
1824       a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
1825
1826       rv = vnet_flow_report_add_del (frm, &a, NULL);
1827       if (rv)
1828         {
1829           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1830           return -1;
1831         }
1832     }
1833   else
1834     {
1835       a.rewrite_callback = snat_template_rewrite_nat44_session;
1836
1837       rv = vnet_flow_report_add_del (frm, &a, NULL);
1838       if (rv)
1839         {
1840           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1841           return -1;
1842         }
1843
1844       a.rewrite_callback = snat_template_rewrite_addr_exhausted;
1845
1846       rv = vnet_flow_report_add_del (frm, &a, NULL);
1847       if (rv)
1848         {
1849           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1850           return -1;
1851         }
1852
1853       a.rewrite_callback = nat_template_rewrite_max_sessions;
1854
1855       rv = vnet_flow_report_add_del (frm, &a, NULL);
1856       if (rv)
1857         {
1858           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1859           return -1;
1860         }
1861
1862       a.rewrite_callback = nat_template_rewrite_max_bibs;
1863
1864       rv = vnet_flow_report_add_del (frm, &a, NULL);
1865       if (rv)
1866         {
1867           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1868           return -1;
1869         }
1870
1871       a.rewrite_callback = nat_template_rewrite_max_frags_ip4;
1872
1873       rv = vnet_flow_report_add_del (frm, &a, NULL);
1874       if (rv)
1875         {
1876           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1877           return -1;
1878         }
1879
1880       a.rewrite_callback = nat_template_rewrite_max_frags_ip6;
1881
1882       rv = vnet_flow_report_add_del (frm, &a, NULL);
1883       if (rv)
1884         {
1885           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1886           return -1;
1887         }
1888
1889       a.rewrite_callback = nat_template_rewrite_nat64_bib;
1890
1891       rv = vnet_flow_report_add_del (frm, &a, NULL);
1892       if (rv)
1893         {
1894           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1895           return -1;
1896         }
1897
1898       a.rewrite_callback = nat_template_rewrite_nat64_session;
1899
1900       rv = vnet_flow_report_add_del (frm, &a, NULL);
1901       if (rv)
1902         {
1903           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1904           return -1;
1905         }
1906
1907       if (sm->endpoint_dependent)
1908         {
1909           a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
1910
1911           rv = vnet_flow_report_add_del (frm, &a, NULL);
1912           if (rv)
1913             {
1914               nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1915               return -1;
1916             }
1917         }
1918     }
1919
1920   return 0;
1921 }
1922
1923 /**
1924  * @brief Initialize NAT plugin IPFIX logging
1925  *
1926  * @param vm vlib main
1927  */
1928 void
1929 snat_ipfix_logging_init (vlib_main_t * vm)
1930 {
1931   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1932   vlib_thread_main_t *tm = vlib_get_thread_main ();
1933
1934   silm->enabled = 0;
1935   silm->worker_vms = 0;
1936   silm->call_counter = 0;
1937
1938   /* Set up time reference pair */
1939   silm->vlib_time_0 = vlib_time_now (vm);
1940   silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
1941
1942   vec_validate (silm->per_thread_data, tm->n_vlib_mains - 1);
1943 }
1944
1945 static uword
1946 ipfix_flush_process (vlib_main_t *vm,
1947                      vlib_node_runtime_t *rt,
1948                      vlib_frame_t *f)
1949 {
1950   snat_ipfix_flush(vm->thread_index);
1951   return 0;
1952 }
1953
1954 /* *INDENT-OFF* */
1955 VLIB_REGISTER_NODE (snat_ipfix_flush_node) = {
1956   .function = ipfix_flush_process,
1957   .name = "snat-ipfix-flush",
1958   .type = VLIB_NODE_TYPE_INPUT,
1959   .state = VLIB_NODE_STATE_INTERRUPT,
1960 };
1961 /* *INDENT-ON* */