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