nat: remove unused code
[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     }
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 = src_address->as_u32;
242   ip->dst_address.as_u32 = collector_address->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 snat_template_rewrite_addr_exhausted (flow_report_main_t * frm,
391                                       flow_report_t * fr,
392                                       ip4_address_t * collector_address,
393                                       ip4_address_t * src_address,
394                                       u16 collector_port,
395                                       ipfix_report_element_t *elts,
396                                       u32 n_elts, u32 *stream_index)
397 {
398   return snat_template_rewrite (frm, fr, collector_address, src_address,
399                                 collector_port, NAT_ADDRESSES_EXHAUTED, 0);
400 }
401
402 u8 *
403 snat_template_rewrite_nat44_session (flow_report_main_t * frm,
404                                      flow_report_t * fr,
405                                      ip4_address_t * collector_address,
406                                      ip4_address_t * src_address,
407                                      u16 collector_port,
408                                      ipfix_report_element_t *elts,
409                                      u32 n_elts, u32 *stream_index)
410 {
411   return snat_template_rewrite (frm, fr, collector_address, src_address,
412                                 collector_port, NAT44_SESSION_CREATE, 0);
413 }
414
415 u8 *
416 snat_template_rewrite_max_entries_per_usr (flow_report_main_t * frm,
417                                            flow_report_t * fr,
418                                            ip4_address_t * collector_address,
419                                            ip4_address_t * src_address,
420                                            u16 collector_port,
421                                            ipfix_report_element_t *elts,
422                                            u32 n_elts, u32 *stream_index)
423 {
424   return snat_template_rewrite (frm, fr, collector_address, src_address,
425                                 collector_port, QUOTA_EXCEEDED,
426                                 MAX_ENTRIES_PER_USER);
427 }
428
429 u8 *
430 nat_template_rewrite_max_sessions (flow_report_main_t * frm,
431                                    flow_report_t * fr,
432                                    ip4_address_t * collector_address,
433                                    ip4_address_t * src_address,
434                                    u16 collector_port,
435                                    ipfix_report_element_t *elts,
436                                    u32 n_elts, u32 *stream_index)
437 {
438   return snat_template_rewrite (frm, fr, collector_address, src_address,
439                                 collector_port, QUOTA_EXCEEDED,
440                                 MAX_SESSION_ENTRIES);
441 }
442
443 u8 *
444 nat_template_rewrite_max_bibs (flow_report_main_t * frm,
445                                flow_report_t * fr,
446                                ip4_address_t * collector_address,
447                                ip4_address_t * src_address,
448                                u16 collector_port,
449                                ipfix_report_element_t *elts,
450                                u32 n_elts, u32 *stream_index)
451 {
452   return snat_template_rewrite (frm, fr, collector_address, src_address,
453                                 collector_port, QUOTA_EXCEEDED,
454                                 MAX_BIB_ENTRIES);
455 }
456
457 u8 *
458 nat_template_rewrite_nat64_bib (flow_report_main_t * frm,
459                                 flow_report_t * fr,
460                                 ip4_address_t * collector_address,
461                                 ip4_address_t * src_address,
462                                 u16 collector_port,
463                                 ipfix_report_element_t *elts,
464                                 u32 n_elts, u32 *stream_index)
465 {
466   return snat_template_rewrite (frm, fr, collector_address, src_address,
467                                 collector_port, NAT64_BIB_CREATE, 0);
468 }
469
470 u8 *
471 nat_template_rewrite_nat64_session (flow_report_main_t * frm,
472                                     flow_report_t * fr,
473                                     ip4_address_t * collector_address,
474                                     ip4_address_t * src_address,
475                                     u16 collector_port,
476                                     ipfix_report_element_t *elts,
477                                     u32 n_elts, u32 *stream_index)
478 {
479   return snat_template_rewrite (frm, fr, collector_address, src_address,
480                                 collector_port, NAT64_SESSION_CREATE, 0);
481 }
482
483 static inline void
484 snat_ipfix_header_create (flow_report_main_t * frm,
485                           vlib_buffer_t * b0, u32 * offset)
486 {
487   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
488   flow_report_stream_t *stream;
489   ip4_ipfix_template_packet_t *tp;
490   ipfix_message_header_t *h = 0;
491   ipfix_set_header_t *s = 0;
492   u32 sequence_number;
493   u32 stream_index;
494   ip4_header_t *ip;
495   udp_header_t *udp;
496   
497   stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
498   stream = &frm->streams[stream_index];
499
500   b0->current_data = 0;
501   b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
502     sizeof (*s);
503   b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_FLOW_REPORT);
504   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
505   vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
506   tp = vlib_buffer_get_current (b0);
507   ip = (ip4_header_t *) & tp->ip4;
508   udp = (udp_header_t *) (ip + 1);
509   h = (ipfix_message_header_t *) (udp + 1);
510   s = (ipfix_set_header_t *) (h + 1);
511
512   ip->ip_version_and_header_length = 0x45;
513   ip->ttl = 254;
514   ip->protocol = IP_PROTOCOL_UDP;
515   ip->flags_and_fragment_offset = 0;
516   ip->src_address.as_u32 = frm->src_address.as_u32;
517   ip->dst_address.as_u32 = frm->ipfix_collector.as_u32;
518   udp->src_port = clib_host_to_net_u16 (stream->src_port);
519   udp->dst_port = clib_host_to_net_u16 (frm->collector_port);
520   udp->checksum = 0;
521
522   h->export_time = clib_host_to_net_u32 ((u32)
523                                          (((f64) frm->unix_time_0) +
524                                           (vlib_time_now (frm->vlib_main) -
525                                            frm->vlib_time_0)));
526
527   sequence_number = clib_atomic_fetch_add (&stream->sequence_number, 1);
528   h->sequence_number = clib_host_to_net_u32 (sequence_number);
529   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
530
531   *offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
532 }
533
534 static inline void
535 snat_ipfix_send (flow_report_main_t * frm,
536                  vlib_frame_t * f, vlib_buffer_t * b0, u16 template_id)
537 {
538   ip4_ipfix_template_packet_t *tp;
539   ipfix_message_header_t *h = 0;
540   ipfix_set_header_t *s = 0;
541   ip4_header_t *ip;
542   udp_header_t *udp;
543   vlib_main_t *vm = frm->vlib_main;
544
545   tp = vlib_buffer_get_current (b0);
546   ip = (ip4_header_t *) & tp->ip4;
547   udp = (udp_header_t *) (ip + 1);
548   h = (ipfix_message_header_t *) (udp + 1);
549   s = (ipfix_set_header_t *) (h + 1);
550
551   s->set_id_length = ipfix_set_id_length (template_id,
552                                           b0->current_length -
553                                           (sizeof (*ip) + sizeof (*udp) +
554                                            sizeof (*h)));
555   h->version_length = version_length (b0->current_length -
556                                       (sizeof (*ip) + sizeof (*udp)));
557
558   ip->length = clib_host_to_net_u16 (b0->current_length);
559   ip->checksum = ip4_header_checksum (ip);
560   udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
561
562   if (frm->udp_checksum)
563     {
564       udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
565       if (udp->checksum == 0)
566         udp->checksum = 0xffff;
567     }
568
569   ASSERT (ip->checksum == ip4_header_checksum (ip));
570
571   vlib_put_frame_to_node (vm, ip4_lookup_node.index, f);
572 }
573
574 static void
575 snat_ipfix_logging_nat44_ses (u32 thread_index, u8 nat_event, u32 src_ip,
576                               u32 nat_src_ip, snat_protocol_t snat_proto,
577                               u16 src_port, u16 nat_src_port, u32 vrf_id,
578                               int do_flush)
579 {
580   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
581   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
582   flow_report_main_t *frm = &flow_report_main;
583   vlib_frame_t *f;
584   vlib_buffer_t *b0 = 0;
585   u32 bi0 = ~0;
586   u32 offset;
587   vlib_main_t *vm = frm->vlib_main;
588   u64 now;
589   u8 proto = ~0;
590   u16 template_id;
591
592   proto = snat_proto_to_ip_proto (snat_proto);
593
594   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
595   now += silm->milisecond_time_0;
596
597   b0 = sitd->nat44_session_buffer;
598
599   if (PREDICT_FALSE (b0 == 0))
600     {
601       if (do_flush)
602         return;
603
604       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
605         {
606           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
607           return;
608         }
609
610       b0 = sitd->nat44_session_buffer = vlib_get_buffer (vm, bi0);
611       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
612       offset = 0;
613     }
614   else
615     {
616       bi0 = vlib_get_buffer_index (vm, b0);
617       offset = sitd->nat44_session_next_record_offset;
618     }
619
620   f = sitd->nat44_session_frame;
621   if (PREDICT_FALSE (f == 0))
622     {
623       u32 *to_next;
624       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
625       sitd->nat44_session_frame = f;
626       to_next = vlib_frame_vector_args (f);
627       to_next[0] = bi0;
628       f->n_vectors = 1;
629     }
630
631   if (PREDICT_FALSE (offset == 0))
632     snat_ipfix_header_create (frm, b0, &offset);
633
634   if (PREDICT_TRUE (do_flush == 0))
635     {
636       u64 time_stamp = clib_host_to_net_u64 (now);
637       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
638       offset += sizeof (time_stamp);
639
640       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
641       offset += sizeof (nat_event);
642
643       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
644       offset += sizeof (src_ip);
645
646       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
647       offset += sizeof (nat_src_ip);
648
649       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
650       offset += sizeof (proto);
651
652       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
653       offset += sizeof (src_port);
654
655       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
656       offset += sizeof (nat_src_port);
657
658       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
659       offset += sizeof (vrf_id);
660
661       b0->current_length += NAT44_SESSION_CREATE_LEN;
662     }
663
664   if (PREDICT_FALSE
665       (do_flush || (offset + NAT44_SESSION_CREATE_LEN) > frm->path_mtu))
666     {
667       template_id = clib_atomic_fetch_or (
668         &silm->nat44_session_template_id,
669         0);
670       snat_ipfix_send (frm, f, b0, template_id);
671       sitd->nat44_session_frame = 0;
672       sitd->nat44_session_buffer = 0;
673       offset = 0;
674     }
675   sitd->nat44_session_next_record_offset = offset;
676 }
677
678 static void
679 snat_ipfix_logging_addr_exhausted (u32 thread_index, u32 pool_id, int do_flush)
680 {
681   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
682   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
683   flow_report_main_t *frm = &flow_report_main;
684   vlib_frame_t *f;
685   vlib_buffer_t *b0 = 0;
686   u32 bi0 = ~0;
687   u32 offset;
688   vlib_main_t *vm = frm->vlib_main;
689   u64 now;
690   u8 nat_event = NAT_ADDRESSES_EXHAUTED;
691   u16 template_id;
692
693   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
694   now += silm->milisecond_time_0;
695
696   b0 = sitd->addr_exhausted_buffer;
697
698   if (PREDICT_FALSE (b0 == 0))
699     {
700       if (do_flush)
701         return;
702
703       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
704         {
705           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
706           return;
707         }
708
709       b0 = sitd->addr_exhausted_buffer = vlib_get_buffer (vm, bi0);
710       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
711       offset = 0;
712     }
713   else
714     {
715       bi0 = vlib_get_buffer_index (vm, b0);
716       offset = sitd->addr_exhausted_next_record_offset;
717     }
718
719   f = sitd->addr_exhausted_frame;
720   if (PREDICT_FALSE (f == 0))
721     {
722       u32 *to_next;
723       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
724       sitd->addr_exhausted_frame = f;
725       to_next = vlib_frame_vector_args (f);
726       to_next[0] = bi0;
727       f->n_vectors = 1;
728     }
729
730   if (PREDICT_FALSE (offset == 0))
731     snat_ipfix_header_create (frm, b0, &offset);
732
733   if (PREDICT_TRUE (do_flush == 0))
734     {
735       u64 time_stamp = clib_host_to_net_u64 (now);
736       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
737       offset += sizeof (time_stamp);
738
739       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
740       offset += sizeof (nat_event);
741
742       clib_memcpy_fast (b0->data + offset, &pool_id, sizeof (pool_id));
743       offset += sizeof (pool_id);
744
745       b0->current_length += NAT_ADDRESSES_EXHAUTED_LEN;
746     }
747
748   if (PREDICT_FALSE
749       (do_flush || (offset + NAT_ADDRESSES_EXHAUTED_LEN) > frm->path_mtu))
750     {
751       template_id = clib_atomic_fetch_or (
752           &silm->addr_exhausted_template_id,
753           0);
754       snat_ipfix_send (frm, f, b0, template_id);
755       sitd->addr_exhausted_frame = 0;
756       sitd->addr_exhausted_buffer = 0;
757       offset = 0;
758     }
759   sitd->addr_exhausted_next_record_offset = offset;
760 }
761
762 static void
763 snat_ipfix_logging_max_entries_per_usr (u32 thread_index,
764                                         u32 limit, u32 src_ip, int do_flush)
765 {
766   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
767   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
768   flow_report_main_t *frm = &flow_report_main;
769   vlib_frame_t *f;
770   vlib_buffer_t *b0 = 0;
771   u32 bi0 = ~0;
772   u32 offset;
773   vlib_main_t *vm = frm->vlib_main;
774   u64 now;
775   u8 nat_event = QUOTA_EXCEEDED;
776   u32 quota_event = MAX_ENTRIES_PER_USER;
777   u16 template_id;
778
779   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
780   now += silm->milisecond_time_0;
781
782   b0 = sitd->max_entries_per_user_buffer;
783
784   if (PREDICT_FALSE (b0 == 0))
785     {
786       if (do_flush)
787         return;
788
789       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
790         {
791           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
792           return;
793         }
794
795       b0 = sitd->max_entries_per_user_buffer = vlib_get_buffer (vm, bi0);
796       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
797       offset = 0;
798     }
799   else
800     {
801       bi0 = vlib_get_buffer_index (vm, b0);
802       offset = sitd->max_entries_per_user_next_record_offset;
803     }
804
805   f = sitd->max_entries_per_user_frame;
806   if (PREDICT_FALSE (f == 0))
807     {
808       u32 *to_next;
809       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
810       sitd->max_entries_per_user_frame = f;
811       to_next = vlib_frame_vector_args (f);
812       to_next[0] = bi0;
813       f->n_vectors = 1;
814     }
815
816   if (PREDICT_FALSE (offset == 0))
817     snat_ipfix_header_create (frm, b0, &offset);
818
819   if (PREDICT_TRUE (do_flush == 0))
820     {
821       u64 time_stamp = clib_host_to_net_u64 (now);
822       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
823       offset += sizeof (time_stamp);
824
825       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
826       offset += sizeof (nat_event);
827
828       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
829       offset += sizeof (quota_event);
830
831       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
832       offset += sizeof (limit);
833
834       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
835       offset += sizeof (src_ip);
836
837       b0->current_length += MAX_ENTRIES_PER_USER_LEN;
838     }
839
840   if (PREDICT_FALSE
841       (do_flush || (offset + MAX_ENTRIES_PER_USER_LEN) > frm->path_mtu))
842     {
843       template_id = clib_atomic_fetch_or (
844           &silm->max_entries_per_user_template_id,
845           0);
846       snat_ipfix_send (frm, f, b0, template_id);
847       sitd->max_entries_per_user_frame = 0;
848       sitd->max_entries_per_user_buffer = 0;
849       offset = 0;
850     }
851   sitd->max_entries_per_user_next_record_offset = offset;
852 }
853
854 static void
855 nat_ipfix_logging_max_ses (u32 thread_index, u32 limit, int do_flush)
856 {
857   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
858   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
859   flow_report_main_t *frm = &flow_report_main;
860   vlib_frame_t *f;
861   vlib_buffer_t *b0 = 0;
862   u32 bi0 = ~0;
863   u32 offset;
864   vlib_main_t *vm = frm->vlib_main;
865   u64 now;
866   u8 nat_event = QUOTA_EXCEEDED;
867   u32 quota_event = MAX_SESSION_ENTRIES;
868   u16 template_id;
869
870   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
871   now += silm->milisecond_time_0;
872
873   b0 = sitd->max_sessions_buffer;
874
875   if (PREDICT_FALSE (b0 == 0))
876     {
877       if (do_flush)
878         return;
879
880       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
881         {
882           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
883           return;
884         }
885
886       b0 = sitd->max_sessions_buffer = vlib_get_buffer (vm, bi0);
887       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
888       offset = 0;
889     }
890   else
891     {
892       bi0 = vlib_get_buffer_index (vm, b0);
893       offset = sitd->max_sessions_next_record_offset;
894     }
895
896   f = sitd->max_sessions_frame;
897   if (PREDICT_FALSE (f == 0))
898     {
899       u32 *to_next;
900       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
901       sitd->max_sessions_frame = f;
902       to_next = vlib_frame_vector_args (f);
903       to_next[0] = bi0;
904       f->n_vectors = 1;
905     }
906
907   if (PREDICT_FALSE (offset == 0))
908     snat_ipfix_header_create (frm, b0, &offset);
909
910   if (PREDICT_TRUE (do_flush == 0))
911     {
912       u64 time_stamp = clib_host_to_net_u64 (now);
913       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
914       offset += sizeof (time_stamp);
915
916       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
917       offset += sizeof (nat_event);
918
919       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
920       offset += sizeof (quota_event);
921
922       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
923       offset += sizeof (limit);
924
925       b0->current_length += MAX_SESSIONS_LEN;
926     }
927
928   if (PREDICT_FALSE
929       (do_flush || (offset + MAX_SESSIONS_LEN) > frm->path_mtu))
930     {
931       template_id = clib_atomic_fetch_or (
932         &silm->max_sessions_template_id,
933         0);
934       snat_ipfix_send (frm, f, b0, template_id);
935       sitd->max_sessions_frame = 0;
936       sitd->max_sessions_buffer = 0;
937       offset = 0;
938     }
939   sitd->max_sessions_next_record_offset = offset;
940 }
941
942 static void
943 nat_ipfix_logging_max_bib (u32 thread_index, u32 limit, int do_flush)
944 {
945   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
946   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
947   flow_report_main_t *frm = &flow_report_main;
948   vlib_frame_t *f;
949   vlib_buffer_t *b0 = 0;
950   u32 bi0 = ~0;
951   u32 offset;
952   vlib_main_t *vm = frm->vlib_main;
953   u64 now;
954   u8 nat_event = QUOTA_EXCEEDED;
955   u32 quota_event = MAX_BIB_ENTRIES;
956   u16 template_id;
957
958   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
959   now += silm->milisecond_time_0;
960
961   b0 = sitd->max_bibs_buffer;
962
963   if (PREDICT_FALSE (b0 == 0))
964     {
965       if (do_flush)
966         return;
967
968       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
969         {
970           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
971           return;
972         }
973
974       b0 = sitd->max_bibs_buffer = vlib_get_buffer (vm, bi0);
975       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
976       offset = 0;
977     }
978   else
979     {
980       bi0 = vlib_get_buffer_index (vm, b0);
981       offset = sitd->max_bibs_next_record_offset;
982     }
983
984   f = sitd->max_bibs_frame;
985   if (PREDICT_FALSE (f == 0))
986     {
987       u32 *to_next;
988       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
989       sitd->max_bibs_frame = f;
990       to_next = vlib_frame_vector_args (f);
991       to_next[0] = bi0;
992       f->n_vectors = 1;
993     }
994
995   if (PREDICT_FALSE (offset == 0))
996     snat_ipfix_header_create (frm, b0, &offset);
997
998   if (PREDICT_TRUE (do_flush == 0))
999     {
1000       u64 time_stamp = clib_host_to_net_u64 (now);
1001       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1002       offset += sizeof (time_stamp);
1003
1004       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1005       offset += sizeof (nat_event);
1006
1007       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1008       offset += sizeof (quota_event);
1009
1010       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
1011       offset += sizeof (limit);
1012
1013       b0->current_length += MAX_BIBS_LEN;
1014     }
1015
1016   if (PREDICT_FALSE
1017       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1018     {
1019       template_id = clib_atomic_fetch_or (
1020         &silm->max_bibs_template_id,
1021         0);
1022       snat_ipfix_send (frm, f, b0, template_id);
1023       sitd->max_bibs_frame = 0;
1024       sitd->max_bibs_buffer = 0;
1025       offset = 0;
1026     }
1027   sitd->max_bibs_next_record_offset = offset;
1028 }
1029
1030 static void
1031 nat_ipfix_logging_nat64_bibe (u32 thread_index, u8 nat_event,
1032                               ip6_address_t * src_ip, u32 nat_src_ip,
1033                               u8 proto, u16 src_port, u16 nat_src_port,
1034                               u32 vrf_id, int do_flush)
1035 {
1036   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1037   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1038   flow_report_main_t *frm = &flow_report_main;
1039   vlib_frame_t *f;
1040   vlib_buffer_t *b0 = 0;
1041   u32 bi0 = ~0;
1042   u32 offset;
1043   vlib_main_t *vm = frm->vlib_main;
1044   u64 now;
1045   u16 template_id;
1046
1047   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1048   now += silm->milisecond_time_0;
1049
1050   b0 = sitd->nat64_bib_buffer;
1051
1052   if (PREDICT_FALSE (b0 == 0))
1053     {
1054       if (do_flush)
1055         return;
1056
1057       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1058         {
1059           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1060           return;
1061         }
1062
1063       b0 = sitd->nat64_bib_buffer = vlib_get_buffer (vm, bi0);
1064       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1065       offset = 0;
1066     }
1067   else
1068     {
1069       bi0 = vlib_get_buffer_index (vm, b0);
1070       offset = sitd->nat64_bib_next_record_offset;
1071     }
1072
1073   f = sitd->nat64_bib_frame;
1074   if (PREDICT_FALSE (f == 0))
1075     {
1076       u32 *to_next;
1077       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1078       sitd->nat64_bib_frame = f;
1079       to_next = vlib_frame_vector_args (f);
1080       to_next[0] = bi0;
1081       f->n_vectors = 1;
1082     }
1083
1084   if (PREDICT_FALSE (offset == 0))
1085     snat_ipfix_header_create (frm, b0, &offset);
1086
1087   if (PREDICT_TRUE (do_flush == 0))
1088     {
1089       u64 time_stamp = clib_host_to_net_u64 (now);
1090       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1091       offset += sizeof (time_stamp);
1092
1093       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1094       offset += sizeof (nat_event);
1095
1096       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1097       offset += sizeof (ip6_address_t);
1098
1099       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1100       offset += sizeof (nat_src_ip);
1101
1102       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1103       offset += sizeof (proto);
1104
1105       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1106       offset += sizeof (src_port);
1107
1108       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1109       offset += sizeof (nat_src_port);
1110
1111       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1112       offset += sizeof (vrf_id);
1113
1114       b0->current_length += NAT64_BIB_LEN;
1115     }
1116
1117   if (PREDICT_FALSE
1118       (do_flush || (offset + NAT64_BIB_LEN) > frm->path_mtu))
1119     {
1120       template_id = clib_atomic_fetch_or (
1121         &silm->nat64_bib_template_id,
1122         0);
1123       snat_ipfix_send (frm, f, b0, template_id);
1124       sitd->nat64_bib_frame = 0;
1125       sitd->nat64_bib_buffer = 0;
1126       offset = 0;
1127     }
1128   sitd->nat64_bib_next_record_offset = offset;
1129 }
1130
1131 static void
1132 nat_ipfix_logging_nat64_ses (u32 thread_index, u8 nat_event,
1133                              ip6_address_t * src_ip, u32 nat_src_ip,
1134                              u8 proto, u16 src_port, u16 nat_src_port,
1135                              ip6_address_t * dst_ip, u32 nat_dst_ip,
1136                              u16 dst_port, u16 nat_dst_port,
1137                              u32 vrf_id, int do_flush)
1138 {
1139   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1140   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1141   flow_report_main_t *frm = &flow_report_main;
1142   vlib_frame_t *f;
1143   vlib_buffer_t *b0 = 0;
1144   u32 bi0 = ~0;
1145   u32 offset;
1146   vlib_main_t *vm = frm->vlib_main;
1147   u64 now;
1148   u16 template_id;
1149
1150   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1151   now += silm->milisecond_time_0;
1152
1153   b0 = sitd->nat64_ses_buffer;
1154
1155   if (PREDICT_FALSE (b0 == 0))
1156     {
1157       if (do_flush)
1158         return;
1159
1160       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1161         {
1162           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1163           return;
1164         }
1165
1166       b0 = sitd->nat64_ses_buffer = vlib_get_buffer (vm, bi0);
1167       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1168       offset = 0;
1169     }
1170   else
1171     {
1172       bi0 = vlib_get_buffer_index (vm, b0);
1173       offset = sitd->nat64_ses_next_record_offset;
1174     }
1175
1176   f = sitd->nat64_ses_frame;
1177   if (PREDICT_FALSE (f == 0))
1178     {
1179       u32 *to_next;
1180       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1181       sitd->nat64_ses_frame = f;
1182       to_next = vlib_frame_vector_args (f);
1183       to_next[0] = bi0;
1184       f->n_vectors = 1;
1185     }
1186
1187   if (PREDICT_FALSE (offset == 0))
1188     snat_ipfix_header_create (frm, b0, &offset);
1189
1190   if (PREDICT_TRUE (do_flush == 0))
1191     {
1192       u64 time_stamp = clib_host_to_net_u64 (now);
1193       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1194       offset += sizeof (time_stamp);
1195
1196       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1197       offset += sizeof (nat_event);
1198
1199       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1200       offset += sizeof (ip6_address_t);
1201
1202       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1203       offset += sizeof (nat_src_ip);
1204
1205       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1206       offset += sizeof (proto);
1207
1208       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1209       offset += sizeof (src_port);
1210
1211       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1212       offset += sizeof (nat_src_port);
1213
1214       clib_memcpy_fast (b0->data + offset, dst_ip, sizeof (ip6_address_t));
1215       offset += sizeof (ip6_address_t);
1216
1217       clib_memcpy_fast (b0->data + offset, &nat_dst_ip, sizeof (nat_dst_ip));
1218       offset += sizeof (nat_dst_ip);
1219
1220       clib_memcpy_fast (b0->data + offset, &dst_port, sizeof (dst_port));
1221       offset += sizeof (dst_port);
1222
1223       clib_memcpy_fast (b0->data + offset, &nat_dst_port, sizeof (nat_dst_port));
1224       offset += sizeof (nat_dst_port);
1225
1226       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1227       offset += sizeof (vrf_id);
1228
1229       b0->current_length += NAT64_SES_LEN;
1230     }
1231
1232   if (PREDICT_FALSE
1233       (do_flush || (offset + NAT64_SES_LEN) > frm->path_mtu))
1234     {
1235       template_id = clib_atomic_fetch_or (
1236         &silm->nat64_ses_template_id,
1237         0);
1238       snat_ipfix_send (frm, f, b0, template_id);
1239       sitd->nat64_ses_frame = 0;
1240       sitd->nat64_ses_buffer = 0;
1241       offset = 0;
1242     }
1243   sitd->nat64_ses_next_record_offset = offset;
1244 }
1245
1246 void
1247 snat_ipfix_flush (u32 thread_index)
1248 {
1249   int do_flush = 1;
1250
1251   snat_ipfix_logging_nat44_ses (thread_index,
1252                                 0, 0, 0, 0, 0, 0, 0, do_flush);
1253   snat_ipfix_logging_addr_exhausted (thread_index, 0, do_flush);
1254   snat_ipfix_logging_max_entries_per_usr (thread_index, 0, 0, do_flush);
1255   nat_ipfix_logging_max_ses (thread_index, 0, do_flush);
1256   nat_ipfix_logging_max_bib (thread_index, 0, do_flush);
1257   nat_ipfix_logging_nat64_bibe (thread_index,
1258                                 0, 0, 0, 0, 0, 0, 0, do_flush);
1259   nat_ipfix_logging_nat64_ses (thread_index,
1260                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, do_flush);
1261 }
1262
1263 void
1264 snat_ipfix_flush_from_main (void)
1265 {
1266   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1267   vlib_main_t *worker_vm;
1268   int i;
1269
1270   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))
1271     return;
1272
1273   if (PREDICT_FALSE (!silm->worker_vms))
1274     {
1275       for (i = 1; i < vec_len (vlib_mains); i++)
1276         {
1277           worker_vm = vlib_mains[i];
1278           if (worker_vm)
1279             vec_add1 (silm->worker_vms, worker_vm);
1280         }
1281     }
1282
1283   /* Trigger flush for each worker thread */
1284   for (i = 0; i < vec_len (silm->worker_vms); i++)
1285     {
1286       worker_vm = silm->worker_vms[i];
1287       if (worker_vm)
1288         vlib_node_set_interrupt_pending (worker_vm,
1289                                          snat_ipfix_flush_node.index);
1290     }
1291
1292   /* Finally flush main thread */
1293   snat_ipfix_flush (0);
1294 }
1295
1296 /**
1297  * @brief Generate NAT44 session create event
1298  *
1299  * @param thread_index thread index
1300  * @param src_ip       source IPv4 address
1301  * @param nat_src_ip   transaltes source IPv4 address
1302  * @param snat_proto   NAT transport protocol
1303  * @param src_port     source port
1304  * @param nat_src_port translated source port
1305  * @param vrf_id       VRF ID
1306  */
1307 void
1308 snat_ipfix_logging_nat44_ses_create (u32 thread_index,
1309                                      u32 src_ip,
1310                                      u32 nat_src_ip,
1311                                      snat_protocol_t snat_proto,
1312                                      u16 src_port,
1313                                      u16 nat_src_port, u32 vrf_id)
1314 {
1315   skip_if_disabled ();
1316
1317   snat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_CREATE, src_ip,
1318                                 nat_src_ip, snat_proto, src_port, nat_src_port,
1319                                 vrf_id, 0);
1320 }
1321
1322 /**
1323  * @brief Generate NAT44 session delete event
1324  *
1325  * @param thread_index thread index
1326  * @param src_ip       source IPv4 address
1327  * @param nat_src_ip   transaltes source IPv4 address
1328  * @param snat_proto   NAT transport protocol
1329  * @param src_port     source port
1330  * @param nat_src_port translated source port
1331  * @param vrf_id       VRF ID
1332  */
1333 void
1334 snat_ipfix_logging_nat44_ses_delete (u32 thread_index,
1335                                      u32 src_ip,
1336                                      u32 nat_src_ip,
1337                                      snat_protocol_t snat_proto,
1338                                      u16 src_port,
1339                                      u16 nat_src_port, u32 vrf_id)
1340 {
1341   skip_if_disabled ();
1342
1343   snat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_DELETE, src_ip,
1344                                 nat_src_ip, snat_proto, src_port, nat_src_port,
1345                                 vrf_id, 0);
1346 }
1347
1348 /**
1349  * @brief Generate NAT addresses exhausted event
1350  *
1351  * @param thread_index thread index
1352  * @param pool_id NAT pool ID
1353  */
1354 void
1355 snat_ipfix_logging_addresses_exhausted (u32 thread_index, u32 pool_id)
1356 {
1357   //TODO: This event SHOULD be rate limited
1358   skip_if_disabled ();
1359
1360   snat_ipfix_logging_addr_exhausted (thread_index, pool_id, 0);
1361 }
1362
1363 /**
1364  * @brief Generate maximum entries per user exceeded event
1365  *
1366  * @param thread_index thread index
1367  * @param limit maximum NAT entries that can be created per user
1368  * @param src_ip source IPv4 address
1369  */
1370 void
1371 snat_ipfix_logging_max_entries_per_user (u32 thread_index, u32 limit, u32 src_ip)
1372 {
1373   //TODO: This event SHOULD be rate limited
1374   skip_if_disabled ();
1375
1376   snat_ipfix_logging_max_entries_per_usr (thread_index, limit, src_ip, 0);
1377 }
1378
1379 vlib_frame_t *
1380 deterministic_nat_data_callback
1381 (flow_report_main_t * frm,
1382                                         flow_report_t * fr,
1383                                         vlib_frame_t * f,
1384                                         u32 * to_next, u32 node_index)
1385 {
1386   snat_ipfix_flush_from_main();
1387
1388   return f;
1389 }
1390
1391 /**
1392  * @brief Generate maximum session entries exceeded event
1393  *
1394  * @param thread_index thread index
1395  * @param limit configured limit
1396  */
1397 void
1398 nat_ipfix_logging_max_sessions (u32 thread_index, u32 limit)
1399 {
1400   //TODO: This event SHOULD be rate limited
1401   skip_if_disabled ();
1402
1403   nat_ipfix_logging_max_ses (thread_index, limit, 0);
1404 }
1405
1406 /**
1407  * @brief Generate maximum BIB entries exceeded event
1408  *
1409  * @param thread_index thread index
1410  * @param limit configured limit
1411  */
1412 void
1413 nat_ipfix_logging_max_bibs (u32 thread_index, u32 limit)
1414 {
1415   //TODO: This event SHOULD be rate limited
1416   skip_if_disabled ();
1417
1418   nat_ipfix_logging_max_bib (thread_index, limit, 0);
1419 }
1420
1421 /**
1422  * @brief Generate NAT64 BIB create and delete events
1423  *
1424  * @param thread_index thread index
1425  * @param src_ip       source IPv6 address
1426  * @param nat_src_ip   transaltes source IPv4 address
1427  * @param proto        L4 protocol
1428  * @param src_port     source port
1429  * @param nat_src_port translated source port
1430  * @param vrf_id       VRF ID
1431  * @param is_create    non-zero value if create event otherwise delete event
1432  */
1433 void
1434 nat_ipfix_logging_nat64_bib (u32 thread_index, ip6_address_t * src_ip,
1435                              ip4_address_t * nat_src_ip, u8 proto,
1436                              u16 src_port, u16 nat_src_port, u32 vrf_id,
1437                              u8 is_create)
1438 {
1439   u8 nat_event;
1440
1441   skip_if_disabled ();
1442
1443   nat_event = is_create ? NAT64_BIB_CREATE : NAT64_BIB_DELETE;
1444
1445   nat_ipfix_logging_nat64_bibe (thread_index, nat_event, src_ip,
1446                                 nat_src_ip->as_u32, proto, src_port,
1447                                 nat_src_port, vrf_id, 0);
1448 }
1449
1450 /**
1451  * @brief Generate NAT64 session create and delete events
1452  *
1453  * @param thread_index thread index
1454  * @param src_ip       source IPv6 address
1455  * @param nat_src_ip   transaltes source IPv4 address
1456  * @param proto        L4 protocol
1457  * @param src_port     source port
1458  * @param nat_src_port translated source port
1459  * @param dst_ip       destination IPv6 address
1460  * @param nat_dst_ip   destination IPv4 address
1461  * @param dst_port     destination port
1462  * @param nat_dst_port translated destination port
1463  * @param vrf_id       VRF ID
1464  * @param is_create    non-zero value if create event otherwise delete event
1465  */
1466 void
1467 nat_ipfix_logging_nat64_session (u32 thread_index,
1468                                  ip6_address_t * src_ip,
1469                                  ip4_address_t * nat_src_ip, u8 proto,
1470                                  u16 src_port, u16 nat_src_port,
1471                                  ip6_address_t * dst_ip,
1472                                  ip4_address_t * nat_dst_ip, u16 dst_port,
1473                                  u16 nat_dst_port, u32 vrf_id, u8 is_create)
1474 {
1475   u8 nat_event;
1476
1477   skip_if_disabled ();
1478
1479   nat_event = is_create ? NAT64_SESSION_CREATE : NAT64_SESSION_DELETE;
1480
1481   nat_ipfix_logging_nat64_ses (thread_index, nat_event, src_ip,
1482                                nat_src_ip->as_u32, proto, src_port,
1483                                nat_src_port, dst_ip, nat_dst_ip->as_u32,
1484                                dst_port, nat_dst_port, vrf_id, 0);
1485 }
1486
1487 vlib_frame_t *
1488 data_callback (flow_report_main_t * frm, flow_report_t * fr,
1489                vlib_frame_t * f, u32 * to_next, u32 node_index)
1490 {
1491   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1492
1493   if (PREDICT_FALSE (++silm->call_counter >= vec_len (frm->reports)))
1494     {
1495       snat_ipfix_flush_from_main();
1496       silm->call_counter = 0;
1497     }
1498
1499   return f;
1500 }
1501
1502 /**
1503  * @brief Enable/disable NAT plugin IPFIX logging
1504  *
1505  * @param enable    1 if enable, 0 if disable
1506  * @param domain_id observation domain ID
1507  * @param src_port  source port number
1508  *
1509  * @returns 0 if success
1510  */
1511 int
1512 snat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
1513 {
1514   snat_main_t *sm = &snat_main;
1515   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1516   flow_report_main_t *frm = &flow_report_main;
1517   vnet_flow_report_add_del_args_t a;
1518   int rv;
1519   u8 e = enable ? 1 : 0;
1520
1521   if (clib_atomic_cmp_and_swap (&silm->enabled, e ^ 1, e) == e)
1522     return 0;
1523
1524   clib_memset (&a, 0, sizeof (a));
1525   a.is_add = enable;
1526   a.domain_id = domain_id ? domain_id : 1;
1527   a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
1528   a.flow_data_callback = data_callback;
1529
1530   if (sm->deterministic)
1531     {
1532       a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
1533
1534       rv = vnet_flow_report_add_del (frm, &a, NULL);
1535       if (rv)
1536         {
1537           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1538           return -1;
1539         }
1540     }
1541   else
1542     {
1543       a.rewrite_callback = snat_template_rewrite_nat44_session;
1544
1545       rv = vnet_flow_report_add_del (frm, &a, NULL);
1546       if (rv)
1547         {
1548           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1549           return -1;
1550         }
1551
1552       a.rewrite_callback = snat_template_rewrite_addr_exhausted;
1553
1554       rv = vnet_flow_report_add_del (frm, &a, NULL);
1555       if (rv)
1556         {
1557           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1558           return -1;
1559         }
1560
1561       a.rewrite_callback = nat_template_rewrite_max_sessions;
1562
1563       rv = vnet_flow_report_add_del (frm, &a, NULL);
1564       if (rv)
1565         {
1566           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1567           return -1;
1568         }
1569
1570       a.rewrite_callback = nat_template_rewrite_max_bibs;
1571
1572       rv = vnet_flow_report_add_del (frm, &a, NULL);
1573       if (rv)
1574         {
1575           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1576           return -1;
1577         }
1578
1579       a.rewrite_callback = nat_template_rewrite_nat64_bib;
1580
1581       rv = vnet_flow_report_add_del (frm, &a, NULL);
1582       if (rv)
1583         {
1584           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1585           return -1;
1586         }
1587
1588       a.rewrite_callback = nat_template_rewrite_nat64_session;
1589
1590       rv = vnet_flow_report_add_del (frm, &a, NULL);
1591       if (rv)
1592         {
1593           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1594           return -1;
1595         }
1596
1597       if (sm->endpoint_dependent)
1598         {
1599           a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
1600
1601           rv = vnet_flow_report_add_del (frm, &a, NULL);
1602           if (rv)
1603             {
1604               nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1605               return -1;
1606             }
1607         }
1608     }
1609
1610   return 0;
1611 }
1612
1613 /**
1614  * @brief Initialize NAT plugin IPFIX logging
1615  *
1616  * @param vm vlib main
1617  */
1618 void
1619 snat_ipfix_logging_init (vlib_main_t * vm)
1620 {
1621   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1622   vlib_thread_main_t *tm = vlib_get_thread_main ();
1623
1624   silm->enabled = 0;
1625   silm->worker_vms = 0;
1626   silm->call_counter = 0;
1627
1628   /* Set up time reference pair */
1629   silm->vlib_time_0 = vlib_time_now (vm);
1630   silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
1631
1632   vec_validate (silm->per_thread_data, tm->n_vlib_mains - 1);
1633 }
1634
1635 static uword
1636 ipfix_flush_process (vlib_main_t *vm,
1637                      vlib_node_runtime_t *rt,
1638                      vlib_frame_t *f)
1639 {
1640   snat_ipfix_flush(vm->thread_index);
1641   return 0;
1642 }
1643
1644 /* *INDENT-OFF* */
1645 VLIB_REGISTER_NODE (snat_ipfix_flush_node) = {
1646   .function = ipfix_flush_process,
1647   .name = "snat-ipfix-flush",
1648   .type = VLIB_NODE_TYPE_INPUT,
1649   .state = VLIB_NODE_STATE_INTERRUPT,
1650 };
1651 /* *INDENT-ON* */