8bee8e444dc86c2b706dfe26fc317cc53f19352e
[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
23 snat_ipfix_logging_main_t snat_ipfix_logging_main;
24
25 #define NAT44_SESSION_CREATE_LEN 26
26 #define NAT_ADDRESSES_EXHAUTED_LEN 13
27 #define MAX_ENTRIES_PER_USER_LEN 21
28 #define MAX_SESSIONS_LEN 17
29 #define MAX_BIBS_LEN 17
30 #define MAX_FRAGMENTS_IP4_LEN 21
31 #define MAX_FRAGMENTS_IP6_LEN 33
32 #define NAT64_BIB_LEN 38
33 #define NAT64_SES_LEN 62
34
35 #define NAT44_SESSION_CREATE_FIELD_COUNT 8
36 #define NAT_ADDRESSES_EXHAUTED_FIELD_COUNT 3
37 #define MAX_ENTRIES_PER_USER_FIELD_COUNT 5
38 #define MAX_SESSIONS_FIELD_COUNT 4
39 #define MAX_BIBS_FIELD_COUNT 4
40 #define MAX_FRAGMENTS_FIELD_COUNT 5
41 #define NAT64_BIB_FIELD_COUNT 8
42 #define NAT64_SES_FIELD_COUNT 12
43
44 typedef struct
45 {
46   u8 nat_event;
47   u32 src_ip;
48   u32 nat_src_ip;
49   snat_protocol_t snat_proto;
50   u16 src_port;
51   u16 nat_src_port;
52   u32 vrf_id;
53 } snat_ipfix_logging_nat44_ses_args_t;
54
55 typedef struct
56 {
57   u32 pool_id;
58 } snat_ipfix_logging_addr_exhausted_args_t;
59
60 typedef struct
61 {
62   u32 limit;
63   u32 src_ip;
64 } snat_ipfix_logging_max_entries_per_user_args_t;
65
66 typedef struct
67 {
68   u32 limit;
69 } nat_ipfix_logging_max_sessions_args_t;
70
71 typedef struct
72 {
73   u32 limit;
74 } nat_ipfix_logging_max_bibs_args_t;
75
76 typedef struct
77 {
78   u32 limit;
79   u32 src;
80 } nat_ipfix_logging_max_frags_ip4_args_t;
81
82 typedef struct
83 {
84   u32 limit;
85   u64 src[2];
86 } nat_ipfix_logging_max_frags_ip6_args_t;
87
88 typedef struct
89 {
90   u8 nat_event;
91   u64 src_ip[2];
92   u32 nat_src_ip;
93   u8 proto;
94   u16 src_port;
95   u16 nat_src_port;
96   u64 dst_ip[2];
97   u32 nat_dst_ip;
98   u32 vrf_id;
99   u16 dst_port;
100   u16 nat_dst_port;
101 } nat_ipfix_logging_nat64_ses_args_t;
102
103 typedef struct
104 {
105   u8 nat_event;
106   u64 src_ip[2];
107   u32 nat_src_ip;
108   u8 proto;
109   u16 src_port;
110   u16 nat_src_port;
111   u32 vrf_id;
112 } nat_ipfix_logging_nat64_bib_args_t;
113
114 #define skip_if_disabled()                                    \
115 do {                                                          \
116   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main; \
117   if (PREDICT_TRUE (!silm->enabled))                          \
118     return;                                                   \
119 } while (0)
120
121 /**
122  * @brief Create an IPFIX template packet rewrite string
123  *
124  * @param frm               flow report main
125  * @param fr                flow report
126  * @param collector_address collector address
127  * @param src_address       source address
128  * @param collector_port    collector
129  * @param event             NAT event ID
130  * @param quota_event       NAT quota exceeded event ID
131  *
132  * @returns template packet
133  */
134 static inline u8 *
135 snat_template_rewrite (flow_report_main_t * frm,
136                        flow_report_t * fr,
137                        ip4_address_t * collector_address,
138                        ip4_address_t * src_address,
139                        u16 collector_port,
140                        nat_event_t event, quota_exceed_event_t quota_event)
141 {
142   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
143   ip4_header_t *ip;
144   udp_header_t *udp;
145   ipfix_message_header_t *h;
146   ipfix_set_header_t *s;
147   ipfix_template_header_t *t;
148   ipfix_field_specifier_t *f;
149   ipfix_field_specifier_t *first_field;
150   u8 *rewrite = 0;
151   ip4_ipfix_template_packet_t *tp;
152   u32 field_count = 0;
153   flow_report_stream_t *stream;
154
155   stream = &frm->streams[fr->stream_index];
156   silm->stream_index = fr->stream_index;
157
158   if (event == NAT_ADDRESSES_EXHAUTED)
159     {
160       field_count = NAT_ADDRESSES_EXHAUTED_FIELD_COUNT;
161       silm->addr_exhausted_template_id = fr->template_id;
162     }
163   else if (event == NAT44_SESSION_CREATE)
164     {
165       field_count = NAT44_SESSION_CREATE_FIELD_COUNT;
166       silm->nat44_session_template_id = fr->template_id;
167     }
168   else if (event == NAT64_BIB_CREATE)
169     {
170       field_count = NAT64_BIB_FIELD_COUNT;
171       silm->nat64_bib_template_id = fr->template_id;
172     }
173   else if (event == NAT64_SESSION_CREATE)
174     {
175       field_count = NAT64_SES_FIELD_COUNT;
176       silm->nat64_ses_template_id = fr->template_id;
177     }
178   else if (event == QUOTA_EXCEEDED)
179     {
180       if (quota_event == MAX_ENTRIES_PER_USER)
181         {
182           field_count = MAX_ENTRIES_PER_USER_FIELD_COUNT;
183           silm->max_entries_per_user_template_id = fr->template_id;
184         }
185       else if (quota_event == MAX_SESSION_ENTRIES)
186         {
187           field_count = MAX_SESSIONS_FIELD_COUNT;
188           silm->max_sessions_template_id = fr->template_id;
189         }
190       else if (quota_event == MAX_BIB_ENTRIES)
191         {
192           field_count = MAX_BIBS_FIELD_COUNT;
193           silm->max_bibs_template_id = fr->template_id;
194         }
195       else if (quota_event == MAX_FRAGMENTS_PENDING_REASSEMBLY)
196         {
197           field_count = MAX_FRAGMENTS_FIELD_COUNT;
198           silm->max_frags_ip4_template_id = fr->template_id;
199         }
200       else if (quota_event == MAX_FRAGMENTS_PENDING_REASSEMBLY_IP6)
201         {
202           field_count = MAX_FRAGMENTS_FIELD_COUNT;
203           silm->max_frags_ip6_template_id = fr->template_id;
204         }
205     }
206
207   /* allocate rewrite space */
208   vec_validate_aligned (rewrite,
209                         sizeof (ip4_ipfix_template_packet_t)
210                         + field_count * sizeof (ipfix_field_specifier_t) - 1,
211                         CLIB_CACHE_LINE_BYTES);
212
213   tp = (ip4_ipfix_template_packet_t *) rewrite;
214   ip = (ip4_header_t *) & tp->ip4;
215   udp = (udp_header_t *) (ip + 1);
216   h = (ipfix_message_header_t *) (udp + 1);
217   s = (ipfix_set_header_t *) (h + 1);
218   t = (ipfix_template_header_t *) (s + 1);
219   first_field = f = (ipfix_field_specifier_t *) (t + 1);
220
221   ip->ip_version_and_header_length = 0x45;
222   ip->ttl = 254;
223   ip->protocol = IP_PROTOCOL_UDP;
224   ip->src_address.as_u32 = src_address->as_u32;
225   ip->dst_address.as_u32 = collector_address->as_u32;
226   udp->src_port = clib_host_to_net_u16 (stream->src_port);
227   udp->dst_port = clib_host_to_net_u16 (collector_port);
228   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
229
230   /* FIXUP: message header export_time */
231   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
232
233   /* Add TLVs to the template */
234   if (event == NAT_ADDRESSES_EXHAUTED)
235     {
236       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
237       f++;
238       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
239       f++;
240       f->e_id_length = ipfix_e_id_length (0, natPoolId, 4);
241       f++;
242     }
243   else if (event == NAT44_SESSION_CREATE)
244     {
245       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
246       f++;
247       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
248       f++;
249       f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
250       f++;
251       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
252       f++;
253       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
254       f++;
255       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
256       f++;
257       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
258       f++;
259       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
260       f++;
261     }
262   else if (event == NAT64_BIB_CREATE)
263     {
264       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
265       f++;
266       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
267       f++;
268       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
269       f++;
270       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
271       f++;
272       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
273       f++;
274       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
275       f++;
276       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
277       f++;
278       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
279       f++;
280     }
281   else if (event == NAT64_SESSION_CREATE)
282     {
283       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
284       f++;
285       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
286       f++;
287       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
288       f++;
289       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
290       f++;
291       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
292       f++;
293       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
294       f++;
295       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
296       f++;
297       f->e_id_length = ipfix_e_id_length (0, destinationIPv6Address, 16);
298       f++;
299       f->e_id_length = ipfix_e_id_length (0, postNATDestinationIPv4Address, 4);
300       f++;
301       f->e_id_length = ipfix_e_id_length (0, destinationTransportPort, 2);
302       f++;
303       f->e_id_length = ipfix_e_id_length (0, postNAPTDestinationTransportPort,
304                                           2);
305       f++;
306       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
307       f++;
308     }
309   else if (event == QUOTA_EXCEEDED)
310     {
311       if (quota_event == MAX_ENTRIES_PER_USER)
312         {
313           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
314                                               8);
315           f++;
316           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
317           f++;
318           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
319           f++;
320           f->e_id_length = ipfix_e_id_length (0, maxEntriesPerUser, 4);
321           f++;
322           f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
323           f++;
324         }
325       else if (quota_event == MAX_SESSION_ENTRIES)
326         {
327           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
328                                               8);
329           f++;
330           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
331           f++;
332           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
333           f++;
334           f->e_id_length = ipfix_e_id_length (0, maxSessionEntries, 4);
335           f++;
336         }
337       else if (quota_event == MAX_BIB_ENTRIES)
338         {
339           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
340                                               8);
341           f++;
342           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
343           f++;
344           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
345           f++;
346           f->e_id_length = ipfix_e_id_length (0, maxBIBEntries, 4);
347           f++;
348         }
349       else if (quota_event == MAX_FRAGMENTS_PENDING_REASSEMBLY)
350         {
351           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
352                                               8);
353           f++;
354           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
355           f++;
356           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
357           f++;
358           f->e_id_length = ipfix_e_id_length (0, maxFragmentsPendingReassembly,
359                                               4);
360           f++;
361           f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
362           f++;
363         }
364       else if (quota_event == MAX_FRAGMENTS_PENDING_REASSEMBLY_IP6)
365         {
366           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
367                                               8);
368           f++;
369           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
370           f++;
371           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
372           f++;
373           f->e_id_length = ipfix_e_id_length (0, maxFragmentsPendingReassembly,
374                                               4);
375           f++;
376           f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
377           f++;
378         }
379     }
380
381   /* Back to the template packet... */
382   ip = (ip4_header_t *) & tp->ip4;
383   udp = (udp_header_t *) (ip + 1);
384
385   ASSERT (f - first_field);
386   /* Field count in this template */
387   t->id_count = ipfix_id_count (fr->template_id, f - first_field);
388
389   /* set length in octets */
390   s->set_id_length =
391     ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
392
393   /* message length in octets */
394   h->version_length = version_length ((u8 *) f - (u8 *) h);
395
396   ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
397   ip->checksum = ip4_header_checksum (ip);
398
399   return rewrite;
400 }
401
402 u8 *
403 snat_template_rewrite_addr_exhausted (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, NAT_ADDRESSES_EXHAUTED, 0);
413 }
414
415 u8 *
416 snat_template_rewrite_nat44_session (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, NAT44_SESSION_CREATE, 0);
426 }
427
428 u8 *
429 snat_template_rewrite_max_entries_per_usr (flow_report_main_t * frm,
430                                            flow_report_t * fr,
431                                            ip4_address_t * collector_address,
432                                            ip4_address_t * src_address,
433                                            u16 collector_port,
434                                            ipfix_report_element_t *elts,
435                                            u32 n_elts, u32 *stream_index)
436 {
437   return snat_template_rewrite (frm, fr, collector_address, src_address,
438                                 collector_port, QUOTA_EXCEEDED,
439                                 MAX_ENTRIES_PER_USER);
440 }
441
442 u8 *
443 nat_template_rewrite_max_sessions (flow_report_main_t * frm,
444                                    flow_report_t * fr,
445                                    ip4_address_t * collector_address,
446                                    ip4_address_t * src_address,
447                                    u16 collector_port,
448                                    ipfix_report_element_t *elts,
449                                    u32 n_elts, u32 *stream_index)
450 {
451   return snat_template_rewrite (frm, fr, collector_address, src_address,
452                                 collector_port, QUOTA_EXCEEDED,
453                                 MAX_SESSION_ENTRIES);
454 }
455
456 u8 *
457 nat_template_rewrite_max_bibs (flow_report_main_t * frm,
458                                flow_report_t * fr,
459                                ip4_address_t * collector_address,
460                                ip4_address_t * src_address,
461                                u16 collector_port,
462                                ipfix_report_element_t *elts,
463                                u32 n_elts, u32 *stream_index)
464 {
465   return snat_template_rewrite (frm, fr, collector_address, src_address,
466                                 collector_port, QUOTA_EXCEEDED,
467                                 MAX_BIB_ENTRIES);
468 }
469
470 u8 *
471 nat_template_rewrite_max_frags_ip4 (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, QUOTA_EXCEEDED,
481                                 MAX_FRAGMENTS_PENDING_REASSEMBLY);
482 }
483
484 u8 *
485 nat_template_rewrite_max_frags_ip6 (flow_report_main_t * frm,
486                                     flow_report_t * fr,
487                                     ip4_address_t * collector_address,
488                                     ip4_address_t * src_address,
489                                     u16 collector_port,
490                                     ipfix_report_element_t *elts,
491                                     u32 n_elts, u32 *stream_index)
492 {
493   return snat_template_rewrite (frm, fr, collector_address, src_address,
494                                 collector_port, QUOTA_EXCEEDED,
495                                 MAX_FRAGMENTS_PENDING_REASSEMBLY_IP6);
496 }
497
498 u8 *
499 nat_template_rewrite_nat64_bib (flow_report_main_t * frm,
500                                 flow_report_t * fr,
501                                 ip4_address_t * collector_address,
502                                 ip4_address_t * src_address,
503                                 u16 collector_port,
504                                 ipfix_report_element_t *elts,
505                                 u32 n_elts, u32 *stream_index)
506 {
507   return snat_template_rewrite (frm, fr, collector_address, src_address,
508                                 collector_port, NAT64_BIB_CREATE, 0);
509 }
510
511 u8 *
512 nat_template_rewrite_nat64_session (flow_report_main_t * frm,
513                                     flow_report_t * fr,
514                                     ip4_address_t * collector_address,
515                                     ip4_address_t * src_address,
516                                     u16 collector_port,
517                                     ipfix_report_element_t *elts,
518                                     u32 n_elts, u32 *stream_index)
519 {
520   return snat_template_rewrite (frm, fr, collector_address, src_address,
521                                 collector_port, NAT64_SESSION_CREATE, 0);
522 }
523
524 static inline void
525 snat_ipfix_header_create (flow_report_main_t * frm,
526                           vlib_buffer_t * b0, u32 * offset)
527 {
528   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
529   flow_report_stream_t *stream;
530   ip4_ipfix_template_packet_t *tp;
531   ipfix_message_header_t *h = 0;
532   ipfix_set_header_t *s = 0;
533   ip4_header_t *ip;
534   udp_header_t *udp;
535
536   stream = &frm->streams[silm->stream_index];
537
538   b0->current_data = 0;
539   b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
540     sizeof (*s);
541   b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_FLOW_REPORT);
542   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
543   vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
544   tp = vlib_buffer_get_current (b0);
545   ip = (ip4_header_t *) & tp->ip4;
546   udp = (udp_header_t *) (ip + 1);
547   h = (ipfix_message_header_t *) (udp + 1);
548   s = (ipfix_set_header_t *) (h + 1);
549
550   ip->ip_version_and_header_length = 0x45;
551   ip->ttl = 254;
552   ip->protocol = IP_PROTOCOL_UDP;
553   ip->flags_and_fragment_offset = 0;
554   ip->src_address.as_u32 = frm->src_address.as_u32;
555   ip->dst_address.as_u32 = frm->ipfix_collector.as_u32;
556   udp->src_port = clib_host_to_net_u16 (stream->src_port);
557   udp->dst_port = clib_host_to_net_u16 (frm->collector_port);
558   udp->checksum = 0;
559
560   h->export_time = clib_host_to_net_u32 ((u32)
561                                          (((f64) frm->unix_time_0) +
562                                           (vlib_time_now (frm->vlib_main) -
563                                            frm->vlib_time_0)));
564   h->sequence_number = clib_host_to_net_u32 (stream->sequence_number++);
565   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
566
567   *offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
568 }
569
570 static inline void
571 snat_ipfix_send (flow_report_main_t * frm,
572                  vlib_frame_t * f, vlib_buffer_t * b0, u16 template_id)
573 {
574   ip4_ipfix_template_packet_t *tp;
575   ipfix_message_header_t *h = 0;
576   ipfix_set_header_t *s = 0;
577   ip4_header_t *ip;
578   udp_header_t *udp;
579   vlib_main_t *vm = frm->vlib_main;
580
581   tp = vlib_buffer_get_current (b0);
582   ip = (ip4_header_t *) & tp->ip4;
583   udp = (udp_header_t *) (ip + 1);
584   h = (ipfix_message_header_t *) (udp + 1);
585   s = (ipfix_set_header_t *) (h + 1);
586
587   s->set_id_length = ipfix_set_id_length (template_id,
588                                           b0->current_length -
589                                           (sizeof (*ip) + sizeof (*udp) +
590                                            sizeof (*h)));
591   h->version_length = version_length (b0->current_length -
592                                       (sizeof (*ip) + sizeof (*udp)));
593
594   ip->length = clib_host_to_net_u16 (b0->current_length);
595   ip->checksum = ip4_header_checksum (ip);
596   udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
597
598   if (frm->udp_checksum)
599     {
600       udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
601       if (udp->checksum == 0)
602         udp->checksum = 0xffff;
603     }
604
605   ASSERT (ip->checksum == ip4_header_checksum (ip));
606
607   vlib_put_frame_to_node (vm, ip4_lookup_node.index, f);
608 }
609
610 static void
611 snat_ipfix_logging_nat44_ses (u8 nat_event, u32 src_ip, u32 nat_src_ip,
612                               snat_protocol_t snat_proto, u16 src_port,
613                               u16 nat_src_port, u32 vrf_id, int do_flush)
614 {
615   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
616   flow_report_main_t *frm = &flow_report_main;
617   vlib_frame_t *f;
618   vlib_buffer_t *b0 = 0;
619   u32 bi0 = ~0;
620   u32 offset;
621   vlib_main_t *vm = frm->vlib_main;
622   u64 now;
623   u8 proto = ~0;
624
625   if (!silm->enabled)
626     return;
627
628   proto = snat_proto_to_ip_proto (snat_proto);
629
630   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
631   now += silm->milisecond_time_0;
632
633   b0 = silm->nat44_session_buffer;
634
635   if (PREDICT_FALSE (b0 == 0))
636     {
637       if (do_flush)
638         return;
639
640       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
641         {
642           nat_log_err ("can't allocate buffer for NAT IPFIX event");
643           return;
644         }
645
646       b0 = silm->nat44_session_buffer = vlib_get_buffer (vm, bi0);
647       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
648       offset = 0;
649     }
650   else
651     {
652       bi0 = vlib_get_buffer_index (vm, b0);
653       offset = silm->nat44_session_next_record_offset;
654     }
655
656   f = silm->nat44_session_frame;
657   if (PREDICT_FALSE (f == 0))
658     {
659       u32 *to_next;
660       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
661       silm->nat44_session_frame = f;
662       to_next = vlib_frame_vector_args (f);
663       to_next[0] = bi0;
664       f->n_vectors = 1;
665     }
666
667   if (PREDICT_FALSE (offset == 0))
668     snat_ipfix_header_create (frm, b0, &offset);
669
670   if (PREDICT_TRUE (do_flush == 0))
671     {
672       u64 time_stamp = clib_host_to_net_u64 (now);
673       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
674       offset += sizeof (time_stamp);
675
676       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
677       offset += sizeof (nat_event);
678
679       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
680       offset += sizeof (src_ip);
681
682       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
683       offset += sizeof (nat_src_ip);
684
685       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
686       offset += sizeof (proto);
687
688       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
689       offset += sizeof (src_port);
690
691       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
692       offset += sizeof (nat_src_port);
693
694       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
695       offset += sizeof (vrf_id);
696
697       b0->current_length += NAT44_SESSION_CREATE_LEN;
698     }
699
700   if (PREDICT_FALSE
701       (do_flush || (offset + NAT44_SESSION_CREATE_LEN) > frm->path_mtu))
702     {
703       snat_ipfix_send (frm, f, b0, silm->nat44_session_template_id);
704       silm->nat44_session_frame = 0;
705       silm->nat44_session_buffer = 0;
706       offset = 0;
707     }
708   silm->nat44_session_next_record_offset = offset;
709 }
710
711 static void
712 snat_ipfix_logging_addr_exhausted (u32 pool_id, int do_flush)
713 {
714   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
715   flow_report_main_t *frm = &flow_report_main;
716   vlib_frame_t *f;
717   vlib_buffer_t *b0 = 0;
718   u32 bi0 = ~0;
719   u32 offset;
720   vlib_main_t *vm = frm->vlib_main;
721   u64 now;
722   u8 nat_event = NAT_ADDRESSES_EXHAUTED;
723
724   if (!silm->enabled)
725     return;
726
727   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
728   now += silm->milisecond_time_0;
729
730   b0 = silm->addr_exhausted_buffer;
731
732   if (PREDICT_FALSE (b0 == 0))
733     {
734       if (do_flush)
735         return;
736
737       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
738         {
739           nat_log_err ("can't allocate buffer for NAT IPFIX event");
740           return;
741         }
742
743       b0 = silm->addr_exhausted_buffer = vlib_get_buffer (vm, bi0);
744       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
745       offset = 0;
746     }
747   else
748     {
749       bi0 = vlib_get_buffer_index (vm, b0);
750       offset = silm->addr_exhausted_next_record_offset;
751     }
752
753   f = silm->addr_exhausted_frame;
754   if (PREDICT_FALSE (f == 0))
755     {
756       u32 *to_next;
757       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
758       silm->addr_exhausted_frame = f;
759       to_next = vlib_frame_vector_args (f);
760       to_next[0] = bi0;
761       f->n_vectors = 1;
762     }
763
764   if (PREDICT_FALSE (offset == 0))
765     snat_ipfix_header_create (frm, b0, &offset);
766
767   if (PREDICT_TRUE (do_flush == 0))
768     {
769       u64 time_stamp = clib_host_to_net_u64 (now);
770       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
771       offset += sizeof (time_stamp);
772
773       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
774       offset += sizeof (nat_event);
775
776       clib_memcpy_fast (b0->data + offset, &pool_id, sizeof (pool_id));
777       offset += sizeof (pool_id);
778
779       b0->current_length += NAT_ADDRESSES_EXHAUTED_LEN;
780     }
781
782   if (PREDICT_FALSE
783       (do_flush || (offset + NAT_ADDRESSES_EXHAUTED_LEN) > frm->path_mtu))
784     {
785       snat_ipfix_send (frm, f, b0, silm->addr_exhausted_template_id);
786       silm->addr_exhausted_frame = 0;
787       silm->addr_exhausted_buffer = 0;
788       offset = 0;
789     }
790   silm->addr_exhausted_next_record_offset = offset;
791 }
792
793 static void
794 snat_ipfix_logging_max_entries_per_usr (u32 limit, u32 src_ip, int do_flush)
795 {
796   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
797   flow_report_main_t *frm = &flow_report_main;
798   vlib_frame_t *f;
799   vlib_buffer_t *b0 = 0;
800   u32 bi0 = ~0;
801   u32 offset;
802   vlib_main_t *vm = frm->vlib_main;
803   u64 now;
804   u8 nat_event = QUOTA_EXCEEDED;
805   u32 quota_event = MAX_ENTRIES_PER_USER;
806
807   if (!silm->enabled)
808     return;
809
810   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
811   now += silm->milisecond_time_0;
812
813   b0 = silm->max_entries_per_user_buffer;
814
815   if (PREDICT_FALSE (b0 == 0))
816     {
817       if (do_flush)
818         return;
819
820       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
821         {
822           nat_log_err ("can't allocate buffer for NAT IPFIX event");
823           return;
824         }
825
826       b0 = silm->max_entries_per_user_buffer = vlib_get_buffer (vm, bi0);
827       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
828       offset = 0;
829     }
830   else
831     {
832       bi0 = vlib_get_buffer_index (vm, b0);
833       offset = silm->max_entries_per_user_next_record_offset;
834     }
835
836   f = silm->max_entries_per_user_frame;
837   if (PREDICT_FALSE (f == 0))
838     {
839       u32 *to_next;
840       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
841       silm->max_entries_per_user_frame = f;
842       to_next = vlib_frame_vector_args (f);
843       to_next[0] = bi0;
844       f->n_vectors = 1;
845     }
846
847   if (PREDICT_FALSE (offset == 0))
848     snat_ipfix_header_create (frm, b0, &offset);
849
850   if (PREDICT_TRUE (do_flush == 0))
851     {
852       u64 time_stamp = clib_host_to_net_u64 (now);
853       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
854       offset += sizeof (time_stamp);
855
856       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
857       offset += sizeof (nat_event);
858
859       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
860       offset += sizeof (quota_event);
861
862       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
863       offset += sizeof (limit);
864
865       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
866       offset += sizeof (src_ip);
867
868       b0->current_length += MAX_ENTRIES_PER_USER_LEN;
869     }
870
871   if (PREDICT_FALSE
872       (do_flush || (offset + MAX_ENTRIES_PER_USER_LEN) > frm->path_mtu))
873     {
874       snat_ipfix_send (frm, f, b0, silm->max_entries_per_user_template_id);
875       silm->max_entries_per_user_frame = 0;
876       silm->max_entries_per_user_buffer = 0;
877       offset = 0;
878     }
879   silm->max_entries_per_user_next_record_offset = offset;
880 }
881
882 static void
883 nat_ipfix_logging_max_ses (u32 limit, int do_flush)
884 {
885   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
886   flow_report_main_t *frm = &flow_report_main;
887   vlib_frame_t *f;
888   vlib_buffer_t *b0 = 0;
889   u32 bi0 = ~0;
890   u32 offset;
891   vlib_main_t *vm = frm->vlib_main;
892   u64 now;
893   u8 nat_event = QUOTA_EXCEEDED;
894   u32 quota_event = MAX_SESSION_ENTRIES;
895
896   if (!silm->enabled)
897     return;
898
899   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
900   now += silm->milisecond_time_0;
901
902   b0 = silm->max_sessions_buffer;
903
904   if (PREDICT_FALSE (b0 == 0))
905     {
906       if (do_flush)
907         return;
908
909       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
910         {
911           nat_log_err ("can't allocate buffer for NAT IPFIX event");
912           return;
913         }
914
915       b0 = silm->max_sessions_buffer = vlib_get_buffer (vm, bi0);
916       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
917       offset = 0;
918     }
919   else
920     {
921       bi0 = vlib_get_buffer_index (vm, b0);
922       offset = silm->max_sessions_next_record_offset;
923     }
924
925   f = silm->max_sessions_frame;
926   if (PREDICT_FALSE (f == 0))
927     {
928       u32 *to_next;
929       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
930       silm->max_sessions_frame = f;
931       to_next = vlib_frame_vector_args (f);
932       to_next[0] = bi0;
933       f->n_vectors = 1;
934     }
935
936   if (PREDICT_FALSE (offset == 0))
937     snat_ipfix_header_create (frm, b0, &offset);
938
939   if (PREDICT_TRUE (do_flush == 0))
940     {
941       u64 time_stamp = clib_host_to_net_u64 (now);
942       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
943       offset += sizeof (time_stamp);
944
945       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
946       offset += sizeof (nat_event);
947
948       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
949       offset += sizeof (quota_event);
950
951       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
952       offset += sizeof (limit);
953
954       b0->current_length += MAX_SESSIONS_LEN;
955     }
956
957   if (PREDICT_FALSE
958       (do_flush || (offset + MAX_SESSIONS_LEN) > frm->path_mtu))
959     {
960       snat_ipfix_send (frm, f, b0, silm->max_sessions_template_id);
961       silm->max_sessions_frame = 0;
962       silm->max_sessions_buffer = 0;
963       offset = 0;
964     }
965   silm->max_sessions_next_record_offset = offset;
966 }
967
968 static void
969 nat_ipfix_logging_max_bib (u32 limit, int do_flush)
970 {
971   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
972   flow_report_main_t *frm = &flow_report_main;
973   vlib_frame_t *f;
974   vlib_buffer_t *b0 = 0;
975   u32 bi0 = ~0;
976   u32 offset;
977   vlib_main_t *vm = frm->vlib_main;
978   u64 now;
979   u8 nat_event = QUOTA_EXCEEDED;
980   u32 quota_event = MAX_BIB_ENTRIES;
981
982   if (!silm->enabled)
983     return;
984
985   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
986   now += silm->milisecond_time_0;
987
988   b0 = silm->max_bibs_buffer;
989
990   if (PREDICT_FALSE (b0 == 0))
991     {
992       if (do_flush)
993         return;
994
995       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
996         {
997           nat_log_err ("can't allocate buffer for NAT IPFIX event");
998           return;
999         }
1000
1001       b0 = silm->max_bibs_buffer = vlib_get_buffer (vm, bi0);
1002       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1003       offset = 0;
1004     }
1005   else
1006     {
1007       bi0 = vlib_get_buffer_index (vm, b0);
1008       offset = silm->max_bibs_next_record_offset;
1009     }
1010
1011   f = silm->max_bibs_frame;
1012   if (PREDICT_FALSE (f == 0))
1013     {
1014       u32 *to_next;
1015       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1016       silm->max_bibs_frame = f;
1017       to_next = vlib_frame_vector_args (f);
1018       to_next[0] = bi0;
1019       f->n_vectors = 1;
1020     }
1021
1022   if (PREDICT_FALSE (offset == 0))
1023     snat_ipfix_header_create (frm, b0, &offset);
1024
1025   if (PREDICT_TRUE (do_flush == 0))
1026     {
1027       u64 time_stamp = clib_host_to_net_u64 (now);
1028       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1029       offset += sizeof (time_stamp);
1030
1031       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1032       offset += sizeof (nat_event);
1033
1034       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1035       offset += sizeof (quota_event);
1036
1037       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
1038       offset += sizeof (limit);
1039
1040       b0->current_length += MAX_BIBS_LEN;
1041     }
1042
1043   if (PREDICT_FALSE
1044       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1045     {
1046       snat_ipfix_send (frm, f, b0, silm->max_bibs_template_id);
1047       silm->max_bibs_frame = 0;
1048       silm->max_bibs_buffer = 0;
1049       offset = 0;
1050     }
1051   silm->max_bibs_next_record_offset = offset;
1052 }
1053
1054 static void
1055 nat_ipfix_logging_max_frag_ip4 (u32 limit, u32 src, int do_flush)
1056 {
1057   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1058   flow_report_main_t *frm = &flow_report_main;
1059   vlib_frame_t *f;
1060   vlib_buffer_t *b0 = 0;
1061   u32 bi0 = ~0;
1062   u32 offset;
1063   vlib_main_t *vm = frm->vlib_main;
1064   u64 now;
1065   u8 nat_event = QUOTA_EXCEEDED;
1066   u32 quota_event = MAX_FRAGMENTS_PENDING_REASSEMBLY;
1067
1068   if (!silm->enabled)
1069     return;
1070
1071   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1072   now += silm->milisecond_time_0;
1073
1074   b0 = silm->max_frags_ip4_buffer;
1075
1076   if (PREDICT_FALSE (b0 == 0))
1077     {
1078       if (do_flush)
1079         return;
1080
1081       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1082         {
1083           nat_log_err ("can't allocate buffer for NAT IPFIX event");
1084           return;
1085         }
1086
1087       b0 = silm->max_frags_ip4_buffer = vlib_get_buffer (vm, bi0);
1088       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1089       offset = 0;
1090     }
1091   else
1092     {
1093       bi0 = vlib_get_buffer_index (vm, b0);
1094       offset = silm->max_frags_ip4_next_record_offset;
1095     }
1096
1097   f = silm->max_frags_ip4_frame;
1098   if (PREDICT_FALSE (f == 0))
1099     {
1100       u32 *to_next;
1101       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1102       silm->max_frags_ip4_frame = f;
1103       to_next = vlib_frame_vector_args (f);
1104       to_next[0] = bi0;
1105       f->n_vectors = 1;
1106     }
1107
1108   if (PREDICT_FALSE (offset == 0))
1109     snat_ipfix_header_create (frm, b0, &offset);
1110
1111   if (PREDICT_TRUE (do_flush == 0))
1112     {
1113       u64 time_stamp = clib_host_to_net_u64 (now);
1114       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1115       offset += sizeof (time_stamp);
1116
1117       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1118       offset += sizeof (nat_event);
1119
1120       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1121       offset += sizeof (quota_event);
1122
1123       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
1124       offset += sizeof (limit);
1125
1126       clib_memcpy_fast (b0->data + offset, &src, sizeof (src));
1127       offset += sizeof (src);
1128
1129       b0->current_length += MAX_FRAGMENTS_IP4_LEN;
1130     }
1131
1132   if (PREDICT_FALSE
1133       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1134     {
1135       snat_ipfix_send (frm, f, b0, silm->max_frags_ip4_template_id);
1136       silm->max_frags_ip4_frame = 0;
1137       silm->max_frags_ip4_buffer = 0;
1138       offset = 0;
1139     }
1140   silm->max_frags_ip4_next_record_offset = offset;
1141 }
1142
1143 static void
1144 nat_ipfix_logging_max_frag_ip6 (u32 limit, ip6_address_t * src, int do_flush)
1145 {
1146   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1147   flow_report_main_t *frm = &flow_report_main;
1148   vlib_frame_t *f;
1149   vlib_buffer_t *b0 = 0;
1150   u32 bi0 = ~0;
1151   u32 offset;
1152   vlib_main_t *vm = frm->vlib_main;
1153   u64 now;
1154   u8 nat_event = QUOTA_EXCEEDED;
1155   u32 quota_event = MAX_FRAGMENTS_PENDING_REASSEMBLY;
1156
1157   if (!silm->enabled)
1158     return;
1159
1160   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1161   now += silm->milisecond_time_0;
1162
1163   b0 = silm->max_frags_ip6_buffer;
1164
1165   if (PREDICT_FALSE (b0 == 0))
1166     {
1167       if (do_flush)
1168         return;
1169
1170       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1171         {
1172           nat_log_err ("can't allocate buffer for NAT IPFIX event");
1173           return;
1174         }
1175
1176       b0 = silm->max_frags_ip6_buffer = vlib_get_buffer (vm, bi0);
1177       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1178       offset = 0;
1179     }
1180   else
1181     {
1182       bi0 = vlib_get_buffer_index (vm, b0);
1183       offset = silm->max_frags_ip6_next_record_offset;
1184     }
1185
1186   f = silm->max_frags_ip6_frame;
1187   if (PREDICT_FALSE (f == 0))
1188     {
1189       u32 *to_next;
1190       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1191       silm->max_frags_ip6_frame = f;
1192       to_next = vlib_frame_vector_args (f);
1193       to_next[0] = bi0;
1194       f->n_vectors = 1;
1195     }
1196
1197   if (PREDICT_FALSE (offset == 0))
1198     snat_ipfix_header_create (frm, b0, &offset);
1199
1200   if (PREDICT_TRUE (do_flush == 0))
1201     {
1202       u64 time_stamp = clib_host_to_net_u64 (now);
1203       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1204       offset += sizeof (time_stamp);
1205
1206       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1207       offset += sizeof (nat_event);
1208
1209       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1210       offset += sizeof (quota_event);
1211
1212       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
1213       offset += sizeof (limit);
1214
1215       clib_memcpy_fast (b0->data + offset, src, sizeof (ip6_address_t));
1216       offset += sizeof (ip6_address_t);
1217
1218       b0->current_length += MAX_FRAGMENTS_IP6_LEN;
1219     }
1220
1221   if (PREDICT_FALSE
1222       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1223     {
1224       snat_ipfix_send (frm, f, b0, silm->max_frags_ip6_template_id);
1225       silm->max_frags_ip6_frame = 0;
1226       silm->max_frags_ip6_buffer = 0;
1227       offset = 0;
1228     }
1229   silm->max_frags_ip6_next_record_offset = offset;
1230 }
1231
1232 static void
1233 nat_ipfix_logging_nat64_bibe (u8 nat_event, ip6_address_t * src_ip,
1234                               u32 nat_src_ip, u8 proto, u16 src_port,
1235                               u16 nat_src_port, u32 vrf_id, int do_flush)
1236 {
1237   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1238   flow_report_main_t *frm = &flow_report_main;
1239   vlib_frame_t *f;
1240   vlib_buffer_t *b0 = 0;
1241   u32 bi0 = ~0;
1242   u32 offset;
1243   vlib_main_t *vm = frm->vlib_main;
1244   u64 now;
1245
1246   if (!silm->enabled)
1247     return;
1248
1249   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1250   now += silm->milisecond_time_0;
1251
1252   b0 = silm->nat64_bib_buffer;
1253
1254   if (PREDICT_FALSE (b0 == 0))
1255     {
1256       if (do_flush)
1257         return;
1258
1259       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1260         {
1261           nat_log_err ("can't allocate buffer for NAT IPFIX event");
1262           return;
1263         }
1264
1265       b0 = silm->nat64_bib_buffer = vlib_get_buffer (vm, bi0);
1266       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1267       offset = 0;
1268     }
1269   else
1270     {
1271       bi0 = vlib_get_buffer_index (vm, b0);
1272       offset = silm->nat64_bib_next_record_offset;
1273     }
1274
1275   f = silm->nat64_bib_frame;
1276   if (PREDICT_FALSE (f == 0))
1277     {
1278       u32 *to_next;
1279       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1280       silm->nat64_bib_frame = f;
1281       to_next = vlib_frame_vector_args (f);
1282       to_next[0] = bi0;
1283       f->n_vectors = 1;
1284     }
1285
1286   if (PREDICT_FALSE (offset == 0))
1287     snat_ipfix_header_create (frm, b0, &offset);
1288
1289   if (PREDICT_TRUE (do_flush == 0))
1290     {
1291       u64 time_stamp = clib_host_to_net_u64 (now);
1292       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1293       offset += sizeof (time_stamp);
1294
1295       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1296       offset += sizeof (nat_event);
1297
1298       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1299       offset += sizeof (ip6_address_t);
1300
1301       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1302       offset += sizeof (nat_src_ip);
1303
1304       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1305       offset += sizeof (proto);
1306
1307       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1308       offset += sizeof (src_port);
1309
1310       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1311       offset += sizeof (nat_src_port);
1312
1313       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1314       offset += sizeof (vrf_id);
1315
1316       b0->current_length += NAT64_BIB_LEN;
1317     }
1318
1319   if (PREDICT_FALSE
1320       (do_flush || (offset + NAT64_BIB_LEN) > frm->path_mtu))
1321     {
1322       snat_ipfix_send (frm, f, b0, silm->nat64_bib_template_id);
1323       silm->nat64_bib_frame = 0;
1324       silm->nat64_bib_buffer = 0;
1325       offset = 0;
1326     }
1327   silm->nat64_bib_next_record_offset = offset;
1328 }
1329
1330 static void
1331 nat_ipfix_logging_nat64_ses (u8 nat_event, ip6_address_t * src_ip,
1332                              u32 nat_src_ip, u8 proto, u16 src_port,
1333                              u16 nat_src_port, ip6_address_t * dst_ip,
1334                              u32 nat_dst_ip, u16 dst_port, u16 nat_dst_port,
1335                              u32 vrf_id, int do_flush)
1336 {
1337   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1338   flow_report_main_t *frm = &flow_report_main;
1339   vlib_frame_t *f;
1340   vlib_buffer_t *b0 = 0;
1341   u32 bi0 = ~0;
1342   u32 offset;
1343   vlib_main_t *vm = frm->vlib_main;
1344   u64 now;
1345
1346   if (!silm->enabled)
1347     return;
1348
1349   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1350   now += silm->milisecond_time_0;
1351
1352   b0 = silm->nat64_ses_buffer;
1353
1354   if (PREDICT_FALSE (b0 == 0))
1355     {
1356       if (do_flush)
1357         return;
1358
1359       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1360         {
1361           nat_log_err ("can't allocate buffer for NAT IPFIX event");
1362           return;
1363         }
1364
1365       b0 = silm->nat64_ses_buffer = vlib_get_buffer (vm, bi0);
1366       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1367       offset = 0;
1368     }
1369   else
1370     {
1371       bi0 = vlib_get_buffer_index (vm, b0);
1372       offset = silm->nat64_ses_next_record_offset;
1373     }
1374
1375   f = silm->nat64_ses_frame;
1376   if (PREDICT_FALSE (f == 0))
1377     {
1378       u32 *to_next;
1379       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1380       silm->nat64_ses_frame = f;
1381       to_next = vlib_frame_vector_args (f);
1382       to_next[0] = bi0;
1383       f->n_vectors = 1;
1384     }
1385
1386   if (PREDICT_FALSE (offset == 0))
1387     snat_ipfix_header_create (frm, b0, &offset);
1388
1389   if (PREDICT_TRUE (do_flush == 0))
1390     {
1391       u64 time_stamp = clib_host_to_net_u64 (now);
1392       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1393       offset += sizeof (time_stamp);
1394
1395       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1396       offset += sizeof (nat_event);
1397
1398       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1399       offset += sizeof (ip6_address_t);
1400
1401       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1402       offset += sizeof (nat_src_ip);
1403
1404       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1405       offset += sizeof (proto);
1406
1407       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1408       offset += sizeof (src_port);
1409
1410       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1411       offset += sizeof (nat_src_port);
1412
1413       clib_memcpy_fast (b0->data + offset, dst_ip, sizeof (ip6_address_t));
1414       offset += sizeof (ip6_address_t);
1415
1416       clib_memcpy_fast (b0->data + offset, &nat_dst_ip, sizeof (nat_dst_ip));
1417       offset += sizeof (nat_dst_ip);
1418
1419       clib_memcpy_fast (b0->data + offset, &dst_port, sizeof (dst_port));
1420       offset += sizeof (dst_port);
1421
1422       clib_memcpy_fast (b0->data + offset, &nat_dst_port, sizeof (nat_dst_port));
1423       offset += sizeof (nat_dst_port);
1424
1425       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1426       offset += sizeof (vrf_id);
1427
1428       b0->current_length += NAT64_SES_LEN;
1429     }
1430
1431   if (PREDICT_FALSE
1432       (do_flush || (offset + NAT64_SES_LEN) > frm->path_mtu))
1433     {
1434       snat_ipfix_send (frm, f, b0, silm->nat64_ses_template_id);
1435       silm->nat64_ses_frame = 0;
1436       silm->nat64_ses_buffer = 0;
1437       offset = 0;
1438     }
1439   silm->nat64_ses_next_record_offset = offset;
1440 }
1441
1442 static void
1443 snat_ipfix_logging_nat44_ses_rpc_cb (snat_ipfix_logging_nat44_ses_args_t * a)
1444 {
1445   snat_ipfix_logging_nat44_ses (a->nat_event, a->src_ip, a->nat_src_ip,
1446                                 a->snat_proto, a->src_port, a->nat_src_port,
1447                                 a->vrf_id, 0);
1448 }
1449
1450 /**
1451  * @brief Generate NAT44 session create event
1452  *
1453  * @param src_ip       source IPv4 address
1454  * @param nat_src_ip   transaltes source IPv4 address
1455  * @param snat_proto   NAT transport protocol
1456  * @param src_port     source port
1457  * @param nat_src_port translated source port
1458  * @param vrf_id       VRF ID
1459  */
1460 void
1461 snat_ipfix_logging_nat44_ses_create (u32 src_ip,
1462                                      u32 nat_src_ip,
1463                                      snat_protocol_t snat_proto,
1464                                      u16 src_port,
1465                                      u16 nat_src_port, u32 vrf_id)
1466 {
1467   snat_ipfix_logging_nat44_ses_args_t a;
1468
1469   skip_if_disabled ();
1470
1471   a.nat_event = NAT44_SESSION_CREATE;
1472   a.src_ip = src_ip;
1473   a.nat_src_ip = nat_src_ip;
1474   a.snat_proto = snat_proto;
1475   a.src_port = src_port;
1476   a.nat_src_port = nat_src_port;
1477   a.vrf_id = vrf_id;
1478
1479   vl_api_rpc_call_main_thread (snat_ipfix_logging_nat44_ses_rpc_cb,
1480                                (u8 *) & a, sizeof (a));
1481 }
1482
1483 /**
1484  * @brief Generate NAT44 session delete event
1485  *
1486  * @param src_ip       source IPv4 address
1487  * @param nat_src_ip   transaltes source IPv4 address
1488  * @param snat_proto   NAT transport protocol
1489  * @param src_port     source port
1490  * @param nat_src_port translated source port
1491  * @param vrf_id       VRF ID
1492  */
1493 void
1494 snat_ipfix_logging_nat44_ses_delete (u32 src_ip,
1495                                      u32 nat_src_ip,
1496                                      snat_protocol_t snat_proto,
1497                                      u16 src_port,
1498                                      u16 nat_src_port, u32 vrf_id)
1499 {
1500   snat_ipfix_logging_nat44_ses_args_t a;
1501
1502   skip_if_disabled ();
1503
1504   a.nat_event = NAT44_SESSION_DELETE;
1505   a.src_ip = src_ip;
1506   a.nat_src_ip = nat_src_ip;
1507   a.snat_proto = snat_proto;
1508   a.src_port = src_port;
1509   a.nat_src_port = nat_src_port;
1510   a.vrf_id = vrf_id;
1511
1512   vl_api_rpc_call_main_thread (snat_ipfix_logging_nat44_ses_rpc_cb,
1513                                (u8 *) & a, sizeof (a));
1514 }
1515
1516 vlib_frame_t *
1517 snat_data_callback_nat44_session (flow_report_main_t * frm,
1518                                   flow_report_t * fr,
1519                                   vlib_frame_t * f,
1520                                   u32 * to_next, u32 node_index)
1521 {
1522   snat_ipfix_logging_nat44_ses (0, 0, 0, 0, 0, 0, 0, 1);
1523   return f;
1524 }
1525
1526 static void
1527   snat_ipfix_logging_addr_exhausted_rpc_cb
1528   (snat_ipfix_logging_addr_exhausted_args_t * a)
1529 {
1530   snat_ipfix_logging_addr_exhausted (a->pool_id, 0);
1531 }
1532
1533 /**
1534  * @brief Generate NAT addresses exhausted event
1535  *
1536  * @param pool_id NAT pool ID
1537  */
1538 void
1539 snat_ipfix_logging_addresses_exhausted (u32 pool_id)
1540 {
1541   //TODO: This event SHOULD be rate limited
1542   snat_ipfix_logging_addr_exhausted_args_t a;
1543
1544   skip_if_disabled ();
1545
1546   a.pool_id = pool_id;
1547
1548   vl_api_rpc_call_main_thread (snat_ipfix_logging_addr_exhausted_rpc_cb,
1549                                (u8 *) & a, sizeof (a));
1550 }
1551
1552 vlib_frame_t *
1553 snat_data_callback_addr_exhausted (flow_report_main_t * frm,
1554                                    flow_report_t * fr,
1555                                    vlib_frame_t * f,
1556                                    u32 * to_next, u32 node_index)
1557 {
1558   snat_ipfix_logging_addr_exhausted (0, 1);
1559   return f;
1560 }
1561
1562 static void
1563   snat_ipfix_logging_max_entries_per_usr_rpc_cb
1564   (snat_ipfix_logging_max_entries_per_user_args_t * a)
1565 {
1566   snat_ipfix_logging_max_entries_per_usr (a->limit, a->src_ip, 0);
1567 }
1568
1569 /**
1570  * @brief Generate maximum entries per user exceeded event
1571  *
1572  * @param limit maximum NAT entries that can be created per user
1573  * @param src_ip source IPv4 address
1574  */
1575 void
1576 snat_ipfix_logging_max_entries_per_user (u32 limit, u32 src_ip)
1577 {
1578   //TODO: This event SHOULD be rate limited
1579   snat_ipfix_logging_max_entries_per_user_args_t a;
1580
1581   skip_if_disabled ();
1582
1583   a.limit = limit;
1584   a.src_ip = src_ip;
1585
1586   vl_api_rpc_call_main_thread (snat_ipfix_logging_max_entries_per_usr_rpc_cb,
1587                                (u8 *) & a, sizeof (a));
1588 }
1589
1590 vlib_frame_t *
1591 snat_data_callback_max_entries_per_usr (flow_report_main_t * frm,
1592                                         flow_report_t * fr,
1593                                         vlib_frame_t * f,
1594                                         u32 * to_next, u32 node_index)
1595 {
1596   snat_ipfix_logging_max_entries_per_usr (0, 0, 1);
1597   return f;
1598 }
1599
1600 static void
1601 nat_ipfix_logging_max_ses_rpc_cb (nat_ipfix_logging_max_sessions_args_t * a)
1602 {
1603   nat_ipfix_logging_max_ses (a->limit, 0);
1604 }
1605
1606 /**
1607  * @brief Generate maximum session entries exceeded event
1608  *
1609  * @param limit configured limit
1610  */
1611 void
1612 nat_ipfix_logging_max_sessions (u32 limit)
1613 {
1614   //TODO: This event SHOULD be rate limited
1615   nat_ipfix_logging_max_sessions_args_t a;
1616
1617   skip_if_disabled ();
1618
1619   a.limit = limit;
1620
1621   vl_api_rpc_call_main_thread (nat_ipfix_logging_max_ses_rpc_cb,
1622                                (u8 *) & a, sizeof (a));
1623 }
1624
1625 vlib_frame_t *
1626 nat_data_callback_max_sessions (flow_report_main_t * frm,
1627                                 flow_report_t * fr,
1628                                 vlib_frame_t * f,
1629                                 u32 * to_next, u32 node_index)
1630 {
1631   nat_ipfix_logging_max_ses (0, 1);
1632   return f;
1633 }
1634
1635 static void
1636 nat_ipfix_logging_max_bib_rpc_cb (nat_ipfix_logging_max_bibs_args_t * a)
1637 {
1638   nat_ipfix_logging_max_bib (a->limit, 0);
1639 }
1640
1641 /**
1642  * @brief Generate maximum BIB entries exceeded event
1643  *
1644  * @param limit configured limit
1645  */
1646 void
1647 nat_ipfix_logging_max_bibs (u32 limit)
1648 {
1649   //TODO: This event SHOULD be rate limited
1650   nat_ipfix_logging_max_bibs_args_t a;
1651
1652   skip_if_disabled ();
1653
1654   a.limit = limit;
1655
1656   vl_api_rpc_call_main_thread (nat_ipfix_logging_max_bib_rpc_cb,
1657                                (u8 *) & a, sizeof (a));
1658 }
1659
1660 vlib_frame_t *
1661 nat_data_callback_max_bibs (flow_report_main_t * frm,
1662                             flow_report_t * fr,
1663                             vlib_frame_t * f,
1664                             u32 * to_next, u32 node_index)
1665 {
1666   nat_ipfix_logging_max_bib (0, 1);
1667   return f;
1668 }
1669
1670 static void
1671 nat_ipfix_logging_max_frag_ip4_rpc_cb (nat_ipfix_logging_max_frags_ip4_args_t * a)
1672 {
1673   nat_ipfix_logging_max_frag_ip4 (a->limit, a->src, 0);
1674 }
1675
1676 /**
1677  * @brief Generate maximum IPv4 fragments pending reassembly exceeded event
1678  *
1679  * @param limit configured limit
1680  * @param src source IPv4 address
1681  */
1682 void
1683 nat_ipfix_logging_max_fragments_ip4 (u32 limit, ip4_address_t * src)
1684 {
1685   //TODO: This event SHOULD be rate limited
1686   nat_ipfix_logging_max_frags_ip4_args_t a;
1687
1688   skip_if_disabled ();
1689
1690   a.limit = limit;
1691   a.src = src->as_u32;
1692
1693   vl_api_rpc_call_main_thread (nat_ipfix_logging_max_frag_ip4_rpc_cb,
1694                                (u8 *) & a, sizeof (a));
1695 }
1696
1697 vlib_frame_t *
1698 nat_data_callback_max_frags_ip4 (flow_report_main_t * frm,
1699                                  flow_report_t * fr,
1700                                  vlib_frame_t * f,
1701                                  u32 * to_next, u32 node_index)
1702 {
1703   nat_ipfix_logging_max_frag_ip4 (0, 0, 1);
1704   return f;
1705 }
1706
1707 static void
1708 nat_ipfix_logging_max_frag_ip6_rpc_cb (nat_ipfix_logging_max_frags_ip6_args_t * a)
1709 {
1710   ip6_address_t src;
1711   src.as_u64[0] = a->src[0];
1712   src.as_u64[1] = a->src[1];
1713   nat_ipfix_logging_max_frag_ip6 (a->limit, &src, 0);
1714 }
1715
1716 /**
1717  * @brief Generate maximum IPv6 fragments pending reassembly exceeded event
1718  *
1719  * @param limit configured limit
1720  * @param src source IPv6 address
1721  */
1722 void
1723 nat_ipfix_logging_max_fragments_ip6 (u32 limit, ip6_address_t * src)
1724 {
1725   //TODO: This event SHOULD be rate limited
1726   nat_ipfix_logging_max_frags_ip6_args_t a;
1727
1728   skip_if_disabled ();
1729
1730   a.limit = limit;
1731   a.src[0] = src->as_u64[0];
1732   a.src[1] = src->as_u64[1];
1733
1734   vl_api_rpc_call_main_thread (nat_ipfix_logging_max_frag_ip6_rpc_cb,
1735                                (u8 *) & a, sizeof (a));
1736 }
1737
1738 vlib_frame_t *
1739 nat_data_callback_max_frags_ip6 (flow_report_main_t * frm,
1740                                  flow_report_t * fr,
1741                                  vlib_frame_t * f,
1742                                  u32 * to_next, u32 node_index)
1743 {
1744   nat_ipfix_logging_max_frag_ip6 (0, 0, 1);
1745   return f;
1746 }
1747
1748 static void
1749 nat_ipfix_logging_nat64_bib_rpc_cb (nat_ipfix_logging_nat64_bib_args_t * a)
1750 {
1751   ip6_address_t src_ip;
1752   src_ip.as_u64[0] = a->src_ip[0];
1753   src_ip.as_u64[1] = a->src_ip[1];
1754   nat_ipfix_logging_nat64_bibe (a->nat_event, &src_ip, a->nat_src_ip,
1755                                 a->proto, a->src_port, a->nat_src_port,
1756                                 a->vrf_id, 0);
1757 }
1758
1759 /**
1760  * @brief Generate NAT64 BIB create and delete events
1761  *
1762  * @param src_ip       source IPv6 address
1763  * @param nat_src_ip   transaltes source IPv4 address
1764  * @param proto        L4 protocol
1765  * @param src_port     source port
1766  * @param nat_src_port translated source port
1767  * @param vrf_id       VRF ID
1768  * @param is_create    non-zero value if create event otherwise delete event
1769  */
1770 void
1771 nat_ipfix_logging_nat64_bib (ip6_address_t * src_ip,
1772                              ip4_address_t * nat_src_ip, u8 proto,
1773                              u16 src_port, u16 nat_src_port, u32 vrf_id,
1774                              u8 is_create)
1775 {
1776   nat_ipfix_logging_nat64_bib_args_t a;
1777
1778   skip_if_disabled ();
1779
1780   a.src_ip[0] = src_ip->as_u64[0];
1781   a.src_ip[1] = src_ip->as_u64[1];
1782   a.nat_src_ip = nat_src_ip->as_u32;
1783   a.proto = proto;
1784   a.src_port = src_port;
1785   a.nat_src_port = nat_src_port;
1786   a.vrf_id = vrf_id;
1787   a.nat_event = is_create ? NAT64_BIB_CREATE : NAT64_BIB_DELETE;
1788
1789   vl_api_rpc_call_main_thread (nat_ipfix_logging_nat64_bib_rpc_cb,
1790                                (u8 *) & a, sizeof (a));
1791 }
1792
1793 vlib_frame_t *
1794 nat_data_callback_nat64_bib (flow_report_main_t * frm,
1795                              flow_report_t * fr,
1796                              vlib_frame_t * f,
1797                              u32 * to_next, u32 node_index)
1798 {
1799   nat_ipfix_logging_nat64_bibe (0, 0, 0, 0, 0, 0, 0, 1);
1800   return f;
1801 }
1802
1803 static void
1804 nat_ipfix_logging_nat64_ses_rpc_cb (nat_ipfix_logging_nat64_ses_args_t * a)
1805 {
1806   ip6_address_t src_ip, dst_ip;
1807   src_ip.as_u64[0] = a->src_ip[0];
1808   src_ip.as_u64[1] = a->src_ip[1];
1809   dst_ip.as_u64[0] = a->dst_ip[0];
1810   dst_ip.as_u64[1] = a->dst_ip[1];
1811   nat_ipfix_logging_nat64_ses (a->nat_event, &src_ip, a->nat_src_ip,
1812                                a->proto, a->src_port, a->nat_src_port,
1813                                &dst_ip, a->nat_dst_ip, a->dst_port,
1814                                a->nat_dst_port, a->vrf_id, 0);
1815 }
1816
1817 /**
1818  * @brief Generate NAT64 session create and delete events
1819  *
1820  * @param src_ip       source IPv6 address
1821  * @param nat_src_ip   transaltes source IPv4 address
1822  * @param proto        L4 protocol
1823  * @param src_port     source port
1824  * @param nat_src_port translated source port
1825  * @param dst_ip       destination IPv6 address
1826  * @param nat_dst_ip   destination IPv4 address
1827  * @param dst_port     destination port
1828  * @param nat_dst_port translated destination port
1829  * @param vrf_id       VRF ID
1830  * @param is_create    non-zero value if create event otherwise delete event
1831  */
1832 void
1833 nat_ipfix_logging_nat64_session (ip6_address_t * src_ip,
1834                                  ip4_address_t * nat_src_ip, u8 proto,
1835                                  u16 src_port, u16 nat_src_port,
1836                                  ip6_address_t * dst_ip,
1837                                  ip4_address_t * nat_dst_ip, u16 dst_port,
1838                                  u16 nat_dst_port, u32 vrf_id, u8 is_create)
1839 {
1840   nat_ipfix_logging_nat64_ses_args_t a;
1841
1842   skip_if_disabled ();
1843
1844   a.src_ip[0] = src_ip->as_u64[0];
1845   a.src_ip[1] = src_ip->as_u64[1];
1846   a.nat_src_ip = nat_src_ip->as_u32;
1847   a.proto = proto;
1848   a.src_port = src_port;
1849   a.nat_src_port = nat_src_port;
1850   a.dst_ip[0] = dst_ip->as_u64[0];
1851   a.dst_ip[1] = dst_ip->as_u64[1];
1852   a.nat_dst_ip = nat_dst_ip->as_u32;
1853   a.dst_port = dst_port;
1854   a.nat_dst_port = nat_dst_port;
1855   a.vrf_id = vrf_id;
1856   a.nat_event = is_create ? NAT64_SESSION_CREATE : NAT64_SESSION_DELETE;
1857
1858   vl_api_rpc_call_main_thread (nat_ipfix_logging_nat64_ses_rpc_cb,
1859                                (u8 *) & a, sizeof (a));
1860 }
1861
1862 vlib_frame_t *
1863 nat_data_callback_nat64_session (flow_report_main_t * frm,
1864                                  flow_report_t * fr,
1865                                  vlib_frame_t * f,
1866                                  u32 * to_next, u32 node_index)
1867 {
1868   nat_ipfix_logging_nat64_ses (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
1869   return f;
1870 }
1871
1872 /**
1873  * @brief Enable/disable NAT plugin IPFIX logging
1874  *
1875  * @param enable    1 if enable, 0 if disable
1876  * @param domain_id observation domain ID
1877  * @param src_port  source port number
1878  *
1879  * @returns 0 if success
1880  */
1881 int
1882 snat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
1883 {
1884   snat_main_t *sm = &snat_main;
1885   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1886   flow_report_main_t *frm = &flow_report_main;
1887   vnet_flow_report_add_del_args_t a;
1888   int rv;
1889   u8 e = enable ? 1 : 0;
1890
1891   if (silm->enabled == e)
1892     return 0;
1893
1894   silm->enabled = e;
1895
1896   clib_memset (&a, 0, sizeof (a));
1897   a.is_add = enable;
1898   a.domain_id = domain_id ? domain_id : 1;
1899   a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
1900
1901   if (sm->deterministic)
1902     {
1903       a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
1904       a.flow_data_callback = snat_data_callback_max_entries_per_usr;
1905
1906       rv = vnet_flow_report_add_del (frm, &a, NULL);
1907       if (rv)
1908         {
1909           nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
1910           return -1;
1911         }
1912     }
1913   else
1914     {
1915       a.rewrite_callback = snat_template_rewrite_nat44_session;
1916       a.flow_data_callback = snat_data_callback_nat44_session;
1917
1918       rv = vnet_flow_report_add_del (frm, &a, NULL);
1919       if (rv)
1920         {
1921           nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
1922           return -1;
1923         }
1924
1925       a.rewrite_callback = snat_template_rewrite_addr_exhausted;
1926       a.flow_data_callback = snat_data_callback_addr_exhausted;
1927
1928       rv = vnet_flow_report_add_del (frm, &a, NULL);
1929       if (rv)
1930         {
1931           nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
1932           return -1;
1933         }
1934
1935       a.rewrite_callback = nat_template_rewrite_max_sessions;
1936       a.flow_data_callback = nat_data_callback_max_sessions;
1937
1938       rv = vnet_flow_report_add_del (frm, &a, NULL);
1939       if (rv)
1940         {
1941           nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
1942           return -1;
1943         }
1944
1945       a.rewrite_callback = nat_template_rewrite_max_bibs;
1946       a.flow_data_callback = nat_data_callback_max_bibs;
1947
1948       rv = vnet_flow_report_add_del (frm, &a, NULL);
1949       if (rv)
1950         {
1951           nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
1952           return -1;
1953         }
1954
1955       a.rewrite_callback = nat_template_rewrite_max_frags_ip4;
1956       a.flow_data_callback = nat_data_callback_max_frags_ip4;
1957
1958       rv = vnet_flow_report_add_del (frm, &a, NULL);
1959       if (rv)
1960         {
1961           nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
1962           return -1;
1963         }
1964
1965       a.rewrite_callback = nat_template_rewrite_max_frags_ip6;
1966       a.flow_data_callback = nat_data_callback_max_frags_ip6;
1967
1968       rv = vnet_flow_report_add_del (frm, &a, NULL);
1969       if (rv)
1970         {
1971           nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
1972           return -1;
1973         }
1974
1975       a.rewrite_callback = nat_template_rewrite_nat64_bib;
1976       a.flow_data_callback = nat_data_callback_nat64_bib;
1977
1978       rv = vnet_flow_report_add_del (frm, &a, NULL);
1979       if (rv)
1980         {
1981           nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
1982           return -1;
1983         }
1984
1985       a.rewrite_callback = nat_template_rewrite_nat64_session;
1986       a.flow_data_callback = nat_data_callback_nat64_session;
1987
1988       rv = vnet_flow_report_add_del (frm, &a, NULL);
1989       if (rv)
1990         {
1991           nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
1992           return -1;
1993         }
1994
1995       if (sm->endpoint_dependent)
1996         {
1997           a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
1998           a.flow_data_callback = snat_data_callback_max_entries_per_usr;
1999
2000           rv = vnet_flow_report_add_del (frm, &a, NULL);
2001           if (rv)
2002             {
2003               nat_log_warn ("vnet_flow_report_add_del returned %d", rv);
2004               return -1;
2005             }
2006         }
2007     }
2008
2009   return 0;
2010 }
2011
2012 /**
2013  * @brief Initialize NAT plugin IPFIX logging
2014  *
2015  * @param vm vlib main
2016  */
2017 void
2018 snat_ipfix_logging_init (vlib_main_t * vm)
2019 {
2020   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
2021
2022   silm->enabled = 0;
2023
2024   /* Set up time reference pair */
2025   silm->vlib_time_0 = vlib_time_now (vm);
2026   silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
2027 }