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