nat: move deterministic nat to det44 sub feature
[vpp.git] / src / plugins / nat / nat_ipfix_logging.c
1 /*
2  * nat_ipfix_logging.c - NAT Events IPFIX logging
3  *
4  * Copyright (c) 2016 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <vnet/ipfix-export/flow_report.h>
19 #include <vlibmemory/api.h>
20 #include <nat/nat_inlines.h>
21 #include <nat/nat_ipfix_logging.h>
22 #include <vppinfra/atomics.h>
23
24 vlib_node_registration_t snat_ipfix_flush_node;
25 snat_ipfix_logging_main_t snat_ipfix_logging_main;
26
27 #define NAT44_SESSION_CREATE_LEN 26
28 #define NAT_ADDRESSES_EXHAUTED_LEN 13
29 #define MAX_ENTRIES_PER_USER_LEN 21
30 #define MAX_SESSIONS_LEN 17
31 #define MAX_BIBS_LEN 17
32 #define MAX_FRAGMENTS_IP4_LEN 21
33 #define MAX_FRAGMENTS_IP6_LEN 33
34 #define NAT64_BIB_LEN 38
35 #define NAT64_SES_LEN 62
36
37 #define NAT44_SESSION_CREATE_FIELD_COUNT 8
38 #define NAT_ADDRESSES_EXHAUTED_FIELD_COUNT 3
39 #define MAX_ENTRIES_PER_USER_FIELD_COUNT 5
40 #define MAX_SESSIONS_FIELD_COUNT 4
41 #define MAX_BIBS_FIELD_COUNT 4
42 #define MAX_FRAGMENTS_FIELD_COUNT 5
43 #define NAT64_BIB_FIELD_COUNT 8
44 #define NAT64_SES_FIELD_COUNT 12
45
46 typedef struct
47 {
48   u8 nat_event;
49   u32 src_ip;
50   u32 nat_src_ip;
51   nat_protocol_t nat_proto;
52   u16 src_port;
53   u16 nat_src_port;
54   u32 vrf_id;
55 } snat_ipfix_logging_nat44_ses_args_t;
56
57 typedef struct
58 {
59   u32 pool_id;
60 } snat_ipfix_logging_addr_exhausted_args_t;
61
62 typedef struct
63 {
64   u32 limit;
65   u32 src_ip;
66 } snat_ipfix_logging_max_entries_per_user_args_t;
67
68 typedef struct
69 {
70   u32 limit;
71 } nat_ipfix_logging_max_sessions_args_t;
72
73 typedef struct
74 {
75   u32 limit;
76 } nat_ipfix_logging_max_bibs_args_t;
77
78 typedef struct
79 {
80   u32 limit;
81   u32 src;
82 } nat_ipfix_logging_max_frags_ip4_args_t;
83
84 typedef struct
85 {
86   u32 limit;
87   u64 src[2];
88 } nat_ipfix_logging_max_frags_ip6_args_t;
89
90 typedef struct
91 {
92   u8 nat_event;
93   u64 src_ip[2];
94   u32 nat_src_ip;
95   u8 proto;
96   u16 src_port;
97   u16 nat_src_port;
98   u64 dst_ip[2];
99   u32 nat_dst_ip;
100   u32 vrf_id;
101   u16 dst_port;
102   u16 nat_dst_port;
103 } nat_ipfix_logging_nat64_ses_args_t;
104
105 typedef struct
106 {
107   u8 nat_event;
108   u64 src_ip[2];
109   u32 nat_src_ip;
110   u8 proto;
111   u16 src_port;
112   u16 nat_src_port;
113   u32 vrf_id;
114 } nat_ipfix_logging_nat64_bib_args_t;
115
116 #define skip_if_disabled()                                        \
117 do {                                                              \
118   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;     \
119   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))    \
120     return;                                                       \
121 } while (0)
122
123 #define update_template_id(old_id, new_id)                \
124 do {                                                      \
125   u16 template_id = clib_atomic_fetch_or(old_id, 0);      \
126   clib_atomic_cmp_and_swap(old_id, template_id, new_id);  \
127 } while (0)
128
129 /**
130  * @brief Create an IPFIX template packet rewrite string
131  *
132  * @param frm               flow report main
133  * @param fr                flow report
134  * @param collector_address collector address
135  * @param src_address       source address
136  * @param collector_port    collector
137  * @param event             NAT event ID
138  * @param quota_event       NAT quota exceeded event ID
139  *
140  * @returns template packet
141  */
142 static inline u8 *
143 snat_template_rewrite (flow_report_main_t * frm,
144                        flow_report_t * fr,
145                        ip4_address_t * collector_address,
146                        ip4_address_t * src_address,
147                        u16 collector_port,
148                        nat_event_t event, quota_exceed_event_t quota_event)
149 {
150   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
151   ip4_header_t *ip;
152   udp_header_t *udp;
153   ipfix_message_header_t *h;
154   ipfix_set_header_t *s;
155   ipfix_template_header_t *t;
156   ipfix_field_specifier_t *f;
157   ipfix_field_specifier_t *first_field;
158   u8 *rewrite = 0;
159   ip4_ipfix_template_packet_t *tp;
160   u32 field_count = 0;
161   flow_report_stream_t *stream;
162   u32 stream_index;
163
164   stream = &frm->streams[fr->stream_index];
165
166   stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
167   clib_atomic_cmp_and_swap (&silm->stream_index,
168                             stream_index, fr->stream_index);
169
170   if (event == NAT_ADDRESSES_EXHAUTED)
171     {
172       field_count = NAT_ADDRESSES_EXHAUTED_FIELD_COUNT;
173
174       update_template_id(&silm->addr_exhausted_template_id,
175                          fr->template_id);
176     }
177   else if (event == NAT44_SESSION_CREATE)
178     {
179       field_count = NAT44_SESSION_CREATE_FIELD_COUNT;
180
181       update_template_id(&silm->nat44_session_template_id,
182                          fr->template_id);
183     }
184   else if (event == NAT64_BIB_CREATE)
185     {
186       field_count = NAT64_BIB_FIELD_COUNT;
187
188       update_template_id(&silm->nat64_bib_template_id,
189                          fr->template_id);
190     }
191   else if (event == NAT64_SESSION_CREATE)
192     {
193       field_count = NAT64_SES_FIELD_COUNT;
194
195       update_template_id(&silm->nat64_ses_template_id,
196                          fr->template_id);
197     }
198   else if (event == QUOTA_EXCEEDED)
199     {
200       if (quota_event == MAX_ENTRIES_PER_USER)
201         {
202           field_count = MAX_ENTRIES_PER_USER_FIELD_COUNT;
203
204           update_template_id(&silm->max_entries_per_user_template_id,
205                              fr->template_id);
206
207         }
208       else if (quota_event == MAX_SESSION_ENTRIES)
209         {
210           field_count = MAX_SESSIONS_FIELD_COUNT;
211
212           update_template_id(&silm->max_sessions_template_id,
213                              fr->template_id);
214         }
215       else if (quota_event == MAX_BIB_ENTRIES)
216         {
217           field_count = MAX_BIBS_FIELD_COUNT;
218
219           update_template_id(&silm->max_bibs_template_id,
220                              fr->template_id);
221         }
222     }
223
224   /* allocate rewrite space */
225   vec_validate_aligned (rewrite,
226                         sizeof (ip4_ipfix_template_packet_t)
227                         + field_count * sizeof (ipfix_field_specifier_t) - 1,
228                         CLIB_CACHE_LINE_BYTES);
229
230   tp = (ip4_ipfix_template_packet_t *) rewrite;
231   ip = (ip4_header_t *) & tp->ip4;
232   udp = (udp_header_t *) (ip + 1);
233   h = (ipfix_message_header_t *) (udp + 1);
234   s = (ipfix_set_header_t *) (h + 1);
235   t = (ipfix_template_header_t *) (s + 1);
236   first_field = f = (ipfix_field_specifier_t *) (t + 1);
237
238   ip->ip_version_and_header_length = 0x45;
239   ip->ttl = 254;
240   ip->protocol = IP_PROTOCOL_UDP;
241   ip->src_address.as_u32 = src_address->as_u32;
242   ip->dst_address.as_u32 = collector_address->as_u32;
243   udp->src_port = clib_host_to_net_u16 (stream->src_port);
244   udp->dst_port = clib_host_to_net_u16 (collector_port);
245   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
246
247   /* FIXUP: message header export_time */
248   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
249
250   /* Add TLVs to the template */
251   if (event == NAT_ADDRESSES_EXHAUTED)
252     {
253       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
254       f++;
255       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
256       f++;
257       f->e_id_length = ipfix_e_id_length (0, natPoolId, 4);
258       f++;
259     }
260   else if (event == NAT44_SESSION_CREATE)
261     {
262       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
263       f++;
264       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
265       f++;
266       f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
267       f++;
268       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
269       f++;
270       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
271       f++;
272       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
273       f++;
274       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
275       f++;
276       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
277       f++;
278     }
279   else if (event == NAT64_BIB_CREATE)
280     {
281       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
282       f++;
283       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
284       f++;
285       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
286       f++;
287       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
288       f++;
289       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
290       f++;
291       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
292       f++;
293       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
294       f++;
295       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
296       f++;
297     }
298   else if (event == NAT64_SESSION_CREATE)
299     {
300       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
301       f++;
302       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
303       f++;
304       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
305       f++;
306       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
307       f++;
308       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
309       f++;
310       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
311       f++;
312       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
313       f++;
314       f->e_id_length = ipfix_e_id_length (0, destinationIPv6Address, 16);
315       f++;
316       f->e_id_length = ipfix_e_id_length (0, postNATDestinationIPv4Address, 4);
317       f++;
318       f->e_id_length = ipfix_e_id_length (0, destinationTransportPort, 2);
319       f++;
320       f->e_id_length = ipfix_e_id_length (0, postNAPTDestinationTransportPort,
321                                           2);
322       f++;
323       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
324       f++;
325     }
326   else if (event == QUOTA_EXCEEDED)
327     {
328       if (quota_event == MAX_ENTRIES_PER_USER)
329         {
330           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
331                                               8);
332           f++;
333           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
334           f++;
335           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
336           f++;
337           f->e_id_length = ipfix_e_id_length (0, maxEntriesPerUser, 4);
338           f++;
339           f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
340           f++;
341         }
342       else if (quota_event == MAX_SESSION_ENTRIES)
343         {
344           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
345                                               8);
346           f++;
347           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
348           f++;
349           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
350           f++;
351           f->e_id_length = ipfix_e_id_length (0, maxSessionEntries, 4);
352           f++;
353         }
354       else if (quota_event == MAX_BIB_ENTRIES)
355         {
356           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
357                                               8);
358           f++;
359           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
360           f++;
361           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
362           f++;
363           f->e_id_length = ipfix_e_id_length (0, maxBIBEntries, 4);
364           f++;
365         }
366     }
367
368   /* Back to the template packet... */
369   ip = (ip4_header_t *) & tp->ip4;
370   udp = (udp_header_t *) (ip + 1);
371
372   ASSERT (f - first_field);
373   /* Field count in this template */
374   t->id_count = ipfix_id_count (fr->template_id, f - first_field);
375
376   /* set length in octets */
377   s->set_id_length =
378     ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
379
380   /* message length in octets */
381   h->version_length = version_length ((u8 *) f - (u8 *) h);
382
383   ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
384   ip->checksum = ip4_header_checksum (ip);
385
386   return rewrite;
387 }
388
389 u8 *
390 snat_template_rewrite_addr_exhausted (flow_report_main_t * frm,
391                                       flow_report_t * fr,
392                                       ip4_address_t * collector_address,
393                                       ip4_address_t * src_address,
394                                       u16 collector_port,
395                                       ipfix_report_element_t *elts,
396                                       u32 n_elts, u32 *stream_index)
397 {
398   return snat_template_rewrite (frm, fr, collector_address, src_address,
399                                 collector_port, NAT_ADDRESSES_EXHAUTED, 0);
400 }
401
402 u8 *
403 snat_template_rewrite_nat44_session (flow_report_main_t * frm,
404                                      flow_report_t * fr,
405                                      ip4_address_t * collector_address,
406                                      ip4_address_t * src_address,
407                                      u16 collector_port,
408                                      ipfix_report_element_t *elts,
409                                      u32 n_elts, u32 *stream_index)
410 {
411   return snat_template_rewrite (frm, fr, collector_address, src_address,
412                                 collector_port, NAT44_SESSION_CREATE, 0);
413 }
414
415 u8 *
416 snat_template_rewrite_max_entries_per_usr (flow_report_main_t * frm,
417                                            flow_report_t * fr,
418                                            ip4_address_t * collector_address,
419                                            ip4_address_t * src_address,
420                                            u16 collector_port,
421                                            ipfix_report_element_t *elts,
422                                            u32 n_elts, u32 *stream_index)
423 {
424   return snat_template_rewrite (frm, fr, collector_address, src_address,
425                                 collector_port, QUOTA_EXCEEDED,
426                                 MAX_ENTRIES_PER_USER);
427 }
428
429 u8 *
430 nat_template_rewrite_max_sessions (flow_report_main_t * frm,
431                                    flow_report_t * fr,
432                                    ip4_address_t * collector_address,
433                                    ip4_address_t * src_address,
434                                    u16 collector_port,
435                                    ipfix_report_element_t *elts,
436                                    u32 n_elts, u32 *stream_index)
437 {
438   return snat_template_rewrite (frm, fr, collector_address, src_address,
439                                 collector_port, QUOTA_EXCEEDED,
440                                 MAX_SESSION_ENTRIES);
441 }
442
443 u8 *
444 nat_template_rewrite_max_bibs (flow_report_main_t * frm,
445                                flow_report_t * fr,
446                                ip4_address_t * collector_address,
447                                ip4_address_t * src_address,
448                                u16 collector_port,
449                                ipfix_report_element_t *elts,
450                                u32 n_elts, u32 *stream_index)
451 {
452   return snat_template_rewrite (frm, fr, collector_address, src_address,
453                                 collector_port, QUOTA_EXCEEDED,
454                                 MAX_BIB_ENTRIES);
455 }
456
457 u8 *
458 nat_template_rewrite_nat64_bib (flow_report_main_t * frm,
459                                 flow_report_t * fr,
460                                 ip4_address_t * collector_address,
461                                 ip4_address_t * src_address,
462                                 u16 collector_port,
463                                 ipfix_report_element_t *elts,
464                                 u32 n_elts, u32 *stream_index)
465 {
466   return snat_template_rewrite (frm, fr, collector_address, src_address,
467                                 collector_port, NAT64_BIB_CREATE, 0);
468 }
469
470 u8 *
471 nat_template_rewrite_nat64_session (flow_report_main_t * frm,
472                                     flow_report_t * fr,
473                                     ip4_address_t * collector_address,
474                                     ip4_address_t * src_address,
475                                     u16 collector_port,
476                                     ipfix_report_element_t *elts,
477                                     u32 n_elts, u32 *stream_index)
478 {
479   return snat_template_rewrite (frm, fr, collector_address, src_address,
480                                 collector_port, NAT64_SESSION_CREATE, 0);
481 }
482
483 static inline void
484 snat_ipfix_header_create (flow_report_main_t * frm,
485                           vlib_buffer_t * b0, u32 * offset)
486 {
487   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
488   flow_report_stream_t *stream;
489   ip4_ipfix_template_packet_t *tp;
490   ipfix_message_header_t *h = 0;
491   ipfix_set_header_t *s = 0;
492   u32 sequence_number;
493   u32 stream_index;
494   ip4_header_t *ip;
495   udp_header_t *udp;
496   vlib_main_t *vm = vlib_get_main ();
497   
498   stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
499   stream = &frm->streams[stream_index];
500
501   b0->current_data = 0;
502   b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
503     sizeof (*s);
504   b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_FLOW_REPORT);
505   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
506   vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
507   tp = vlib_buffer_get_current (b0);
508   ip = (ip4_header_t *) & tp->ip4;
509   udp = (udp_header_t *) (ip + 1);
510   h = (ipfix_message_header_t *) (udp + 1);
511   s = (ipfix_set_header_t *) (h + 1);
512
513   ip->ip_version_and_header_length = 0x45;
514   ip->ttl = 254;
515   ip->protocol = IP_PROTOCOL_UDP;
516   ip->flags_and_fragment_offset = 0;
517   ip->src_address.as_u32 = frm->src_address.as_u32;
518   ip->dst_address.as_u32 = frm->ipfix_collector.as_u32;
519   udp->src_port = clib_host_to_net_u16 (stream->src_port);
520   udp->dst_port = clib_host_to_net_u16 (frm->collector_port);
521   udp->checksum = 0;
522
523   h->export_time = clib_host_to_net_u32 ((u32)
524                                          (((f64) frm->unix_time_0) +
525                                           (vlib_time_now (vm) -
526                                            frm->vlib_time_0)));
527
528   sequence_number = clib_atomic_fetch_add (&stream->sequence_number, 1);
529   h->sequence_number = clib_host_to_net_u32 (sequence_number);
530   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
531
532   *offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
533 }
534
535 static inline void
536 snat_ipfix_send (u32 thread_index, flow_report_main_t * frm,
537                  vlib_frame_t * f, vlib_buffer_t * b0, u16 template_id)
538 {
539   ip4_ipfix_template_packet_t *tp;
540   ipfix_message_header_t *h = 0;
541   ipfix_set_header_t *s = 0;
542   ip4_header_t *ip;
543   udp_header_t *udp;
544   vlib_main_t *vm = vlib_mains[thread_index];
545
546   tp = vlib_buffer_get_current (b0);
547   ip = (ip4_header_t *) & tp->ip4;
548   udp = (udp_header_t *) (ip + 1);
549   h = (ipfix_message_header_t *) (udp + 1);
550   s = (ipfix_set_header_t *) (h + 1);
551
552   s->set_id_length = ipfix_set_id_length (template_id,
553                                           b0->current_length -
554                                           (sizeof (*ip) + sizeof (*udp) +
555                                            sizeof (*h)));
556   h->version_length = version_length (b0->current_length -
557                                       (sizeof (*ip) + sizeof (*udp)));
558
559   ip->length = clib_host_to_net_u16 (b0->current_length);
560   ip->checksum = ip4_header_checksum (ip);
561   udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
562
563   if (frm->udp_checksum)
564     {
565       udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
566       if (udp->checksum == 0)
567         udp->checksum = 0xffff;
568     }
569
570   ASSERT (ip->checksum == ip4_header_checksum (ip));
571
572   vlib_put_frame_to_node (vm, ip4_lookup_node.index, f);
573 }
574
575 static void
576 snat_ipfix_logging_nat44_ses (u32 thread_index, u8 nat_event, u32 src_ip,
577                               u32 nat_src_ip, nat_protocol_t nat_proto,
578                               u16 src_port, u16 nat_src_port, u32 vrf_id,
579                               int do_flush)
580 {
581   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
582   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
583   flow_report_main_t *frm = &flow_report_main;
584   vlib_frame_t *f;
585   vlib_buffer_t *b0 = 0;
586   u32 bi0 = ~0;
587   u32 offset;
588   vlib_main_t *vm = vlib_mains[thread_index];
589   u64 now;
590   u8 proto;
591   u16 template_id;
592
593   proto = nat_proto_to_ip_proto (nat_proto);
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       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
613       offset = 0;
614     }
615   else
616     {
617       bi0 = vlib_get_buffer_index (vm, b0);
618       offset = sitd->nat44_session_next_record_offset;
619     }
620
621   f = sitd->nat44_session_frame;
622   if (PREDICT_FALSE (f == 0))
623     {
624       u32 *to_next;
625       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
626       sitd->nat44_session_frame = f;
627       to_next = vlib_frame_vector_args (f);
628       to_next[0] = bi0;
629       f->n_vectors = 1;
630     }
631
632   if (PREDICT_FALSE (offset == 0))
633     snat_ipfix_header_create (frm, b0, &offset);
634
635   if (PREDICT_TRUE (do_flush == 0))
636     {
637       u64 time_stamp = clib_host_to_net_u64 (now);
638       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
639       offset += sizeof (time_stamp);
640
641       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
642       offset += sizeof (nat_event);
643
644       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
645       offset += sizeof (src_ip);
646
647       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
648       offset += sizeof (nat_src_ip);
649
650       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
651       offset += sizeof (proto);
652
653       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
654       offset += sizeof (src_port);
655
656       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
657       offset += sizeof (nat_src_port);
658
659       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
660       offset += sizeof (vrf_id);
661
662       b0->current_length += NAT44_SESSION_CREATE_LEN;
663     }
664
665   if (PREDICT_FALSE
666       (do_flush || (offset + NAT44_SESSION_CREATE_LEN) > frm->path_mtu))
667     {
668       template_id = clib_atomic_fetch_or (
669         &silm->nat44_session_template_id,
670         0);
671       snat_ipfix_send (thread_index, frm, f, b0, template_id);
672       sitd->nat44_session_frame = 0;
673       sitd->nat44_session_buffer = 0;
674       offset = 0;
675     }
676   sitd->nat44_session_next_record_offset = offset;
677 }
678
679 static void
680 snat_ipfix_logging_addr_exhausted (u32 thread_index, u32 pool_id, int do_flush)
681 {
682   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
683   snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
684   flow_report_main_t *frm = &flow_report_main;
685   vlib_frame_t *f;
686   vlib_buffer_t *b0 = 0;
687   u32 bi0 = ~0;
688   u32 offset;
689   vlib_main_t *vm = vlib_mains[thread_index];
690   u64 now;
691   u8 nat_event = NAT_ADDRESSES_EXHAUTED;
692   u16 template_id;
693
694   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
695   now += silm->milisecond_time_0;
696
697   b0 = sitd->addr_exhausted_buffer;
698
699   if (PREDICT_FALSE (b0 == 0))
700     {
701       if (do_flush)
702         return;
703
704       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
705         {
706           nat_elog_err ("can't allocate buffer for NAT IPFIX event");
707           return;
708         }
709
710       b0 = sitd->addr_exhausted_buffer = vlib_get_buffer (vm, bi0);
711       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
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     snat_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       snat_ipfix_send (thread_index, 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 snat_ipfix_logging_max_entries_per_usr (u32 thread_index,
765                                         u32 limit, u32 src_ip, int do_flush)
766 {
767   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
768   snat_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_mains[thread_index];
775   u64 now;
776   u8 nat_event = QUOTA_EXCEEDED;
777   u32 quota_event = 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       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
798       offset = 0;
799     }
800   else
801     {
802       bi0 = vlib_get_buffer_index (vm, b0);
803       offset = sitd->max_entries_per_user_next_record_offset;
804     }
805
806   f = sitd->max_entries_per_user_frame;
807   if (PREDICT_FALSE (f == 0))
808     {
809       u32 *to_next;
810       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
811       sitd->max_entries_per_user_frame = f;
812       to_next = vlib_frame_vector_args (f);
813       to_next[0] = bi0;
814       f->n_vectors = 1;
815     }
816
817   if (PREDICT_FALSE (offset == 0))
818     snat_ipfix_header_create (frm, b0, &offset);
819
820   if (PREDICT_TRUE (do_flush == 0))
821     {
822       u64 time_stamp = clib_host_to_net_u64 (now);
823       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
824       offset += sizeof (time_stamp);
825
826       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
827       offset += sizeof (nat_event);
828
829       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
830       offset += sizeof (quota_event);
831
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       snat_ipfix_send (thread_index, 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   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
859   snat_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_mains[thread_index];
866   u64 now;
867   u8 nat_event = QUOTA_EXCEEDED;
868   u32 quota_event = 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       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
889       offset = 0;
890     }
891   else
892     {
893       bi0 = vlib_get_buffer_index (vm, b0);
894       offset = sitd->max_sessions_next_record_offset;
895     }
896
897   f = sitd->max_sessions_frame;
898   if (PREDICT_FALSE (f == 0))
899     {
900       u32 *to_next;
901       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
902       sitd->max_sessions_frame = f;
903       to_next = vlib_frame_vector_args (f);
904       to_next[0] = bi0;
905       f->n_vectors = 1;
906     }
907
908   if (PREDICT_FALSE (offset == 0))
909     snat_ipfix_header_create (frm, b0, &offset);
910
911   if (PREDICT_TRUE (do_flush == 0))
912     {
913       u64 time_stamp = clib_host_to_net_u64 (now);
914       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
915       offset += sizeof (time_stamp);
916
917       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
918       offset += sizeof (nat_event);
919
920       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
921       offset += sizeof (quota_event);
922
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       snat_ipfix_send (thread_index, 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   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
947   snat_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_mains[thread_index];
954   u64 now;
955   u8 nat_event = QUOTA_EXCEEDED;
956   u32 quota_event = 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       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
977       offset = 0;
978     }
979   else
980     {
981       bi0 = vlib_get_buffer_index (vm, b0);
982       offset = sitd->max_bibs_next_record_offset;
983     }
984
985   f = sitd->max_bibs_frame;
986   if (PREDICT_FALSE (f == 0))
987     {
988       u32 *to_next;
989       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
990       sitd->max_bibs_frame = f;
991       to_next = vlib_frame_vector_args (f);
992       to_next[0] = bi0;
993       f->n_vectors = 1;
994     }
995
996   if (PREDICT_FALSE (offset == 0))
997     snat_ipfix_header_create (frm, b0, &offset);
998
999   if (PREDICT_TRUE (do_flush == 0))
1000     {
1001       u64 time_stamp = clib_host_to_net_u64 (now);
1002       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1003       offset += sizeof (time_stamp);
1004
1005       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1006       offset += sizeof (nat_event);
1007
1008       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1009       offset += sizeof (quota_event);
1010
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       snat_ipfix_send (thread_index, 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   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1038   snat_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_mains[thread_index];
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       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1066       offset = 0;
1067     }
1068   else
1069     {
1070       bi0 = vlib_get_buffer_index (vm, b0);
1071       offset = sitd->nat64_bib_next_record_offset;
1072     }
1073
1074   f = sitd->nat64_bib_frame;
1075   if (PREDICT_FALSE (f == 0))
1076     {
1077       u32 *to_next;
1078       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1079       sitd->nat64_bib_frame = f;
1080       to_next = vlib_frame_vector_args (f);
1081       to_next[0] = bi0;
1082       f->n_vectors = 1;
1083     }
1084
1085   if (PREDICT_FALSE (offset == 0))
1086     snat_ipfix_header_create (frm, b0, &offset);
1087
1088   if (PREDICT_TRUE (do_flush == 0))
1089     {
1090       u64 time_stamp = clib_host_to_net_u64 (now);
1091       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1092       offset += sizeof (time_stamp);
1093
1094       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1095       offset += sizeof (nat_event);
1096
1097       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1098       offset += sizeof (ip6_address_t);
1099
1100       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1101       offset += sizeof (nat_src_ip);
1102
1103       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1104       offset += sizeof (proto);
1105
1106       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1107       offset += sizeof (src_port);
1108
1109       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1110       offset += sizeof (nat_src_port);
1111
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       snat_ipfix_send (thread_index, 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   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1141   snat_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_mains[thread_index];
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       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1169       offset = 0;
1170     }
1171   else
1172     {
1173       bi0 = vlib_get_buffer_index (vm, b0);
1174       offset = sitd->nat64_ses_next_record_offset;
1175     }
1176
1177   f = sitd->nat64_ses_frame;
1178   if (PREDICT_FALSE (f == 0))
1179     {
1180       u32 *to_next;
1181       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1182       sitd->nat64_ses_frame = f;
1183       to_next = vlib_frame_vector_args (f);
1184       to_next[0] = bi0;
1185       f->n_vectors = 1;
1186     }
1187
1188   if (PREDICT_FALSE (offset == 0))
1189     snat_ipfix_header_create (frm, b0, &offset);
1190
1191   if (PREDICT_TRUE (do_flush == 0))
1192     {
1193       u64 time_stamp = clib_host_to_net_u64 (now);
1194       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1195       offset += sizeof (time_stamp);
1196
1197       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1198       offset += sizeof (nat_event);
1199
1200       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1201       offset += sizeof (ip6_address_t);
1202
1203       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1204       offset += sizeof (nat_src_ip);
1205
1206       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1207       offset += sizeof (proto);
1208
1209       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1210       offset += sizeof (src_port);
1211
1212       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1213       offset += sizeof (nat_src_port);
1214
1215       clib_memcpy_fast (b0->data + offset, dst_ip, sizeof (ip6_address_t));
1216       offset += sizeof (ip6_address_t);
1217
1218       clib_memcpy_fast (b0->data + offset, &nat_dst_ip, sizeof (nat_dst_ip));
1219       offset += sizeof (nat_dst_ip);
1220
1221       clib_memcpy_fast (b0->data + offset, &dst_port, sizeof (dst_port));
1222       offset += sizeof (dst_port);
1223
1224       clib_memcpy_fast (b0->data + offset, &nat_dst_port, sizeof (nat_dst_port));
1225       offset += sizeof (nat_dst_port);
1226
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       snat_ipfix_send (thread_index, 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 snat_ipfix_flush (u32 thread_index)
1249 {
1250   int do_flush = 1;
1251
1252   snat_ipfix_logging_nat44_ses (thread_index,
1253                                 0, 0, 0, 0, 0, 0, 0, do_flush);
1254   snat_ipfix_logging_addr_exhausted (thread_index, 0, do_flush);
1255   snat_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 void
1265 snat_ipfix_flush_from_main (void)
1266 {
1267   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1268   vlib_main_t *worker_vm;
1269   int i;
1270
1271   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))
1272     return;
1273
1274   if (PREDICT_FALSE (!silm->worker_vms))
1275     {
1276       for (i = 1; i < vec_len (vlib_mains); i++)
1277         {
1278           worker_vm = vlib_mains[i];
1279           if (worker_vm)
1280             vec_add1 (silm->worker_vms, worker_vm);
1281         }
1282     }
1283
1284   /* Trigger flush for each worker thread */
1285   for (i = 0; i < vec_len (silm->worker_vms); i++)
1286     {
1287       worker_vm = silm->worker_vms[i];
1288       if (worker_vm)
1289         vlib_node_set_interrupt_pending (worker_vm,
1290                                          snat_ipfix_flush_node.index);
1291     }
1292
1293   /* Finally flush main thread */
1294   snat_ipfix_flush (0);
1295 }
1296
1297 /**
1298  * @brief Generate NAT44 session create event
1299  *
1300  * @param thread_index thread index
1301  * @param src_ip       source IPv4 address
1302  * @param nat_src_ip   transaltes source IPv4 address
1303  * @param nat_proto   NAT transport protocol
1304  * @param src_port     source port
1305  * @param nat_src_port translated source port
1306  * @param vrf_id       VRF ID
1307  */
1308 void
1309 snat_ipfix_logging_nat44_ses_create (u32 thread_index,
1310                                      u32 src_ip,
1311                                      u32 nat_src_ip,
1312                                      nat_protocol_t nat_proto,
1313                                      u16 src_port,
1314                                      u16 nat_src_port, u32 vrf_id)
1315 {
1316   skip_if_disabled ();
1317
1318   snat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_CREATE, src_ip,
1319                                 nat_src_ip, nat_proto, src_port, nat_src_port,
1320                                 vrf_id, 0);
1321 }
1322
1323 /**
1324  * @brief Generate NAT44 session delete event
1325  *
1326  * @param thread_index thread index
1327  * @param src_ip       source IPv4 address
1328  * @param nat_src_ip   transaltes source IPv4 address
1329  * @param nat_proto   NAT transport protocol
1330  * @param src_port     source port
1331  * @param nat_src_port translated source port
1332  * @param vrf_id       VRF ID
1333  */
1334 void
1335 snat_ipfix_logging_nat44_ses_delete (u32 thread_index,
1336                                      u32 src_ip,
1337                                      u32 nat_src_ip,
1338                                      nat_protocol_t nat_proto,
1339                                      u16 src_port,
1340                                      u16 nat_src_port, u32 vrf_id)
1341 {
1342   skip_if_disabled ();
1343
1344   snat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_DELETE, src_ip,
1345                                 nat_src_ip, nat_proto, src_port, nat_src_port,
1346                                 vrf_id, 0);
1347 }
1348
1349 /**
1350  * @brief Generate NAT addresses exhausted event
1351  *
1352  * @param thread_index thread index
1353  * @param pool_id NAT pool ID
1354  */
1355 void
1356 snat_ipfix_logging_addresses_exhausted (u32 thread_index, u32 pool_id)
1357 {
1358   //TODO: This event SHOULD be rate limited
1359   skip_if_disabled ();
1360
1361   snat_ipfix_logging_addr_exhausted (thread_index, pool_id, 0);
1362 }
1363
1364 /**
1365  * @brief Generate maximum entries per user exceeded event
1366  *
1367  * @param thread_index thread index
1368  * @param limit maximum NAT entries that can be created per user
1369  * @param src_ip source IPv4 address
1370  */
1371 void
1372 snat_ipfix_logging_max_entries_per_user (u32 thread_index, u32 limit, u32 src_ip)
1373 {
1374   //TODO: This event SHOULD be rate limited
1375   skip_if_disabled ();
1376
1377   snat_ipfix_logging_max_entries_per_usr (thread_index, limit, src_ip, 0);
1378 }
1379
1380 vlib_frame_t *
1381 deterministic_nat_data_callback
1382 (flow_report_main_t * frm,
1383                                         flow_report_t * fr,
1384                                         vlib_frame_t * f,
1385                                         u32 * to_next, u32 node_index)
1386 {
1387   snat_ipfix_flush_from_main();
1388
1389   return f;
1390 }
1391
1392 /**
1393  * @brief Generate maximum session entries exceeded event
1394  *
1395  * @param thread_index thread index
1396  * @param limit configured limit
1397  */
1398 void
1399 nat_ipfix_logging_max_sessions (u32 thread_index, u32 limit)
1400 {
1401   //TODO: This event SHOULD be rate limited
1402   skip_if_disabled ();
1403
1404   nat_ipfix_logging_max_ses (thread_index, limit, 0);
1405 }
1406
1407 /**
1408  * @brief Generate maximum BIB entries exceeded event
1409  *
1410  * @param thread_index thread index
1411  * @param limit configured limit
1412  */
1413 void
1414 nat_ipfix_logging_max_bibs (u32 thread_index, u32 limit)
1415 {
1416   //TODO: This event SHOULD be rate limited
1417   skip_if_disabled ();
1418
1419   nat_ipfix_logging_max_bib (thread_index, limit, 0);
1420 }
1421
1422 /**
1423  * @brief Generate NAT64 BIB create and delete events
1424  *
1425  * @param thread_index thread index
1426  * @param src_ip       source IPv6 address
1427  * @param nat_src_ip   transaltes source IPv4 address
1428  * @param proto        L4 protocol
1429  * @param src_port     source port
1430  * @param nat_src_port translated source port
1431  * @param vrf_id       VRF ID
1432  * @param is_create    non-zero value if create event otherwise delete event
1433  */
1434 void
1435 nat_ipfix_logging_nat64_bib (u32 thread_index, ip6_address_t * src_ip,
1436                              ip4_address_t * nat_src_ip, u8 proto,
1437                              u16 src_port, u16 nat_src_port, u32 vrf_id,
1438                              u8 is_create)
1439 {
1440   u8 nat_event;
1441
1442   skip_if_disabled ();
1443
1444   nat_event = is_create ? NAT64_BIB_CREATE : NAT64_BIB_DELETE;
1445
1446   nat_ipfix_logging_nat64_bibe (thread_index, nat_event, src_ip,
1447                                 nat_src_ip->as_u32, proto, src_port,
1448                                 nat_src_port, vrf_id, 0);
1449 }
1450
1451 /**
1452  * @brief Generate NAT64 session create and delete events
1453  *
1454  * @param thread_index thread index
1455  * @param src_ip       source IPv6 address
1456  * @param nat_src_ip   transaltes source IPv4 address
1457  * @param proto        L4 protocol
1458  * @param src_port     source port
1459  * @param nat_src_port translated source port
1460  * @param dst_ip       destination IPv6 address
1461  * @param nat_dst_ip   destination IPv4 address
1462  * @param dst_port     destination port
1463  * @param nat_dst_port translated destination port
1464  * @param vrf_id       VRF ID
1465  * @param is_create    non-zero value if create event otherwise delete event
1466  */
1467 void
1468 nat_ipfix_logging_nat64_session (u32 thread_index,
1469                                  ip6_address_t * src_ip,
1470                                  ip4_address_t * nat_src_ip, u8 proto,
1471                                  u16 src_port, u16 nat_src_port,
1472                                  ip6_address_t * dst_ip,
1473                                  ip4_address_t * nat_dst_ip, u16 dst_port,
1474                                  u16 nat_dst_port, u32 vrf_id, u8 is_create)
1475 {
1476   u8 nat_event;
1477
1478   skip_if_disabled ();
1479
1480   nat_event = is_create ? NAT64_SESSION_CREATE : NAT64_SESSION_DELETE;
1481
1482   nat_ipfix_logging_nat64_ses (thread_index, nat_event, src_ip,
1483                                nat_src_ip->as_u32, proto, src_port,
1484                                nat_src_port, dst_ip, nat_dst_ip->as_u32,
1485                                dst_port, nat_dst_port, vrf_id, 0);
1486 }
1487
1488 vlib_frame_t *
1489 data_callback (flow_report_main_t * frm, flow_report_t * fr,
1490                vlib_frame_t * f, u32 * to_next, u32 node_index)
1491 {
1492   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1493
1494   if (PREDICT_FALSE (++silm->call_counter >= vec_len (frm->reports)))
1495     {
1496       snat_ipfix_flush_from_main();
1497       silm->call_counter = 0;
1498     }
1499
1500   return f;
1501 }
1502
1503 /**
1504  * @brief Enable/disable NAT plugin IPFIX logging
1505  *
1506  * @param enable    1 if enable, 0 if disable
1507  * @param domain_id observation domain ID
1508  * @param src_port  source port number
1509  *
1510  * @returns 0 if success
1511  */
1512 int
1513 snat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
1514 {
1515   snat_main_t *sm = &snat_main;
1516   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1517   flow_report_main_t *frm = &flow_report_main;
1518   vnet_flow_report_add_del_args_t a;
1519   int rv;
1520   u8 e = enable ? 1 : 0;
1521
1522   if (clib_atomic_cmp_and_swap (&silm->enabled, e ^ 1, e) == e)
1523     return 0;
1524
1525   clib_memset (&a, 0, sizeof (a));
1526   a.is_add = enable;
1527   a.domain_id = domain_id ? domain_id : 1;
1528   a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
1529   a.flow_data_callback = data_callback;
1530
1531   /* TODO: ipfix needs to be separated from NAT base plugin
1532   a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
1533   rv = vnet_flow_report_add_del (frm, &a, NULL);
1534   if (rv)
1535     {
1536       nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1537       return -1;
1538     }
1539   */
1540   a.rewrite_callback = snat_template_rewrite_nat44_session;
1541
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 = snat_template_rewrite_addr_exhausted;
1550
1551   rv = vnet_flow_report_add_del (frm, &a, NULL);
1552   if (rv)
1553     {
1554       nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1555       return -1;
1556     }
1557
1558   a.rewrite_callback = nat_template_rewrite_max_sessions;
1559
1560   rv = vnet_flow_report_add_del (frm, &a, NULL);
1561   if (rv)
1562     {
1563       nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1564       return -1;
1565     }
1566
1567   a.rewrite_callback = nat_template_rewrite_max_bibs;
1568
1569   rv = vnet_flow_report_add_del (frm, &a, NULL);
1570   if (rv)
1571     {
1572       nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1573       return -1;
1574     }
1575
1576   a.rewrite_callback = nat_template_rewrite_nat64_bib;
1577
1578   rv = vnet_flow_report_add_del (frm, &a, NULL);
1579   if (rv)
1580     {
1581       nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1582       return -1;
1583     }
1584
1585   a.rewrite_callback = nat_template_rewrite_nat64_session;
1586
1587   rv = vnet_flow_report_add_del (frm, &a, NULL);
1588   if (rv)
1589     {
1590       nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1591       return -1;
1592     }
1593
1594   if (sm->endpoint_dependent)
1595     {
1596       a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
1597
1598       rv = vnet_flow_report_add_del (frm, &a, NULL);
1599       if (rv)
1600         {
1601           nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1602           return -1;
1603         }
1604     }
1605
1606   return 0;
1607 }
1608
1609 /**
1610  * @brief Initialize NAT plugin IPFIX logging
1611  *
1612  * @param vm vlib main
1613  */
1614 void
1615 snat_ipfix_logging_init (vlib_main_t * vm)
1616 {
1617   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1618   vlib_thread_main_t *tm = vlib_get_thread_main ();
1619
1620   silm->enabled = 0;
1621   silm->worker_vms = 0;
1622   silm->call_counter = 0;
1623
1624   /* Set up time reference pair */
1625   silm->vlib_time_0 = vlib_time_now (vm);
1626   silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
1627
1628   vec_validate (silm->per_thread_data, tm->n_vlib_mains - 1);
1629 }
1630
1631 static uword
1632 ipfix_flush_process (vlib_main_t *vm,
1633                      vlib_node_runtime_t *rt,
1634                      vlib_frame_t *f)
1635 {
1636   snat_ipfix_flush(vm->thread_index);
1637   return 0;
1638 }
1639
1640 /* *INDENT-OFF* */
1641 VLIB_REGISTER_NODE (snat_ipfix_flush_node) = {
1642   .function = ipfix_flush_process,
1643   .name = "snat-ipfix-flush",
1644   .type = VLIB_NODE_TYPE_INPUT,
1645   .state = VLIB_NODE_STATE_INTERRUPT,
1646 };
1647 /* *INDENT-ON* */