nat: static mappings in flow hash
[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 (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, ip_protocol_t proto, u16 src_port,
581                              u16 nat_src_port, u32 fib_index, int do_flush)
582 {
583   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
584   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
585   flow_report_main_t *frm = &flow_report_main;
586   vlib_frame_t *f;
587   vlib_buffer_t *b0 = 0;
588   u32 bi0 = ~0;
589   u32 offset;
590   vlib_main_t *vm = vlib_get_main ();
591   u64 now;
592   u16 template_id;
593   u32 vrf_id;
594
595   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
596   now += silm->milisecond_time_0;
597
598   b0 = sitd->nat44_session_buffer;
599
600   if (PREDICT_FALSE (b0 == 0))
601     {
602       if (do_flush)
603         return;
604
605       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
606         {
607           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
608           return;
609         }
610
611       b0 = sitd->nat44_session_buffer = vlib_get_buffer (vm, bi0);
612       offset = 0;
613     }
614   else
615     {
616       bi0 = vlib_get_buffer_index (vm, b0);
617       offset = sitd->nat44_session_next_record_offset;
618     }
619
620   f = sitd->nat44_session_frame;
621   if (PREDICT_FALSE (f == 0))
622     {
623       u32 *to_next;
624       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
625       sitd->nat44_session_frame = f;
626       to_next = vlib_frame_vector_args (f);
627       to_next[0] = bi0;
628       f->n_vectors = 1;
629     }
630
631   if (PREDICT_FALSE (offset == 0))
632     nat_ipfix_header_create (frm, b0, &offset);
633
634   if (PREDICT_TRUE (do_flush == 0))
635     {
636       u64 time_stamp = clib_host_to_net_u64 (now);
637       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
638       offset += sizeof (time_stamp);
639
640       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
641       offset += sizeof (nat_event);
642
643       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
644       offset += sizeof (src_ip);
645
646       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
647       offset += sizeof (nat_src_ip);
648
649       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
650       offset += sizeof (proto);
651
652       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
653       offset += sizeof (src_port);
654
655       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
656       offset += sizeof (nat_src_port);
657
658       vrf_id = fib_table_get_table_id (fib_index, FIB_PROTOCOL_IP4);
659       vrf_id = clib_host_to_net_u32 (vrf_id);
660       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
661       offset += sizeof (vrf_id);
662
663       b0->current_length += NAT44_SESSION_CREATE_LEN;
664     }
665
666   if (PREDICT_FALSE
667       (do_flush || (offset + NAT44_SESSION_CREATE_LEN) > frm->path_mtu))
668     {
669       template_id = clib_atomic_fetch_or (
670         &silm->nat44_session_template_id,
671         0);
672       nat_ipfix_send (frm, f, b0, template_id);
673       sitd->nat44_session_frame = 0;
674       sitd->nat44_session_buffer = 0;
675       offset = 0;
676     }
677   sitd->nat44_session_next_record_offset = offset;
678 }
679
680 static void
681 nat_ipfix_logging_addr_exhausted (u32 thread_index, u32 pool_id, int do_flush)
682 {
683   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
684   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
685   flow_report_main_t *frm = &flow_report_main;
686   vlib_frame_t *f;
687   vlib_buffer_t *b0 = 0;
688   u32 bi0 = ~0;
689   u32 offset;
690   vlib_main_t *vm = vlib_get_main ();
691   u64 now;
692   u8 nat_event = NAT_ADDRESSES_EXHAUTED;
693   u16 template_id;
694
695   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
696   now += silm->milisecond_time_0;
697
698   b0 = sitd->addr_exhausted_buffer;
699
700   if (PREDICT_FALSE (b0 == 0))
701     {
702       if (do_flush)
703         return;
704
705       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
706         {
707           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
708           return;
709         }
710
711       b0 = sitd->addr_exhausted_buffer = vlib_get_buffer (vm, bi0);
712       offset = 0;
713     }
714   else
715     {
716       bi0 = vlib_get_buffer_index (vm, b0);
717       offset = sitd->addr_exhausted_next_record_offset;
718     }
719
720   f = sitd->addr_exhausted_frame;
721   if (PREDICT_FALSE (f == 0))
722     {
723       u32 *to_next;
724       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
725       sitd->addr_exhausted_frame = f;
726       to_next = vlib_frame_vector_args (f);
727       to_next[0] = bi0;
728       f->n_vectors = 1;
729     }
730
731   if (PREDICT_FALSE (offset == 0))
732     nat_ipfix_header_create (frm, b0, &offset);
733
734   if (PREDICT_TRUE (do_flush == 0))
735     {
736       u64 time_stamp = clib_host_to_net_u64 (now);
737       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
738       offset += sizeof (time_stamp);
739
740       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
741       offset += sizeof (nat_event);
742
743       clib_memcpy_fast (b0->data + offset, &pool_id, sizeof (pool_id));
744       offset += sizeof (pool_id);
745
746       b0->current_length += NAT_ADDRESSES_EXHAUTED_LEN;
747     }
748
749   if (PREDICT_FALSE
750       (do_flush || (offset + NAT_ADDRESSES_EXHAUTED_LEN) > frm->path_mtu))
751     {
752       template_id = clib_atomic_fetch_or (
753           &silm->addr_exhausted_template_id,
754           0);
755       nat_ipfix_send (frm, f, b0, template_id);
756       sitd->addr_exhausted_frame = 0;
757       sitd->addr_exhausted_buffer = 0;
758       offset = 0;
759     }
760   sitd->addr_exhausted_next_record_offset = offset;
761 }
762
763 static void
764 nat_ipfix_logging_max_entries_per_usr (u32 thread_index,
765                                         u32 limit, u32 src_ip, int do_flush)
766 {
767   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
768   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
769   flow_report_main_t *frm = &flow_report_main;
770   vlib_frame_t *f;
771   vlib_buffer_t *b0 = 0;
772   u32 bi0 = ~0;
773   u32 offset;
774   vlib_main_t *vm = vlib_get_main ();
775   u64 now;
776   u8 nat_event = QUOTA_EXCEEDED;
777   u32 quota_event = clib_host_to_net_u32 (MAX_ENTRIES_PER_USER);
778   u16 template_id;
779
780   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
781   now += silm->milisecond_time_0;
782
783   b0 = sitd->max_entries_per_user_buffer;
784
785   if (PREDICT_FALSE (b0 == 0))
786     {
787       if (do_flush)
788         return;
789
790       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
791         {
792           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
793           return;
794         }
795
796       b0 = sitd->max_entries_per_user_buffer = vlib_get_buffer (vm, bi0);
797       offset = 0;
798     }
799   else
800     {
801       bi0 = vlib_get_buffer_index (vm, b0);
802       offset = sitd->max_entries_per_user_next_record_offset;
803     }
804
805   f = sitd->max_entries_per_user_frame;
806   if (PREDICT_FALSE (f == 0))
807     {
808       u32 *to_next;
809       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
810       sitd->max_entries_per_user_frame = f;
811       to_next = vlib_frame_vector_args (f);
812       to_next[0] = bi0;
813       f->n_vectors = 1;
814     }
815
816   if (PREDICT_FALSE (offset == 0))
817     nat_ipfix_header_create (frm, b0, &offset);
818
819   if (PREDICT_TRUE (do_flush == 0))
820     {
821       u64 time_stamp = clib_host_to_net_u64 (now);
822       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
823       offset += sizeof (time_stamp);
824
825       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
826       offset += sizeof (nat_event);
827
828       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
829       offset += sizeof (quota_event);
830
831       limit = clib_host_to_net_u32 (limit);
832       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
833       offset += sizeof (limit);
834
835       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
836       offset += sizeof (src_ip);
837
838       b0->current_length += MAX_ENTRIES_PER_USER_LEN;
839     }
840
841   if (PREDICT_FALSE
842       (do_flush || (offset + MAX_ENTRIES_PER_USER_LEN) > frm->path_mtu))
843     {
844       template_id = clib_atomic_fetch_or (
845           &silm->max_entries_per_user_template_id,
846           0);
847       nat_ipfix_send (frm, f, b0, template_id);
848       sitd->max_entries_per_user_frame = 0;
849       sitd->max_entries_per_user_buffer = 0;
850       offset = 0;
851     }
852   sitd->max_entries_per_user_next_record_offset = offset;
853 }
854
855 static void
856 nat_ipfix_logging_max_ses (u32 thread_index, u32 limit, int do_flush)
857 {
858   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
859   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
860   flow_report_main_t *frm = &flow_report_main;
861   vlib_frame_t *f;
862   vlib_buffer_t *b0 = 0;
863   u32 bi0 = ~0;
864   u32 offset;
865   vlib_main_t *vm = vlib_get_main ();
866   u64 now;
867   u8 nat_event = QUOTA_EXCEEDED;
868   u32 quota_event = clib_host_to_net_u32 (MAX_SESSION_ENTRIES);
869   u16 template_id;
870
871   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
872   now += silm->milisecond_time_0;
873
874   b0 = sitd->max_sessions_buffer;
875
876   if (PREDICT_FALSE (b0 == 0))
877     {
878       if (do_flush)
879         return;
880
881       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
882         {
883           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
884           return;
885         }
886
887       b0 = sitd->max_sessions_buffer = vlib_get_buffer (vm, bi0);
888       offset = 0;
889     }
890   else
891     {
892       bi0 = vlib_get_buffer_index (vm, b0);
893       offset = sitd->max_sessions_next_record_offset;
894     }
895
896   f = sitd->max_sessions_frame;
897   if (PREDICT_FALSE (f == 0))
898     {
899       u32 *to_next;
900       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
901       sitd->max_sessions_frame = f;
902       to_next = vlib_frame_vector_args (f);
903       to_next[0] = bi0;
904       f->n_vectors = 1;
905     }
906
907   if (PREDICT_FALSE (offset == 0))
908     nat_ipfix_header_create (frm, b0, &offset);
909
910   if (PREDICT_TRUE (do_flush == 0))
911     {
912       u64 time_stamp = clib_host_to_net_u64 (now);
913       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
914       offset += sizeof (time_stamp);
915
916       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
917       offset += sizeof (nat_event);
918
919       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
920       offset += sizeof (quota_event);
921
922       limit = clib_host_to_net_u32 (limit);
923       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
924       offset += sizeof (limit);
925
926       b0->current_length += MAX_SESSIONS_LEN;
927     }
928
929   if (PREDICT_FALSE
930       (do_flush || (offset + MAX_SESSIONS_LEN) > frm->path_mtu))
931     {
932       template_id = clib_atomic_fetch_or (
933         &silm->max_sessions_template_id,
934         0);
935       nat_ipfix_send (frm, f, b0, template_id);
936       sitd->max_sessions_frame = 0;
937       sitd->max_sessions_buffer = 0;
938       offset = 0;
939     }
940   sitd->max_sessions_next_record_offset = offset;
941 }
942
943 static void
944 nat_ipfix_logging_max_bib (u32 thread_index, u32 limit, int do_flush)
945 {
946   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
947   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
948   flow_report_main_t *frm = &flow_report_main;
949   vlib_frame_t *f;
950   vlib_buffer_t *b0 = 0;
951   u32 bi0 = ~0;
952   u32 offset;
953   vlib_main_t *vm = vlib_get_main ();
954   u64 now;
955   u8 nat_event = QUOTA_EXCEEDED;
956   u32 quota_event = clib_host_to_net_u32 (MAX_BIB_ENTRIES);
957   u16 template_id;
958
959   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
960   now += silm->milisecond_time_0;
961
962   b0 = sitd->max_bibs_buffer;
963
964   if (PREDICT_FALSE (b0 == 0))
965     {
966       if (do_flush)
967         return;
968
969       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
970         {
971           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
972           return;
973         }
974
975       b0 = sitd->max_bibs_buffer = vlib_get_buffer (vm, bi0);
976       offset = 0;
977     }
978   else
979     {
980       bi0 = vlib_get_buffer_index (vm, b0);
981       offset = sitd->max_bibs_next_record_offset;
982     }
983
984   f = sitd->max_bibs_frame;
985   if (PREDICT_FALSE (f == 0))
986     {
987       u32 *to_next;
988       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
989       sitd->max_bibs_frame = f;
990       to_next = vlib_frame_vector_args (f);
991       to_next[0] = bi0;
992       f->n_vectors = 1;
993     }
994
995   if (PREDICT_FALSE (offset == 0))
996     nat_ipfix_header_create (frm, b0, &offset);
997
998   if (PREDICT_TRUE (do_flush == 0))
999     {
1000       u64 time_stamp = clib_host_to_net_u64 (now);
1001       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1002       offset += sizeof (time_stamp);
1003
1004       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1005       offset += sizeof (nat_event);
1006
1007       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1008       offset += sizeof (quota_event);
1009
1010       limit = clib_host_to_net_u32 (limit);
1011       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
1012       offset += sizeof (limit);
1013
1014       b0->current_length += MAX_BIBS_LEN;
1015     }
1016
1017   if (PREDICT_FALSE
1018       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1019     {
1020       template_id = clib_atomic_fetch_or (
1021         &silm->max_bibs_template_id,
1022         0);
1023       nat_ipfix_send (frm, f, b0, template_id);
1024       sitd->max_bibs_frame = 0;
1025       sitd->max_bibs_buffer = 0;
1026       offset = 0;
1027     }
1028   sitd->max_bibs_next_record_offset = offset;
1029 }
1030
1031 static void
1032 nat_ipfix_logging_nat64_bibe (u32 thread_index, u8 nat_event,
1033                               ip6_address_t * src_ip, u32 nat_src_ip,
1034                               u8 proto, u16 src_port, u16 nat_src_port,
1035                               u32 vrf_id, int do_flush)
1036 {
1037   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1038   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1039   flow_report_main_t *frm = &flow_report_main;
1040   vlib_frame_t *f;
1041   vlib_buffer_t *b0 = 0;
1042   u32 bi0 = ~0;
1043   u32 offset;
1044   vlib_main_t *vm = vlib_get_main ();
1045   u64 now;
1046   u16 template_id;
1047
1048   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1049   now += silm->milisecond_time_0;
1050
1051   b0 = sitd->nat64_bib_buffer;
1052
1053   if (PREDICT_FALSE (b0 == 0))
1054     {
1055       if (do_flush)
1056         return;
1057
1058       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1059         {
1060           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1061           return;
1062         }
1063
1064       b0 = sitd->nat64_bib_buffer = vlib_get_buffer (vm, bi0);
1065       offset = 0;
1066     }
1067   else
1068     {
1069       bi0 = vlib_get_buffer_index (vm, b0);
1070       offset = sitd->nat64_bib_next_record_offset;
1071     }
1072
1073   f = sitd->nat64_bib_frame;
1074   if (PREDICT_FALSE (f == 0))
1075     {
1076       u32 *to_next;
1077       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1078       sitd->nat64_bib_frame = f;
1079       to_next = vlib_frame_vector_args (f);
1080       to_next[0] = bi0;
1081       f->n_vectors = 1;
1082     }
1083
1084   if (PREDICT_FALSE (offset == 0))
1085     nat_ipfix_header_create (frm, b0, &offset);
1086
1087   if (PREDICT_TRUE (do_flush == 0))
1088     {
1089       u64 time_stamp = clib_host_to_net_u64 (now);
1090       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1091       offset += sizeof (time_stamp);
1092
1093       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1094       offset += sizeof (nat_event);
1095
1096       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1097       offset += sizeof (ip6_address_t);
1098
1099       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1100       offset += sizeof (nat_src_ip);
1101
1102       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1103       offset += sizeof (proto);
1104
1105       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1106       offset += sizeof (src_port);
1107
1108       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1109       offset += sizeof (nat_src_port);
1110
1111       vrf_id = clib_host_to_net_u32 (vrf_id);
1112       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1113       offset += sizeof (vrf_id);
1114
1115       b0->current_length += NAT64_BIB_LEN;
1116     }
1117
1118   if (PREDICT_FALSE
1119       (do_flush || (offset + NAT64_BIB_LEN) > frm->path_mtu))
1120     {
1121       template_id = clib_atomic_fetch_or (
1122         &silm->nat64_bib_template_id,
1123         0);
1124       nat_ipfix_send (frm, f, b0, template_id);
1125       sitd->nat64_bib_frame = 0;
1126       sitd->nat64_bib_buffer = 0;
1127       offset = 0;
1128     }
1129   sitd->nat64_bib_next_record_offset = offset;
1130 }
1131
1132 static void
1133 nat_ipfix_logging_nat64_ses (u32 thread_index, u8 nat_event,
1134                              ip6_address_t * src_ip, u32 nat_src_ip,
1135                              u8 proto, u16 src_port, u16 nat_src_port,
1136                              ip6_address_t * dst_ip, u32 nat_dst_ip,
1137                              u16 dst_port, u16 nat_dst_port,
1138                              u32 vrf_id, int do_flush)
1139 {
1140   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1141   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1142   flow_report_main_t *frm = &flow_report_main;
1143   vlib_frame_t *f;
1144   vlib_buffer_t *b0 = 0;
1145   u32 bi0 = ~0;
1146   u32 offset;
1147   vlib_main_t *vm = vlib_get_main ();
1148   u64 now;
1149   u16 template_id;
1150
1151   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1152   now += silm->milisecond_time_0;
1153
1154   b0 = sitd->nat64_ses_buffer;
1155
1156   if (PREDICT_FALSE (b0 == 0))
1157     {
1158       if (do_flush)
1159         return;
1160
1161       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1162         {
1163           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1164           return;
1165         }
1166
1167       b0 = sitd->nat64_ses_buffer = vlib_get_buffer (vm, bi0);
1168       offset = 0;
1169     }
1170   else
1171     {
1172       bi0 = vlib_get_buffer_index (vm, b0);
1173       offset = sitd->nat64_ses_next_record_offset;
1174     }
1175
1176   f = sitd->nat64_ses_frame;
1177   if (PREDICT_FALSE (f == 0))
1178     {
1179       u32 *to_next;
1180       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1181       sitd->nat64_ses_frame = f;
1182       to_next = vlib_frame_vector_args (f);
1183       to_next[0] = bi0;
1184       f->n_vectors = 1;
1185     }
1186
1187   if (PREDICT_FALSE (offset == 0))
1188     nat_ipfix_header_create (frm, b0, &offset);
1189
1190   if (PREDICT_TRUE (do_flush == 0))
1191     {
1192       u64 time_stamp = clib_host_to_net_u64 (now);
1193       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1194       offset += sizeof (time_stamp);
1195
1196       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1197       offset += sizeof (nat_event);
1198
1199       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1200       offset += sizeof (ip6_address_t);
1201
1202       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1203       offset += sizeof (nat_src_ip);
1204
1205       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1206       offset += sizeof (proto);
1207
1208       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1209       offset += sizeof (src_port);
1210
1211       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1212       offset += sizeof (nat_src_port);
1213
1214       clib_memcpy_fast (b0->data + offset, dst_ip, sizeof (ip6_address_t));
1215       offset += sizeof (ip6_address_t);
1216
1217       clib_memcpy_fast (b0->data + offset, &nat_dst_ip, sizeof (nat_dst_ip));
1218       offset += sizeof (nat_dst_ip);
1219
1220       clib_memcpy_fast (b0->data + offset, &dst_port, sizeof (dst_port));
1221       offset += sizeof (dst_port);
1222
1223       clib_memcpy_fast (b0->data + offset, &nat_dst_port, sizeof (nat_dst_port));
1224       offset += sizeof (nat_dst_port);
1225
1226       vrf_id = clib_host_to_net_u32 (vrf_id);
1227       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1228       offset += sizeof (vrf_id);
1229
1230       b0->current_length += NAT64_SES_LEN;
1231     }
1232
1233   if (PREDICT_FALSE
1234       (do_flush || (offset + NAT64_SES_LEN) > frm->path_mtu))
1235     {
1236       template_id = clib_atomic_fetch_or (
1237         &silm->nat64_ses_template_id,
1238         0);
1239       nat_ipfix_send (frm, f, b0, template_id);
1240       sitd->nat64_ses_frame = 0;
1241       sitd->nat64_ses_buffer = 0;
1242       offset = 0;
1243     }
1244   sitd->nat64_ses_next_record_offset = offset;
1245 }
1246
1247 void
1248 nat_ipfix_flush (u32 thread_index)
1249 {
1250   int do_flush = 1;
1251
1252   nat_ipfix_logging_nat44_ses (thread_index,
1253                                 0, 0, 0, 0, 0, 0, 0, do_flush);
1254   nat_ipfix_logging_addr_exhausted (thread_index, 0, do_flush);
1255   nat_ipfix_logging_max_entries_per_usr (thread_index, 0, 0, do_flush);
1256   nat_ipfix_logging_max_ses (thread_index, 0, do_flush);
1257   nat_ipfix_logging_max_bib (thread_index, 0, do_flush);
1258   nat_ipfix_logging_nat64_bibe (thread_index,
1259                                 0, 0, 0, 0, 0, 0, 0, do_flush);
1260   nat_ipfix_logging_nat64_ses (thread_index,
1261                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, do_flush);
1262 }
1263
1264 int
1265 nat_ipfix_logging_enabled ()
1266 {
1267   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1268   return !clib_atomic_fetch_or(&silm->enabled, 0);
1269 }
1270
1271 void
1272 nat_ipfix_flush_from_main (void)
1273 {
1274   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1275   vlib_main_t *worker_vm;
1276   int i;
1277
1278   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))
1279     return;
1280
1281   if (PREDICT_FALSE (!silm->worker_vms))
1282     {
1283       for (i = 1; i < vlib_get_n_threads (); i++)
1284         {
1285           worker_vm = vlib_get_main_by_index (i);
1286           if (worker_vm)
1287             vec_add1 (silm->worker_vms, worker_vm);
1288         }
1289     }
1290
1291   /* Trigger flush for each worker thread */
1292   for (i = 0; i < vec_len (silm->worker_vms); i++)
1293     {
1294       worker_vm = silm->worker_vms[i];
1295       if (worker_vm)
1296         vlib_node_set_interrupt_pending (worker_vm,
1297                                          nat_ipfix_flush_node.index);
1298     }
1299
1300   /* Finally flush main thread */
1301   nat_ipfix_flush (0);
1302 }
1303
1304 /**
1305  * @brief Generate NAT44 session create event
1306  */
1307 void
1308 nat_ipfix_logging_nat44_ses_create (u32 thread_index, u32 src_ip,
1309                                     u32 nat_src_ip, ip_protocol_t proto,
1310                                     u16 src_port, u16 nat_src_port,
1311                                     u32 fib_index)
1312 {
1313   skip_if_disabled ();
1314
1315   nat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_CREATE, src_ip,
1316                                nat_src_ip, proto, src_port, nat_src_port,
1317                                fib_index, 0);
1318 }
1319
1320 /**
1321  * @brief Generate NAT44 session delete event
1322  */
1323 void
1324 nat_ipfix_logging_nat44_ses_delete (u32 thread_index, u32 src_ip,
1325                                     u32 nat_src_ip, ip_protocol_t proto,
1326                                     u16 src_port, u16 nat_src_port,
1327                                     u32 fib_index)
1328 {
1329   skip_if_disabled ();
1330
1331   nat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_DELETE, src_ip,
1332                                nat_src_ip, proto, src_port, nat_src_port,
1333                                fib_index, 0);
1334 }
1335
1336 /**
1337  * @brief Generate NAT addresses exhausted event
1338  *
1339  * @param thread_index thread index
1340  * @param pool_id NAT pool ID
1341  */
1342 void
1343 nat_ipfix_logging_addresses_exhausted (u32 thread_index, u32 pool_id)
1344 {
1345   //TODO: This event SHOULD be rate limited
1346   skip_if_disabled ();
1347
1348   nat_ipfix_logging_addr_exhausted (thread_index, pool_id, 0);
1349 }
1350
1351 /**
1352  * @brief Generate maximum entries per user exceeded event
1353  *
1354  * @param thread_index thread index
1355  * @param limit maximum NAT entries that can be created per user
1356  * @param src_ip source IPv4 address
1357  */
1358 void
1359 nat_ipfix_logging_max_entries_per_user (u32 thread_index, u32 limit, u32 src_ip)
1360 {
1361   //TODO: This event SHOULD be rate limited
1362   skip_if_disabled ();
1363
1364   nat_ipfix_logging_max_entries_per_usr (thread_index, limit, src_ip, 0);
1365 }
1366
1367 vlib_frame_t *
1368 deterministic_nat_data_callback
1369 (flow_report_main_t * frm,
1370                                         flow_report_t * fr,
1371                                         vlib_frame_t * f,
1372                                         u32 * to_next, u32 node_index)
1373 {
1374   nat_ipfix_flush_from_main();
1375
1376   return f;
1377 }
1378
1379 /**
1380  * @brief Generate maximum session entries exceeded event
1381  *
1382  * @param thread_index thread index
1383  * @param limit configured limit
1384  */
1385 void
1386 nat_ipfix_logging_max_sessions (u32 thread_index, u32 limit)
1387 {
1388   //TODO: This event SHOULD be rate limited
1389   skip_if_disabled ();
1390
1391   nat_ipfix_logging_max_ses (thread_index, limit, 0);
1392 }
1393
1394 /**
1395  * @brief Generate maximum BIB entries exceeded event
1396  *
1397  * @param thread_index thread index
1398  * @param limit configured limit
1399  */
1400 void
1401 nat_ipfix_logging_max_bibs (u32 thread_index, u32 limit)
1402 {
1403   //TODO: This event SHOULD be rate limited
1404   skip_if_disabled ();
1405
1406   nat_ipfix_logging_max_bib (thread_index, limit, 0);
1407 }
1408
1409 /**
1410  * @brief Generate NAT64 BIB create and delete events
1411  *
1412  * @param thread_index thread index
1413  * @param src_ip       source IPv6 address
1414  * @param nat_src_ip   transaltes source IPv4 address
1415  * @param proto        L4 protocol
1416  * @param src_port     source port
1417  * @param nat_src_port translated source port
1418  * @param vrf_id       VRF ID
1419  * @param is_create    non-zero value if create event otherwise delete event
1420  */
1421 void
1422 nat_ipfix_logging_nat64_bib (u32 thread_index, ip6_address_t * src_ip,
1423                              ip4_address_t * nat_src_ip, u8 proto,
1424                              u16 src_port, u16 nat_src_port, u32 vrf_id,
1425                              u8 is_create)
1426 {
1427   u8 nat_event;
1428
1429   skip_if_disabled ();
1430
1431   nat_event = is_create ? NAT64_BIB_CREATE : NAT64_BIB_DELETE;
1432
1433   nat_ipfix_logging_nat64_bibe (thread_index, nat_event, src_ip,
1434                                 nat_src_ip->as_u32, proto, src_port,
1435                                 nat_src_port, vrf_id, 0);
1436 }
1437
1438 /**
1439  * @brief Generate NAT64 session create and delete events
1440  *
1441  * @param thread_index thread index
1442  * @param src_ip       source IPv6 address
1443  * @param nat_src_ip   transaltes source IPv4 address
1444  * @param proto        L4 protocol
1445  * @param src_port     source port
1446  * @param nat_src_port translated source port
1447  * @param dst_ip       destination IPv6 address
1448  * @param nat_dst_ip   destination IPv4 address
1449  * @param dst_port     destination port
1450  * @param nat_dst_port translated destination port
1451  * @param vrf_id       VRF ID
1452  * @param is_create    non-zero value if create event otherwise delete event
1453  */
1454 void
1455 nat_ipfix_logging_nat64_session (u32 thread_index,
1456                                  ip6_address_t * src_ip,
1457                                  ip4_address_t * nat_src_ip, u8 proto,
1458                                  u16 src_port, u16 nat_src_port,
1459                                  ip6_address_t * dst_ip,
1460                                  ip4_address_t * nat_dst_ip, u16 dst_port,
1461                                  u16 nat_dst_port, u32 vrf_id, u8 is_create)
1462 {
1463   u8 nat_event;
1464
1465   skip_if_disabled ();
1466
1467   nat_event = is_create ? NAT64_SESSION_CREATE : NAT64_SESSION_DELETE;
1468
1469   nat_ipfix_logging_nat64_ses (thread_index, nat_event, src_ip,
1470                                nat_src_ip->as_u32, proto, src_port,
1471                                nat_src_port, dst_ip, nat_dst_ip->as_u32,
1472                                dst_port, nat_dst_port, vrf_id, 0);
1473 }
1474
1475 vlib_frame_t *
1476 data_callback (flow_report_main_t * frm, flow_report_t * fr,
1477                vlib_frame_t * f, u32 * to_next, u32 node_index)
1478 {
1479   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1480
1481   if (PREDICT_FALSE (++silm->call_counter >= vec_len (frm->reports)))
1482     {
1483       nat_ipfix_flush_from_main();
1484       silm->call_counter = 0;
1485     }
1486
1487   return f;
1488 }
1489
1490 /**
1491  * @brief Enable/disable NAT plugin IPFIX logging
1492  *
1493  * @param enable    1 if enable, 0 if disable
1494  * @param domain_id observation domain ID
1495  * @param src_port  source port number
1496  *
1497  * @returns 0 if success
1498  */
1499 int
1500 nat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
1501 {
1502   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1503   flow_report_main_t *frm = &flow_report_main;
1504   vnet_flow_report_add_del_args_t a;
1505   int rv;
1506   u8 e = enable ? 1 : 0;
1507
1508   if (clib_atomic_cmp_and_swap (&silm->enabled, e ^ 1, e) == e)
1509     return 0;
1510
1511   clib_memset (&a, 0, sizeof (a));
1512   a.is_add = enable;
1513   a.domain_id = domain_id ? domain_id : 1;
1514   a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
1515   a.flow_data_callback = data_callback;
1516
1517   a.rewrite_callback = nat_template_rewrite_nat44_session;
1518   rv = vnet_flow_report_add_del (frm, &a, NULL);
1519   if (rv)
1520     {
1521       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1522       return -1;
1523     }
1524
1525   a.rewrite_callback = nat_template_rewrite_addr_exhausted;
1526   rv = vnet_flow_report_add_del (frm, &a, NULL);
1527   if (rv)
1528     {
1529       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1530       return -1;
1531     }
1532
1533   a.rewrite_callback = nat_template_rewrite_max_sessions;
1534   rv = vnet_flow_report_add_del (frm, &a, NULL);
1535   if (rv)
1536     {
1537       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1538       return -1;
1539     }
1540
1541   a.rewrite_callback = nat_template_rewrite_max_bibs;
1542   rv = vnet_flow_report_add_del (frm, &a, NULL);
1543   if (rv)
1544     {
1545       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1546       return -1;
1547     }
1548
1549   a.rewrite_callback = nat_template_rewrite_nat64_bib;
1550   rv = vnet_flow_report_add_del (frm, &a, NULL);
1551   if (rv)
1552     {
1553       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1554       return -1;
1555     }
1556
1557   a.rewrite_callback = nat_template_rewrite_nat64_session;
1558   rv = vnet_flow_report_add_del (frm, &a, NULL);
1559   if (rv)
1560     {
1561       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1562       return -1;
1563     }
1564
1565   // if endpoint dependent per user max entries is also required
1566   /*
1567   a.rewrite_callback = nat_template_rewrite_max_entries_per_usr;
1568   rv = vnet_flow_report_add_del (frm, &a, NULL);
1569   if (rv)
1570     {
1571       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1572       return -1;
1573     }
1574   */
1575
1576   return 0;
1577 }
1578
1579 /**
1580  * @brief Initialize NAT plugin IPFIX logging
1581  *
1582  * @param vm vlib main
1583  */
1584 void
1585 nat_ipfix_logging_init (vlib_main_t * vm)
1586 {
1587   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
1588   vlib_thread_main_t *tm = vlib_get_thread_main ();
1589
1590   silm->enabled = 0;
1591   silm->worker_vms = 0;
1592   silm->call_counter = 0;
1593
1594   /* Set up time reference pair */
1595   silm->vlib_time_0 = vlib_time_now (vm);
1596   silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
1597
1598   vec_validate (silm->per_thread_data, tm->n_vlib_mains - 1);
1599 }
1600
1601 static uword
1602 ipfix_flush_process (vlib_main_t *vm,
1603                      vlib_node_runtime_t *rt,
1604                      vlib_frame_t *f)
1605 {
1606   nat_ipfix_flush(vm->thread_index);
1607   return 0;
1608 }
1609
1610 /* *INDENT-OFF* */
1611 VLIB_REGISTER_NODE (nat_ipfix_flush_node) = {
1612   .function = ipfix_flush_process,
1613   .name = "nat-ipfix-flush",
1614   .type = VLIB_NODE_TYPE_INPUT,
1615   .state = VLIB_NODE_STATE_INTERRUPT,
1616 };
1617 /* *INDENT-ON* */