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