NAT44: add support for session timeout (VPP-1272)
[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   vlib_buffer_free_list_t *fl;
624   u8 proto = ~0;
625
626   if (!silm->enabled)
627     return;
628
629   proto = snat_proto_to_ip_proto (snat_proto);
630
631   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
632   now += silm->milisecond_time_0;
633
634   b0 = silm->nat44_session_buffer;
635
636   if (PREDICT_FALSE (b0 == 0))
637     {
638       if (do_flush)
639         return;
640
641       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
642         {
643           clib_warning ("can't allocate buffer for NAT IPFIX event");
644           return;
645         }
646
647       b0 = silm->nat44_session_buffer = vlib_get_buffer (vm, bi0);
648       fl =
649         vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
650       vlib_buffer_init_for_free_list (b0, fl);
651       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
652       offset = 0;
653     }
654   else
655     {
656       bi0 = vlib_get_buffer_index (vm, b0);
657       offset = silm->nat44_session_next_record_offset;
658     }
659
660   f = silm->nat44_session_frame;
661   if (PREDICT_FALSE (f == 0))
662     {
663       u32 *to_next;
664       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
665       silm->nat44_session_frame = f;
666       to_next = vlib_frame_vector_args (f);
667       to_next[0] = bi0;
668       f->n_vectors = 1;
669     }
670
671   if (PREDICT_FALSE (offset == 0))
672     snat_ipfix_header_create (frm, b0, &offset);
673
674   if (PREDICT_TRUE (do_flush == 0))
675     {
676       u64 time_stamp = clib_host_to_net_u64 (now);
677       clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
678       offset += sizeof (time_stamp);
679
680       clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
681       offset += sizeof (nat_event);
682
683       clib_memcpy (b0->data + offset, &src_ip, sizeof (src_ip));
684       offset += sizeof (src_ip);
685
686       clib_memcpy (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
687       offset += sizeof (nat_src_ip);
688
689       clib_memcpy (b0->data + offset, &proto, sizeof (proto));
690       offset += sizeof (proto);
691
692       clib_memcpy (b0->data + offset, &src_port, sizeof (src_port));
693       offset += sizeof (src_port);
694
695       clib_memcpy (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
696       offset += sizeof (nat_src_port);
697
698       clib_memcpy (b0->data + offset, &vrf_id, sizeof (vrf_id));
699       offset += sizeof (vrf_id);
700
701       b0->current_length += NAT44_SESSION_CREATE_LEN;
702     }
703
704   if (PREDICT_FALSE
705       (do_flush || (offset + NAT44_SESSION_CREATE_LEN) > frm->path_mtu))
706     {
707       snat_ipfix_send (frm, f, b0, silm->nat44_session_template_id);
708       silm->nat44_session_frame = 0;
709       silm->nat44_session_buffer = 0;
710       offset = 0;
711     }
712   silm->nat44_session_next_record_offset = offset;
713 }
714
715 static void
716 snat_ipfix_logging_addr_exhausted (u32 pool_id, int do_flush)
717 {
718   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
719   flow_report_main_t *frm = &flow_report_main;
720   vlib_frame_t *f;
721   vlib_buffer_t *b0 = 0;
722   u32 bi0 = ~0;
723   u32 offset;
724   vlib_main_t *vm = frm->vlib_main;
725   u64 now;
726   vlib_buffer_free_list_t *fl;
727   u8 nat_event = NAT_ADDRESSES_EXHAUTED;
728
729   if (!silm->enabled)
730     return;
731
732   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
733   now += silm->milisecond_time_0;
734
735   b0 = silm->addr_exhausted_buffer;
736
737   if (PREDICT_FALSE (b0 == 0))
738     {
739       if (do_flush)
740         return;
741
742       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
743         {
744           clib_warning ("can't allocate buffer for NAT IPFIX event");
745           return;
746         }
747
748       b0 = silm->addr_exhausted_buffer = vlib_get_buffer (vm, bi0);
749       fl =
750         vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
751       vlib_buffer_init_for_free_list (b0, fl);
752       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
753       offset = 0;
754     }
755   else
756     {
757       bi0 = vlib_get_buffer_index (vm, b0);
758       offset = silm->addr_exhausted_next_record_offset;
759     }
760
761   f = silm->addr_exhausted_frame;
762   if (PREDICT_FALSE (f == 0))
763     {
764       u32 *to_next;
765       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
766       silm->addr_exhausted_frame = f;
767       to_next = vlib_frame_vector_args (f);
768       to_next[0] = bi0;
769       f->n_vectors = 1;
770     }
771
772   if (PREDICT_FALSE (offset == 0))
773     snat_ipfix_header_create (frm, b0, &offset);
774
775   if (PREDICT_TRUE (do_flush == 0))
776     {
777       u64 time_stamp = clib_host_to_net_u64 (now);
778       clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
779       offset += sizeof (time_stamp);
780
781       clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
782       offset += sizeof (nat_event);
783
784       clib_memcpy (b0->data + offset, &pool_id, sizeof (pool_id));
785       offset += sizeof (pool_id);
786
787       b0->current_length += NAT_ADDRESSES_EXHAUTED_LEN;
788     }
789
790   if (PREDICT_FALSE
791       (do_flush || (offset + NAT_ADDRESSES_EXHAUTED_LEN) > frm->path_mtu))
792     {
793       snat_ipfix_send (frm, f, b0, silm->addr_exhausted_template_id);
794       silm->addr_exhausted_frame = 0;
795       silm->addr_exhausted_buffer = 0;
796       offset = 0;
797     }
798   silm->addr_exhausted_next_record_offset = offset;
799 }
800
801 static void
802 snat_ipfix_logging_max_entries_per_usr (u32 limit, u32 src_ip, int do_flush)
803 {
804   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
805   flow_report_main_t *frm = &flow_report_main;
806   vlib_frame_t *f;
807   vlib_buffer_t *b0 = 0;
808   u32 bi0 = ~0;
809   u32 offset;
810   vlib_main_t *vm = frm->vlib_main;
811   u64 now;
812   vlib_buffer_free_list_t *fl;
813   u8 nat_event = QUOTA_EXCEEDED;
814   u32 quota_event = MAX_ENTRIES_PER_USER;
815
816   if (!silm->enabled)
817     return;
818
819   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
820   now += silm->milisecond_time_0;
821
822   b0 = silm->max_entries_per_user_buffer;
823
824   if (PREDICT_FALSE (b0 == 0))
825     {
826       if (do_flush)
827         return;
828
829       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
830         {
831           clib_warning ("can't allocate buffer for NAT IPFIX event");
832           return;
833         }
834
835       b0 = silm->max_entries_per_user_buffer = vlib_get_buffer (vm, bi0);
836       fl =
837         vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
838       vlib_buffer_init_for_free_list (b0, fl);
839       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
840       offset = 0;
841     }
842   else
843     {
844       bi0 = vlib_get_buffer_index (vm, b0);
845       offset = silm->max_entries_per_user_next_record_offset;
846     }
847
848   f = silm->max_entries_per_user_frame;
849   if (PREDICT_FALSE (f == 0))
850     {
851       u32 *to_next;
852       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
853       silm->max_entries_per_user_frame = f;
854       to_next = vlib_frame_vector_args (f);
855       to_next[0] = bi0;
856       f->n_vectors = 1;
857     }
858
859   if (PREDICT_FALSE (offset == 0))
860     snat_ipfix_header_create (frm, b0, &offset);
861
862   if (PREDICT_TRUE (do_flush == 0))
863     {
864       u64 time_stamp = clib_host_to_net_u64 (now);
865       clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
866       offset += sizeof (time_stamp);
867
868       clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
869       offset += sizeof (nat_event);
870
871       clib_memcpy (b0->data + offset, &quota_event, sizeof (quota_event));
872       offset += sizeof (quota_event);
873
874       clib_memcpy (b0->data + offset, &limit, sizeof (limit));
875       offset += sizeof (limit);
876
877       clib_memcpy (b0->data + offset, &src_ip, sizeof (src_ip));
878       offset += sizeof (src_ip);
879
880       b0->current_length += MAX_ENTRIES_PER_USER_LEN;
881     }
882
883   if (PREDICT_FALSE
884       (do_flush || (offset + MAX_ENTRIES_PER_USER_LEN) > frm->path_mtu))
885     {
886       snat_ipfix_send (frm, f, b0, silm->max_entries_per_user_template_id);
887       silm->max_entries_per_user_frame = 0;
888       silm->max_entries_per_user_buffer = 0;
889       offset = 0;
890     }
891   silm->max_entries_per_user_next_record_offset = offset;
892 }
893
894 static void
895 nat_ipfix_logging_max_ses (u32 limit, int do_flush)
896 {
897   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
898   flow_report_main_t *frm = &flow_report_main;
899   vlib_frame_t *f;
900   vlib_buffer_t *b0 = 0;
901   u32 bi0 = ~0;
902   u32 offset;
903   vlib_main_t *vm = frm->vlib_main;
904   u64 now;
905   vlib_buffer_free_list_t *fl;
906   u8 nat_event = QUOTA_EXCEEDED;
907   u32 quota_event = MAX_SESSION_ENTRIES;
908
909   if (!silm->enabled)
910     return;
911
912   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
913   now += silm->milisecond_time_0;
914
915   b0 = silm->max_sessions_buffer;
916
917   if (PREDICT_FALSE (b0 == 0))
918     {
919       if (do_flush)
920         return;
921
922       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
923         {
924           clib_warning ("can't allocate buffer for NAT IPFIX event");
925           return;
926         }
927
928       b0 = silm->max_sessions_buffer = vlib_get_buffer (vm, bi0);
929       fl =
930         vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
931       vlib_buffer_init_for_free_list (b0, fl);
932       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
933       offset = 0;
934     }
935   else
936     {
937       bi0 = vlib_get_buffer_index (vm, b0);
938       offset = silm->max_sessions_next_record_offset;
939     }
940
941   f = silm->max_sessions_frame;
942   if (PREDICT_FALSE (f == 0))
943     {
944       u32 *to_next;
945       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
946       silm->max_sessions_frame = f;
947       to_next = vlib_frame_vector_args (f);
948       to_next[0] = bi0;
949       f->n_vectors = 1;
950     }
951
952   if (PREDICT_FALSE (offset == 0))
953     snat_ipfix_header_create (frm, b0, &offset);
954
955   if (PREDICT_TRUE (do_flush == 0))
956     {
957       u64 time_stamp = clib_host_to_net_u64 (now);
958       clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
959       offset += sizeof (time_stamp);
960
961       clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
962       offset += sizeof (nat_event);
963
964       clib_memcpy (b0->data + offset, &quota_event, sizeof (quota_event));
965       offset += sizeof (quota_event);
966
967       clib_memcpy (b0->data + offset, &limit, sizeof (limit));
968       offset += sizeof (limit);
969
970       b0->current_length += MAX_SESSIONS_LEN;
971     }
972
973   if (PREDICT_FALSE
974       (do_flush || (offset + MAX_SESSIONS_LEN) > frm->path_mtu))
975     {
976       snat_ipfix_send (frm, f, b0, silm->max_sessions_template_id);
977       silm->max_sessions_frame = 0;
978       silm->max_sessions_buffer = 0;
979       offset = 0;
980     }
981   silm->max_sessions_next_record_offset = offset;
982 }
983
984 static void
985 nat_ipfix_logging_max_bib (u32 limit, int do_flush)
986 {
987   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
988   flow_report_main_t *frm = &flow_report_main;
989   vlib_frame_t *f;
990   vlib_buffer_t *b0 = 0;
991   u32 bi0 = ~0;
992   u32 offset;
993   vlib_main_t *vm = frm->vlib_main;
994   u64 now;
995   vlib_buffer_free_list_t *fl;
996   u8 nat_event = QUOTA_EXCEEDED;
997   u32 quota_event = MAX_BIB_ENTRIES;
998
999   if (!silm->enabled)
1000     return;
1001
1002   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1003   now += silm->milisecond_time_0;
1004
1005   b0 = silm->max_bibs_buffer;
1006
1007   if (PREDICT_FALSE (b0 == 0))
1008     {
1009       if (do_flush)
1010         return;
1011
1012       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1013         {
1014           clib_warning ("can't allocate buffer for NAT IPFIX event");
1015           return;
1016         }
1017
1018       b0 = silm->max_bibs_buffer = vlib_get_buffer (vm, bi0);
1019       fl =
1020         vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
1021       vlib_buffer_init_for_free_list (b0, fl);
1022       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1023       offset = 0;
1024     }
1025   else
1026     {
1027       bi0 = vlib_get_buffer_index (vm, b0);
1028       offset = silm->max_bibs_next_record_offset;
1029     }
1030
1031   f = silm->max_bibs_frame;
1032   if (PREDICT_FALSE (f == 0))
1033     {
1034       u32 *to_next;
1035       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1036       silm->max_bibs_frame = f;
1037       to_next = vlib_frame_vector_args (f);
1038       to_next[0] = bi0;
1039       f->n_vectors = 1;
1040     }
1041
1042   if (PREDICT_FALSE (offset == 0))
1043     snat_ipfix_header_create (frm, b0, &offset);
1044
1045   if (PREDICT_TRUE (do_flush == 0))
1046     {
1047       u64 time_stamp = clib_host_to_net_u64 (now);
1048       clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
1049       offset += sizeof (time_stamp);
1050
1051       clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
1052       offset += sizeof (nat_event);
1053
1054       clib_memcpy (b0->data + offset, &quota_event, sizeof (quota_event));
1055       offset += sizeof (quota_event);
1056
1057       clib_memcpy (b0->data + offset, &limit, sizeof (limit));
1058       offset += sizeof (limit);
1059
1060       b0->current_length += MAX_BIBS_LEN;
1061     }
1062
1063   if (PREDICT_FALSE
1064       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1065     {
1066       snat_ipfix_send (frm, f, b0, silm->max_bibs_template_id);
1067       silm->max_bibs_frame = 0;
1068       silm->max_bibs_buffer = 0;
1069       offset = 0;
1070     }
1071   silm->max_bibs_next_record_offset = offset;
1072 }
1073
1074 static void
1075 nat_ipfix_logging_max_frag_ip4 (u32 limit, u32 src, int do_flush)
1076 {
1077   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1078   flow_report_main_t *frm = &flow_report_main;
1079   vlib_frame_t *f;
1080   vlib_buffer_t *b0 = 0;
1081   u32 bi0 = ~0;
1082   u32 offset;
1083   vlib_main_t *vm = frm->vlib_main;
1084   u64 now;
1085   vlib_buffer_free_list_t *fl;
1086   u8 nat_event = QUOTA_EXCEEDED;
1087   u32 quota_event = MAX_FRAGMENTS_PENDING_REASSEMBLY;
1088
1089   if (!silm->enabled)
1090     return;
1091
1092   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1093   now += silm->milisecond_time_0;
1094
1095   b0 = silm->max_frags_ip4_buffer;
1096
1097   if (PREDICT_FALSE (b0 == 0))
1098     {
1099       if (do_flush)
1100         return;
1101
1102       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1103         {
1104           clib_warning ("can't allocate buffer for NAT IPFIX event");
1105           return;
1106         }
1107
1108       b0 = silm->max_frags_ip4_buffer = vlib_get_buffer (vm, bi0);
1109       fl =
1110         vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
1111       vlib_buffer_init_for_free_list (b0, fl);
1112       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1113       offset = 0;
1114     }
1115   else
1116     {
1117       bi0 = vlib_get_buffer_index (vm, b0);
1118       offset = silm->max_frags_ip4_next_record_offset;
1119     }
1120
1121   f = silm->max_frags_ip4_frame;
1122   if (PREDICT_FALSE (f == 0))
1123     {
1124       u32 *to_next;
1125       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1126       silm->max_frags_ip4_frame = f;
1127       to_next = vlib_frame_vector_args (f);
1128       to_next[0] = bi0;
1129       f->n_vectors = 1;
1130     }
1131
1132   if (PREDICT_FALSE (offset == 0))
1133     snat_ipfix_header_create (frm, b0, &offset);
1134
1135   if (PREDICT_TRUE (do_flush == 0))
1136     {
1137       u64 time_stamp = clib_host_to_net_u64 (now);
1138       clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
1139       offset += sizeof (time_stamp);
1140
1141       clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
1142       offset += sizeof (nat_event);
1143
1144       clib_memcpy (b0->data + offset, &quota_event, sizeof (quota_event));
1145       offset += sizeof (quota_event);
1146
1147       clib_memcpy (b0->data + offset, &limit, sizeof (limit));
1148       offset += sizeof (limit);
1149
1150       clib_memcpy (b0->data + offset, &src, sizeof (src));
1151       offset += sizeof (src);
1152
1153       b0->current_length += MAX_FRAGMENTS_IP4_LEN;
1154     }
1155
1156   if (PREDICT_FALSE
1157       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1158     {
1159       snat_ipfix_send (frm, f, b0, silm->max_frags_ip4_template_id);
1160       silm->max_frags_ip4_frame = 0;
1161       silm->max_frags_ip4_buffer = 0;
1162       offset = 0;
1163     }
1164   silm->max_frags_ip4_next_record_offset = offset;
1165 }
1166
1167 static void
1168 nat_ipfix_logging_max_frag_ip6 (u32 limit, ip6_address_t * src, int do_flush)
1169 {
1170   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1171   flow_report_main_t *frm = &flow_report_main;
1172   vlib_frame_t *f;
1173   vlib_buffer_t *b0 = 0;
1174   u32 bi0 = ~0;
1175   u32 offset;
1176   vlib_main_t *vm = frm->vlib_main;
1177   u64 now;
1178   vlib_buffer_free_list_t *fl;
1179   u8 nat_event = QUOTA_EXCEEDED;
1180   u32 quota_event = MAX_FRAGMENTS_PENDING_REASSEMBLY;
1181
1182   if (!silm->enabled)
1183     return;
1184
1185   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1186   now += silm->milisecond_time_0;
1187
1188   b0 = silm->max_frags_ip6_buffer;
1189
1190   if (PREDICT_FALSE (b0 == 0))
1191     {
1192       if (do_flush)
1193         return;
1194
1195       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1196         {
1197           clib_warning ("can't allocate buffer for NAT IPFIX event");
1198           return;
1199         }
1200
1201       b0 = silm->max_frags_ip6_buffer = vlib_get_buffer (vm, bi0);
1202       fl =
1203         vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
1204       vlib_buffer_init_for_free_list (b0, fl);
1205       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1206       offset = 0;
1207     }
1208   else
1209     {
1210       bi0 = vlib_get_buffer_index (vm, b0);
1211       offset = silm->max_frags_ip6_next_record_offset;
1212     }
1213
1214   f = silm->max_frags_ip6_frame;
1215   if (PREDICT_FALSE (f == 0))
1216     {
1217       u32 *to_next;
1218       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1219       silm->max_frags_ip6_frame = f;
1220       to_next = vlib_frame_vector_args (f);
1221       to_next[0] = bi0;
1222       f->n_vectors = 1;
1223     }
1224
1225   if (PREDICT_FALSE (offset == 0))
1226     snat_ipfix_header_create (frm, b0, &offset);
1227
1228   if (PREDICT_TRUE (do_flush == 0))
1229     {
1230       u64 time_stamp = clib_host_to_net_u64 (now);
1231       clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
1232       offset += sizeof (time_stamp);
1233
1234       clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
1235       offset += sizeof (nat_event);
1236
1237       clib_memcpy (b0->data + offset, &quota_event, sizeof (quota_event));
1238       offset += sizeof (quota_event);
1239
1240       clib_memcpy (b0->data + offset, &limit, sizeof (limit));
1241       offset += sizeof (limit);
1242
1243       clib_memcpy (b0->data + offset, src, sizeof (ip6_address_t));
1244       offset += sizeof (ip6_address_t);
1245
1246       b0->current_length += MAX_FRAGMENTS_IP6_LEN;
1247     }
1248
1249   if (PREDICT_FALSE
1250       (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1251     {
1252       snat_ipfix_send (frm, f, b0, silm->max_frags_ip6_template_id);
1253       silm->max_frags_ip6_frame = 0;
1254       silm->max_frags_ip6_buffer = 0;
1255       offset = 0;
1256     }
1257   silm->max_frags_ip6_next_record_offset = offset;
1258 }
1259
1260 static void
1261 nat_ipfix_logging_nat64_bibe (u8 nat_event, ip6_address_t * src_ip,
1262                               u32 nat_src_ip, u8 proto, u16 src_port,
1263                               u16 nat_src_port, u32 vrf_id, int do_flush)
1264 {
1265   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1266   flow_report_main_t *frm = &flow_report_main;
1267   vlib_frame_t *f;
1268   vlib_buffer_t *b0 = 0;
1269   u32 bi0 = ~0;
1270   u32 offset;
1271   vlib_main_t *vm = frm->vlib_main;
1272   u64 now;
1273   vlib_buffer_free_list_t *fl;
1274
1275   if (!silm->enabled)
1276     return;
1277
1278   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1279   now += silm->milisecond_time_0;
1280
1281   b0 = silm->nat64_bib_buffer;
1282
1283   if (PREDICT_FALSE (b0 == 0))
1284     {
1285       if (do_flush)
1286         return;
1287
1288       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1289         {
1290           clib_warning ("can't allocate buffer for NAT IPFIX event");
1291           return;
1292         }
1293
1294       b0 = silm->nat64_bib_buffer = vlib_get_buffer (vm, bi0);
1295       fl =
1296         vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
1297       vlib_buffer_init_for_free_list (b0, fl);
1298       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1299       offset = 0;
1300     }
1301   else
1302     {
1303       bi0 = vlib_get_buffer_index (vm, b0);
1304       offset = silm->nat64_bib_next_record_offset;
1305     }
1306
1307   f = silm->nat64_bib_frame;
1308   if (PREDICT_FALSE (f == 0))
1309     {
1310       u32 *to_next;
1311       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1312       silm->nat64_bib_frame = f;
1313       to_next = vlib_frame_vector_args (f);
1314       to_next[0] = bi0;
1315       f->n_vectors = 1;
1316     }
1317
1318   if (PREDICT_FALSE (offset == 0))
1319     snat_ipfix_header_create (frm, b0, &offset);
1320
1321   if (PREDICT_TRUE (do_flush == 0))
1322     {
1323       u64 time_stamp = clib_host_to_net_u64 (now);
1324       clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
1325       offset += sizeof (time_stamp);
1326
1327       clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
1328       offset += sizeof (nat_event);
1329
1330       clib_memcpy (b0->data + offset, src_ip, sizeof (ip6_address_t));
1331       offset += sizeof (ip6_address_t);
1332
1333       clib_memcpy (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1334       offset += sizeof (nat_src_ip);
1335
1336       clib_memcpy (b0->data + offset, &proto, sizeof (proto));
1337       offset += sizeof (proto);
1338
1339       clib_memcpy (b0->data + offset, &src_port, sizeof (src_port));
1340       offset += sizeof (src_port);
1341
1342       clib_memcpy (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1343       offset += sizeof (nat_src_port);
1344
1345       clib_memcpy (b0->data + offset, &vrf_id, sizeof (vrf_id));
1346       offset += sizeof (vrf_id);
1347
1348       b0->current_length += NAT64_BIB_LEN;
1349     }
1350
1351   if (PREDICT_FALSE
1352       (do_flush || (offset + NAT64_BIB_LEN) > frm->path_mtu))
1353     {
1354       snat_ipfix_send (frm, f, b0, silm->nat64_bib_template_id);
1355       silm->nat64_bib_frame = 0;
1356       silm->nat64_bib_buffer = 0;
1357       offset = 0;
1358     }
1359   silm->nat64_bib_next_record_offset = offset;
1360 }
1361
1362 static void
1363 nat_ipfix_logging_nat64_ses (u8 nat_event, ip6_address_t * src_ip,
1364                              u32 nat_src_ip, u8 proto, u16 src_port,
1365                              u16 nat_src_port, ip6_address_t * dst_ip,
1366                              u32 nat_dst_ip, u16 dst_port, u16 nat_dst_port,
1367                              u32 vrf_id, int do_flush)
1368 {
1369   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1370   flow_report_main_t *frm = &flow_report_main;
1371   vlib_frame_t *f;
1372   vlib_buffer_t *b0 = 0;
1373   u32 bi0 = ~0;
1374   u32 offset;
1375   vlib_main_t *vm = frm->vlib_main;
1376   u64 now;
1377   vlib_buffer_free_list_t *fl;
1378
1379   if (!silm->enabled)
1380     return;
1381
1382   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1383   now += silm->milisecond_time_0;
1384
1385   b0 = silm->nat64_ses_buffer;
1386
1387   if (PREDICT_FALSE (b0 == 0))
1388     {
1389       if (do_flush)
1390         return;
1391
1392       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1393         {
1394           clib_warning ("can't allocate buffer for NAT IPFIX event");
1395           return;
1396         }
1397
1398       b0 = silm->nat64_ses_buffer = vlib_get_buffer (vm, bi0);
1399       fl =
1400         vlib_buffer_get_free_list (vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
1401       vlib_buffer_init_for_free_list (b0, fl);
1402       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1403       offset = 0;
1404     }
1405   else
1406     {
1407       bi0 = vlib_get_buffer_index (vm, b0);
1408       offset = silm->nat64_ses_next_record_offset;
1409     }
1410
1411   f = silm->nat64_ses_frame;
1412   if (PREDICT_FALSE (f == 0))
1413     {
1414       u32 *to_next;
1415       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1416       silm->nat64_ses_frame = f;
1417       to_next = vlib_frame_vector_args (f);
1418       to_next[0] = bi0;
1419       f->n_vectors = 1;
1420     }
1421
1422   if (PREDICT_FALSE (offset == 0))
1423     snat_ipfix_header_create (frm, b0, &offset);
1424
1425   if (PREDICT_TRUE (do_flush == 0))
1426     {
1427       u64 time_stamp = clib_host_to_net_u64 (now);
1428       clib_memcpy (b0->data + offset, &time_stamp, sizeof (time_stamp));
1429       offset += sizeof (time_stamp);
1430
1431       clib_memcpy (b0->data + offset, &nat_event, sizeof (nat_event));
1432       offset += sizeof (nat_event);
1433
1434       clib_memcpy (b0->data + offset, src_ip, sizeof (ip6_address_t));
1435       offset += sizeof (ip6_address_t);
1436
1437       clib_memcpy (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1438       offset += sizeof (nat_src_ip);
1439
1440       clib_memcpy (b0->data + offset, &proto, sizeof (proto));
1441       offset += sizeof (proto);
1442
1443       clib_memcpy (b0->data + offset, &src_port, sizeof (src_port));
1444       offset += sizeof (src_port);
1445
1446       clib_memcpy (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1447       offset += sizeof (nat_src_port);
1448
1449       clib_memcpy (b0->data + offset, dst_ip, sizeof (ip6_address_t));
1450       offset += sizeof (ip6_address_t);
1451
1452       clib_memcpy (b0->data + offset, &nat_dst_ip, sizeof (nat_dst_ip));
1453       offset += sizeof (nat_dst_ip);
1454
1455       clib_memcpy (b0->data + offset, &dst_port, sizeof (dst_port));
1456       offset += sizeof (dst_port);
1457
1458       clib_memcpy (b0->data + offset, &nat_dst_port, sizeof (nat_dst_port));
1459       offset += sizeof (nat_dst_port);
1460
1461       clib_memcpy (b0->data + offset, &vrf_id, sizeof (vrf_id));
1462       offset += sizeof (vrf_id);
1463
1464       b0->current_length += NAT64_SES_LEN;
1465     }
1466
1467   if (PREDICT_FALSE
1468       (do_flush || (offset + NAT64_SES_LEN) > frm->path_mtu))
1469     {
1470       snat_ipfix_send (frm, f, b0, silm->nat64_ses_template_id);
1471       silm->nat64_ses_frame = 0;
1472       silm->nat64_ses_buffer = 0;
1473       offset = 0;
1474     }
1475   silm->nat64_ses_next_record_offset = offset;
1476 }
1477
1478 static void
1479 snat_ipfix_logging_nat44_ses_rpc_cb (snat_ipfix_logging_nat44_ses_args_t * a)
1480 {
1481   snat_ipfix_logging_nat44_ses (a->nat_event, a->src_ip, a->nat_src_ip,
1482                                 a->snat_proto, a->src_port, a->nat_src_port,
1483                                 a->vrf_id, 0);
1484 }
1485
1486 /**
1487  * @brief Generate NAT44 session create event
1488  *
1489  * @param src_ip       source IPv4 address
1490  * @param nat_src_ip   transaltes source IPv4 address
1491  * @param snat_proto   NAT transport protocol
1492  * @param src_port     source port
1493  * @param nat_src_port translated source port
1494  * @param vrf_id       VRF ID
1495  */
1496 void
1497 snat_ipfix_logging_nat44_ses_create (u32 src_ip,
1498                                      u32 nat_src_ip,
1499                                      snat_protocol_t snat_proto,
1500                                      u16 src_port,
1501                                      u16 nat_src_port, u32 vrf_id)
1502 {
1503   snat_ipfix_logging_nat44_ses_args_t a;
1504
1505   skip_if_disabled ();
1506
1507   a.nat_event = NAT44_SESSION_CREATE;
1508   a.src_ip = src_ip;
1509   a.nat_src_ip = nat_src_ip;
1510   a.snat_proto = snat_proto;
1511   a.src_port = src_port;
1512   a.nat_src_port = nat_src_port;
1513   a.vrf_id = vrf_id;
1514
1515   vl_api_rpc_call_main_thread (snat_ipfix_logging_nat44_ses_rpc_cb,
1516                                (u8 *) & a, sizeof (a));
1517 }
1518
1519 /**
1520  * @brief Generate NAT44 session delete event
1521  *
1522  * @param src_ip       source IPv4 address
1523  * @param nat_src_ip   transaltes source IPv4 address
1524  * @param snat_proto   NAT transport protocol
1525  * @param src_port     source port
1526  * @param nat_src_port translated source port
1527  * @param vrf_id       VRF ID
1528  */
1529 void
1530 snat_ipfix_logging_nat44_ses_delete (u32 src_ip,
1531                                      u32 nat_src_ip,
1532                                      snat_protocol_t snat_proto,
1533                                      u16 src_port,
1534                                      u16 nat_src_port, u32 vrf_id)
1535 {
1536   snat_ipfix_logging_nat44_ses_args_t a;
1537
1538   skip_if_disabled ();
1539
1540   a.nat_event = NAT44_SESSION_DELETE;
1541   a.src_ip = src_ip;
1542   a.nat_src_ip = nat_src_ip;
1543   a.snat_proto = snat_proto;
1544   a.src_port = src_port;
1545   a.nat_src_port = nat_src_port;
1546   a.vrf_id = vrf_id;
1547
1548   vl_api_rpc_call_main_thread (snat_ipfix_logging_nat44_ses_rpc_cb,
1549                                (u8 *) & a, sizeof (a));
1550 }
1551
1552 vlib_frame_t *
1553 snat_data_callback_nat44_session (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_nat44_ses (0, 0, 0, 0, 0, 0, 0, 1);
1559   return f;
1560 }
1561
1562 static void
1563   snat_ipfix_logging_addr_exhausted_rpc_cb
1564   (snat_ipfix_logging_addr_exhausted_args_t * a)
1565 {
1566   snat_ipfix_logging_addr_exhausted (a->pool_id, 0);
1567 }
1568
1569 /**
1570  * @brief Generate NAT addresses exhausted event
1571  *
1572  * @param pool_id NAT pool ID
1573  */
1574 void
1575 snat_ipfix_logging_addresses_exhausted (u32 pool_id)
1576 {
1577   //TODO: This event SHOULD be rate limited
1578   snat_ipfix_logging_addr_exhausted_args_t a;
1579
1580   skip_if_disabled ();
1581
1582   a.pool_id = pool_id;
1583
1584   vl_api_rpc_call_main_thread (snat_ipfix_logging_addr_exhausted_rpc_cb,
1585                                (u8 *) & a, sizeof (a));
1586 }
1587
1588 vlib_frame_t *
1589 snat_data_callback_addr_exhausted (flow_report_main_t * frm,
1590                                    flow_report_t * fr,
1591                                    vlib_frame_t * f,
1592                                    u32 * to_next, u32 node_index)
1593 {
1594   snat_ipfix_logging_addr_exhausted (0, 1);
1595   return f;
1596 }
1597
1598 static void
1599   snat_ipfix_logging_max_entries_per_usr_rpc_cb
1600   (snat_ipfix_logging_max_entries_per_user_args_t * a)
1601 {
1602   snat_ipfix_logging_max_entries_per_usr (a->limit, a->src_ip, 0);
1603 }
1604
1605 /**
1606  * @brief Generate maximum entries per user exceeded event
1607  *
1608  * @param limit maximum NAT entries that can be created per user
1609  * @param src_ip source IPv4 address
1610  */
1611 void
1612 snat_ipfix_logging_max_entries_per_user (u32 limit, u32 src_ip)
1613 {
1614   //TODO: This event SHOULD be rate limited
1615   snat_ipfix_logging_max_entries_per_user_args_t a;
1616
1617   skip_if_disabled ();
1618
1619   a.limit = limit;
1620   a.src_ip = src_ip;
1621
1622   vl_api_rpc_call_main_thread (snat_ipfix_logging_max_entries_per_usr_rpc_cb,
1623                                (u8 *) & a, sizeof (a));
1624 }
1625
1626 vlib_frame_t *
1627 snat_data_callback_max_entries_per_usr (flow_report_main_t * frm,
1628                                         flow_report_t * fr,
1629                                         vlib_frame_t * f,
1630                                         u32 * to_next, u32 node_index)
1631 {
1632   snat_ipfix_logging_max_entries_per_usr (0, 0, 1);
1633   return f;
1634 }
1635
1636 static void
1637 nat_ipfix_logging_max_ses_rpc_cb (nat_ipfix_logging_max_sessions_args_t * a)
1638 {
1639   nat_ipfix_logging_max_ses (a->limit, 0);
1640 }
1641
1642 /**
1643  * @brief Generate maximum session entries exceeded event
1644  *
1645  * @param limit configured limit
1646  */
1647 void
1648 nat_ipfix_logging_max_sessions (u32 limit)
1649 {
1650   //TODO: This event SHOULD be rate limited
1651   nat_ipfix_logging_max_sessions_args_t a;
1652
1653   skip_if_disabled ();
1654
1655   a.limit = limit;
1656
1657   vl_api_rpc_call_main_thread (nat_ipfix_logging_max_ses_rpc_cb,
1658                                (u8 *) & a, sizeof (a));
1659 }
1660
1661 vlib_frame_t *
1662 nat_data_callback_max_sessions (flow_report_main_t * frm,
1663                                 flow_report_t * fr,
1664                                 vlib_frame_t * f,
1665                                 u32 * to_next, u32 node_index)
1666 {
1667   nat_ipfix_logging_max_ses (0, 1);
1668   return f;
1669 }
1670
1671 static void
1672 nat_ipfix_logging_max_bib_rpc_cb (nat_ipfix_logging_max_bibs_args_t * a)
1673 {
1674   nat_ipfix_logging_max_bib (a->limit, 0);
1675 }
1676
1677 /**
1678  * @brief Generate maximum BIB entries exceeded event
1679  *
1680  * @param limit configured limit
1681  */
1682 void
1683 nat_ipfix_logging_max_bibs (u32 limit)
1684 {
1685   //TODO: This event SHOULD be rate limited
1686   nat_ipfix_logging_max_bibs_args_t a;
1687
1688   skip_if_disabled ();
1689
1690   a.limit = limit;
1691
1692   vl_api_rpc_call_main_thread (nat_ipfix_logging_max_bib_rpc_cb,
1693                                (u8 *) & a, sizeof (a));
1694 }
1695
1696 vlib_frame_t *
1697 nat_data_callback_max_bibs (flow_report_main_t * frm,
1698                             flow_report_t * fr,
1699                             vlib_frame_t * f,
1700                             u32 * to_next, u32 node_index)
1701 {
1702   nat_ipfix_logging_max_bib (0, 1);
1703   return f;
1704 }
1705
1706 static void
1707 nat_ipfix_logging_max_frag_ip4_rpc_cb (nat_ipfix_logging_max_frags_ip4_args_t * a)
1708 {
1709   nat_ipfix_logging_max_frag_ip4 (a->limit, a->src, 0);
1710 }
1711
1712 /**
1713  * @brief Generate maximum IPv4 fragments pending reassembly exceeded event
1714  *
1715  * @param limit configured limit
1716  * @param src source IPv4 address
1717  */
1718 void
1719 nat_ipfix_logging_max_fragments_ip4 (u32 limit, ip4_address_t * src)
1720 {
1721   //TODO: This event SHOULD be rate limited
1722   nat_ipfix_logging_max_frags_ip4_args_t a;
1723
1724   skip_if_disabled ();
1725
1726   a.limit = limit;
1727   a.src = src->as_u32;
1728
1729   vl_api_rpc_call_main_thread (nat_ipfix_logging_max_frag_ip4_rpc_cb,
1730                                (u8 *) & a, sizeof (a));
1731 }
1732
1733 vlib_frame_t *
1734 nat_data_callback_max_frags_ip4 (flow_report_main_t * frm,
1735                                  flow_report_t * fr,
1736                                  vlib_frame_t * f,
1737                                  u32 * to_next, u32 node_index)
1738 {
1739   nat_ipfix_logging_max_frag_ip4 (0, 0, 1);
1740   return f;
1741 }
1742
1743 static void
1744 nat_ipfix_logging_max_frag_ip6_rpc_cb (nat_ipfix_logging_max_frags_ip6_args_t * a)
1745 {
1746   ip6_address_t src;
1747   src.as_u64[0] = a->src[0];
1748   src.as_u64[1] = a->src[1];
1749   nat_ipfix_logging_max_frag_ip6 (a->limit, &src, 0);
1750 }
1751
1752 /**
1753  * @brief Generate maximum IPv6 fragments pending reassembly exceeded event
1754  *
1755  * @param limit configured limit
1756  * @param src source IPv6 address
1757  */
1758 void
1759 nat_ipfix_logging_max_fragments_ip6 (u32 limit, ip6_address_t * src)
1760 {
1761   //TODO: This event SHOULD be rate limited
1762   nat_ipfix_logging_max_frags_ip6_args_t a;
1763
1764   skip_if_disabled ();
1765
1766   a.limit = limit;
1767   a.src[0] = src->as_u64[0];
1768   a.src[1] = src->as_u64[1];
1769
1770   vl_api_rpc_call_main_thread (nat_ipfix_logging_max_frag_ip6_rpc_cb,
1771                                (u8 *) & a, sizeof (a));
1772 }
1773
1774 vlib_frame_t *
1775 nat_data_callback_max_frags_ip6 (flow_report_main_t * frm,
1776                                  flow_report_t * fr,
1777                                  vlib_frame_t * f,
1778                                  u32 * to_next, u32 node_index)
1779 {
1780   nat_ipfix_logging_max_frag_ip6 (0, 0, 1);
1781   return f;
1782 }
1783
1784 static void
1785 nat_ipfix_logging_nat64_bib_rpc_cb (nat_ipfix_logging_nat64_bib_args_t * a)
1786 {
1787   ip6_address_t src_ip;
1788   src_ip.as_u64[0] = a->src_ip[0];
1789   src_ip.as_u64[1] = a->src_ip[1];
1790   nat_ipfix_logging_nat64_bibe (a->nat_event, &src_ip, a->nat_src_ip,
1791                                 a->proto, a->src_port, a->nat_src_port,
1792                                 a->vrf_id, 0);
1793 }
1794
1795 /**
1796  * @brief Generate NAT64 BIB create and delete events
1797  *
1798  * @param src_ip       source IPv6 address
1799  * @param nat_src_ip   transaltes source IPv4 address
1800  * @param proto        L4 protocol
1801  * @param src_port     source port
1802  * @param nat_src_port translated source port
1803  * @param vrf_id       VRF ID
1804  * @param is_create    non-zero value if create event otherwise delete event
1805  */
1806 void
1807 nat_ipfix_logging_nat64_bib (ip6_address_t * src_ip,
1808                              ip4_address_t * nat_src_ip, u8 proto,
1809                              u16 src_port, u16 nat_src_port, u32 vrf_id,
1810                              u8 is_create)
1811 {
1812   nat_ipfix_logging_nat64_bib_args_t a;
1813
1814   skip_if_disabled ();
1815
1816   a.src_ip[0] = src_ip->as_u64[0];
1817   a.src_ip[1] = src_ip->as_u64[1];
1818   a.nat_src_ip = nat_src_ip->as_u32;
1819   a.proto = proto;
1820   a.src_port = src_port;
1821   a.nat_src_port = nat_src_port;
1822   a.vrf_id = vrf_id;
1823   a.nat_event = is_create ? NAT64_BIB_CREATE : NAT64_BIB_DELETE;
1824
1825   vl_api_rpc_call_main_thread (nat_ipfix_logging_nat64_bib_rpc_cb,
1826                                (u8 *) & a, sizeof (a));
1827 }
1828
1829 vlib_frame_t *
1830 nat_data_callback_nat64_bib (flow_report_main_t * frm,
1831                              flow_report_t * fr,
1832                              vlib_frame_t * f,
1833                              u32 * to_next, u32 node_index)
1834 {
1835   nat_ipfix_logging_nat64_bibe (0, 0, 0, 0, 0, 0, 0, 1);
1836   return f;
1837 }
1838
1839 static void
1840 nat_ipfix_logging_nat64_ses_rpc_cb (nat_ipfix_logging_nat64_ses_args_t * a)
1841 {
1842   ip6_address_t src_ip, dst_ip;
1843   src_ip.as_u64[0] = a->src_ip[0];
1844   src_ip.as_u64[1] = a->src_ip[1];
1845   dst_ip.as_u64[0] = a->dst_ip[0];
1846   dst_ip.as_u64[1] = a->dst_ip[1];
1847   nat_ipfix_logging_nat64_ses (a->nat_event, &src_ip, a->nat_src_ip,
1848                                a->proto, a->src_port, a->nat_src_port,
1849                                &dst_ip, a->nat_dst_ip, a->dst_port,
1850                                a->nat_dst_port, a->vrf_id, 0);
1851 }
1852
1853 /**
1854  * @brief Generate NAT64 session create and delete events
1855  *
1856  * @param src_ip       source IPv6 address
1857  * @param nat_src_ip   transaltes source IPv4 address
1858  * @param proto        L4 protocol
1859  * @param src_port     source port
1860  * @param nat_src_port translated source port
1861  * @param dst_ip       destination IPv6 address
1862  * @param nat_dst_ip   destination IPv4 address
1863  * @param dst_port     destination port
1864  * @param nat_dst_port translated destination port
1865  * @param vrf_id       VRF ID
1866  * @param is_create    non-zero value if create event otherwise delete event
1867  */
1868 void
1869 nat_ipfix_logging_nat64_session (ip6_address_t * src_ip,
1870                                  ip4_address_t * nat_src_ip, u8 proto,
1871                                  u16 src_port, u16 nat_src_port,
1872                                  ip6_address_t * dst_ip,
1873                                  ip4_address_t * nat_dst_ip, u16 dst_port,
1874                                  u16 nat_dst_port, u32 vrf_id, u8 is_create)
1875 {
1876   nat_ipfix_logging_nat64_ses_args_t a;
1877
1878   skip_if_disabled ();
1879
1880   a.src_ip[0] = src_ip->as_u64[0];
1881   a.src_ip[1] = src_ip->as_u64[1];
1882   a.nat_src_ip = nat_src_ip->as_u32;
1883   a.proto = proto;
1884   a.src_port = src_port;
1885   a.nat_src_port = nat_src_port;
1886   a.dst_ip[0] = dst_ip->as_u64[0];
1887   a.dst_ip[1] = dst_ip->as_u64[1];
1888   a.nat_dst_ip = nat_dst_ip->as_u32;
1889   a.dst_port = dst_port;
1890   a.nat_dst_port = nat_dst_port;
1891   a.vrf_id = vrf_id;
1892   a.nat_event = is_create ? NAT64_SESSION_CREATE : NAT64_SESSION_DELETE;
1893
1894   vl_api_rpc_call_main_thread (nat_ipfix_logging_nat64_ses_rpc_cb,
1895                                (u8 *) & a, sizeof (a));
1896 }
1897
1898 vlib_frame_t *
1899 nat_data_callback_nat64_session (flow_report_main_t * frm,
1900                                  flow_report_t * fr,
1901                                  vlib_frame_t * f,
1902                                  u32 * to_next, u32 node_index)
1903 {
1904   nat_ipfix_logging_nat64_ses (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
1905   return f;
1906 }
1907
1908 /**
1909  * @brief Enable/disable NAT plugin IPFIX logging
1910  *
1911  * @param enable    1 if enable, 0 if disable
1912  * @param domain_id observation domain ID
1913  * @param src_port  source port number
1914  *
1915  * @returns 0 if success
1916  */
1917 int
1918 snat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
1919 {
1920   snat_main_t *sm = &snat_main;
1921   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
1922   flow_report_main_t *frm = &flow_report_main;
1923   vnet_flow_report_add_del_args_t a;
1924   int rv;
1925   u8 e = enable ? 1 : 0;
1926
1927   if (silm->enabled == e)
1928     return 0;
1929
1930   silm->enabled = e;
1931
1932   memset (&a, 0, sizeof (a));
1933   a.is_add = enable;
1934   a.domain_id = domain_id ? domain_id : 1;
1935   a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
1936
1937   if (sm->deterministic)
1938     {
1939       a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
1940       a.flow_data_callback = snat_data_callback_max_entries_per_usr;
1941
1942       rv = vnet_flow_report_add_del (frm, &a, NULL);
1943       if (rv)
1944         {
1945           clib_warning ("vnet_flow_report_add_del returned %d", rv);
1946           return -1;
1947         }
1948     }
1949   else
1950     {
1951       a.rewrite_callback = snat_template_rewrite_nat44_session;
1952       a.flow_data_callback = snat_data_callback_nat44_session;
1953
1954       rv = vnet_flow_report_add_del (frm, &a, NULL);
1955       if (rv)
1956         {
1957           clib_warning ("vnet_flow_report_add_del returned %d", rv);
1958           return -1;
1959         }
1960
1961       a.rewrite_callback = snat_template_rewrite_addr_exhausted;
1962       a.flow_data_callback = snat_data_callback_addr_exhausted;
1963
1964       rv = vnet_flow_report_add_del (frm, &a, NULL);
1965       if (rv)
1966         {
1967           clib_warning ("vnet_flow_report_add_del returned %d", rv);
1968           return -1;
1969         }
1970
1971       a.rewrite_callback = nat_template_rewrite_max_sessions;
1972       a.flow_data_callback = nat_data_callback_max_sessions;
1973
1974       rv = vnet_flow_report_add_del (frm, &a, NULL);
1975       if (rv)
1976         {
1977           clib_warning ("vnet_flow_report_add_del returned %d", rv);
1978           return -1;
1979         }
1980
1981       a.rewrite_callback = nat_template_rewrite_max_bibs;
1982       a.flow_data_callback = nat_data_callback_max_bibs;
1983
1984       rv = vnet_flow_report_add_del (frm, &a, NULL);
1985       if (rv)
1986         {
1987           clib_warning ("vnet_flow_report_add_del returned %d", rv);
1988           return -1;
1989         }
1990
1991       a.rewrite_callback = nat_template_rewrite_max_frags_ip4;
1992       a.flow_data_callback = nat_data_callback_max_frags_ip4;
1993
1994       rv = vnet_flow_report_add_del (frm, &a, NULL);
1995       if (rv)
1996         {
1997           clib_warning ("vnet_flow_report_add_del returned %d", rv);
1998           return -1;
1999         }
2000
2001       a.rewrite_callback = nat_template_rewrite_max_frags_ip6;
2002       a.flow_data_callback = nat_data_callback_max_frags_ip6;
2003
2004       rv = vnet_flow_report_add_del (frm, &a, NULL);
2005       if (rv)
2006         {
2007           clib_warning ("vnet_flow_report_add_del returned %d", rv);
2008           return -1;
2009         }
2010
2011       a.rewrite_callback = nat_template_rewrite_nat64_bib;
2012       a.flow_data_callback = nat_data_callback_nat64_bib;
2013
2014       rv = vnet_flow_report_add_del (frm, &a, NULL);
2015       if (rv)
2016         {
2017           clib_warning ("vnet_flow_report_add_del returned %d", rv);
2018           return -1;
2019         }
2020
2021       a.rewrite_callback = nat_template_rewrite_nat64_session;
2022       a.flow_data_callback = nat_data_callback_nat64_session;
2023
2024       rv = vnet_flow_report_add_del (frm, &a, NULL);
2025       if (rv)
2026         {
2027           clib_warning ("vnet_flow_report_add_del returned %d", rv);
2028           return -1;
2029         }
2030
2031       if (sm->endpoint_dependent)
2032         {
2033           a.rewrite_callback = snat_template_rewrite_max_entries_per_usr;
2034           a.flow_data_callback = snat_data_callback_max_entries_per_usr;
2035
2036           rv = vnet_flow_report_add_del (frm, &a, NULL);
2037           if (rv)
2038             {
2039               clib_warning ("vnet_flow_report_add_del returned %d", rv);
2040               return -1;
2041             }
2042         }
2043     }
2044
2045   return 0;
2046 }
2047
2048 /**
2049  * @brief Initialize NAT plugin IPFIX logging
2050  *
2051  * @param vm vlib main
2052  */
2053 void
2054 snat_ipfix_logging_init (vlib_main_t * vm)
2055 {
2056   snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main;
2057
2058   silm->enabled = 0;
2059
2060   /* Set up time reference pair */
2061   silm->vlib_time_0 = vlib_time_now (vm);
2062   silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
2063 }