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