LCOV - code coverage report
Current view: top level - plugins/nat/lib - ipfix_logging.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 594 712 83.4 %
Date: 2023-07-05 22:20:52 Functions: 30 35 85.7 %

          Line data    Source code
       1             : /*
       2             :  * nat_ipfix_logging.c - NAT Events IPFIX logging
       3             :  *
       4             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vnet/fib/fib_table.h>
      19             : #include <vnet/ipfix-export/flow_report.h>
      20             : #include <vnet/ip/ip4.h>
      21             : #include <vnet/udp/udp_local.h>
      22             : #include <vlibmemory/api.h>
      23             : #include <vppinfra/atomics.h>
      24             : #include <nat/lib/ipfix_logging.h>
      25             : #include <nat/lib/inlines.h>
      26             : 
      27             : vlib_node_registration_t nat_ipfix_flush_node;
      28             : nat_ipfix_logging_main_t nat_ipfix_logging_main;
      29             : 
      30             : #define NAT44_SESSION_CREATE_LEN 26
      31             : #define NAT_ADDRESSES_EXHAUTED_LEN 13
      32             : #define MAX_ENTRIES_PER_USER_LEN 21
      33             : #define MAX_SESSIONS_LEN 17
      34             : #define MAX_BIBS_LEN 17
      35             : #define MAX_FRAGMENTS_IP4_LEN 21
      36             : #define MAX_FRAGMENTS_IP6_LEN 33
      37             : #define NAT64_BIB_LEN 38
      38             : #define NAT64_SES_LEN 62
      39             : 
      40             : #define NAT44_SESSION_CREATE_FIELD_COUNT 8
      41             : #define NAT_ADDRESSES_EXHAUTED_FIELD_COUNT 3
      42             : #define MAX_ENTRIES_PER_USER_FIELD_COUNT 5
      43             : #define MAX_SESSIONS_FIELD_COUNT 4
      44             : #define MAX_BIBS_FIELD_COUNT 4
      45             : #define MAX_FRAGMENTS_FIELD_COUNT 5
      46             : #define NAT64_BIB_FIELD_COUNT 8
      47             : #define NAT64_SES_FIELD_COUNT 12
      48             : 
      49             : typedef struct
      50             : {
      51             :   u8 nat_event;
      52             :   u32 src_ip;
      53             :   u32 nat_src_ip;
      54             :   ip_protocol_t proto;
      55             :   u16 src_port;
      56             :   u16 nat_src_port;
      57             :   u32 vrf_id;
      58             : } nat_ipfix_logging_nat44_ses_args_t;
      59             : 
      60             : typedef struct
      61             : {
      62             :   u32 pool_id;
      63             : } nat_ipfix_logging_addr_exhausted_args_t;
      64             : 
      65             : typedef struct
      66             : {
      67             :   u32 limit;
      68             :   u32 src_ip;
      69             : } nat_ipfix_logging_max_entries_per_user_args_t;
      70             : 
      71             : typedef struct
      72             : {
      73             :   u32 limit;
      74             : } nat_ipfix_logging_max_sessions_args_t;
      75             : 
      76             : typedef struct
      77             : {
      78             :   u32 limit;
      79             : } nat_ipfix_logging_max_bibs_args_t;
      80             : 
      81             : typedef struct
      82             : {
      83             :   u32 limit;
      84             :   u32 src;
      85             : } nat_ipfix_logging_max_frags_ip4_args_t;
      86             : 
      87             : typedef struct
      88             : {
      89             :   u32 limit;
      90             :   u64 src[2];
      91             : } nat_ipfix_logging_max_frags_ip6_args_t;
      92             : 
      93             : typedef struct
      94             : {
      95             :   u8 nat_event;
      96             :   u64 src_ip[2];
      97             :   u32 nat_src_ip;
      98             :   u8 proto;
      99             :   u16 src_port;
     100             :   u16 nat_src_port;
     101             :   u64 dst_ip[2];
     102             :   u32 nat_dst_ip;
     103             :   u32 vrf_id;
     104             :   u16 dst_port;
     105             :   u16 nat_dst_port;
     106             : } nat_ipfix_logging_nat64_ses_args_t;
     107             : 
     108             : typedef struct
     109             : {
     110             :   u8 nat_event;
     111             :   u64 src_ip[2];
     112             :   u32 nat_src_ip;
     113             :   u8 proto;
     114             :   u16 src_port;
     115             :   u16 nat_src_port;
     116             :   u32 vrf_id;
     117             : } nat_ipfix_logging_nat64_bib_args_t;
     118             : 
     119             : #define skip_if_disabled()                                        \
     120             : do {                                                              \
     121             :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;     \
     122             :   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))    \
     123             :     return;                                                       \
     124             : } while (0)
     125             : 
     126             : #define update_template_id(old_id, new_id)                \
     127             : do {                                                      \
     128             :   u16 template_id = clib_atomic_fetch_or(old_id, 0);      \
     129             :   clib_atomic_cmp_and_swap(old_id, template_id, new_id);  \
     130             : } while (0)
     131             : 
     132             : /**
     133             :  * @brief Create an IPFIX template packet rewrite string
     134             :  *
     135             :  * @param frm               flow report main
     136             :  * @param fr                flow report
     137             :  * @param collector_address collector address
     138             :  * @param src_address       source address
     139             :  * @param collector_port    collector
     140             :  * @param event             NAT event ID
     141             :  * @param quota_event       NAT quota exceeded event ID
     142             :  *
     143             :  * @returns template packet
     144             :  */
     145             : static inline u8 *
     146          24 : nat_template_rewrite (ipfix_exporter_t *exp, flow_report_t *fr,
     147             :                       u16 collector_port, nat_event_t event,
     148             :                       quota_exceed_event_t quota_event)
     149             : {
     150          24 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
     151             :   ip4_header_t *ip;
     152             :   udp_header_t *udp;
     153             :   ipfix_message_header_t *h;
     154             :   ipfix_set_header_t *s;
     155             :   ipfix_template_header_t *t;
     156             :   ipfix_field_specifier_t *f;
     157             :   ipfix_field_specifier_t *first_field;
     158          24 :   u8 *rewrite = 0;
     159             :   ip4_ipfix_template_packet_t *tp;
     160          24 :   u32 field_count = 0;
     161             :   flow_report_stream_t *stream;
     162             :   u32 stream_index;
     163             : 
     164          24 :   stream = &exp->streams[fr->stream_index];
     165             : 
     166          24 :   stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
     167          24 :   clib_atomic_cmp_and_swap (&silm->stream_index,
     168             :                             stream_index, fr->stream_index);
     169             : 
     170          24 :   if (event == NAT_ADDRESSES_EXHAUTED)
     171             :     {
     172           4 :       field_count = NAT_ADDRESSES_EXHAUTED_FIELD_COUNT;
     173             : 
     174           4 :       update_template_id(&silm->addr_exhausted_template_id,
     175             :                          fr->template_id);
     176             :     }
     177          20 :   else if (event == NAT44_SESSION_CREATE)
     178             :     {
     179           4 :       field_count = NAT44_SESSION_CREATE_FIELD_COUNT;
     180             : 
     181           4 :       update_template_id(&silm->nat44_session_template_id,
     182             :                          fr->template_id);
     183             :     }
     184          16 :   else if (event == NAT64_BIB_CREATE)
     185             :     {
     186           4 :       field_count = NAT64_BIB_FIELD_COUNT;
     187             : 
     188           4 :       update_template_id(&silm->nat64_bib_template_id,
     189             :                          fr->template_id);
     190             :     }
     191          12 :   else if (event == NAT64_SESSION_CREATE)
     192             :     {
     193           4 :       field_count = NAT64_SES_FIELD_COUNT;
     194             : 
     195           4 :       update_template_id(&silm->nat64_ses_template_id,
     196             :                          fr->template_id);
     197             :     }
     198           8 :   else if (event == QUOTA_EXCEEDED)
     199             :     {
     200           8 :       if (quota_event == MAX_ENTRIES_PER_USER)
     201             :         {
     202           0 :           field_count = MAX_ENTRIES_PER_USER_FIELD_COUNT;
     203             : 
     204           0 :           update_template_id(&silm->max_entries_per_user_template_id,
     205             :                              fr->template_id);
     206             : 
     207             :         }
     208           8 :       else if (quota_event == MAX_SESSION_ENTRIES)
     209             :         {
     210           4 :           field_count = MAX_SESSIONS_FIELD_COUNT;
     211             : 
     212           4 :           update_template_id(&silm->max_sessions_template_id,
     213             :                              fr->template_id);
     214             :         }
     215           4 :       else if (quota_event == MAX_BIB_ENTRIES)
     216             :         {
     217           4 :           field_count = MAX_BIBS_FIELD_COUNT;
     218             : 
     219           4 :           update_template_id(&silm->max_bibs_template_id,
     220             :                              fr->template_id);
     221             :         }
     222             :     }
     223             : 
     224             :   /* allocate rewrite space */
     225          24 :   vec_validate_aligned (rewrite,
     226             :                         sizeof (ip4_ipfix_template_packet_t)
     227             :                         + field_count * sizeof (ipfix_field_specifier_t) - 1,
     228             :                         CLIB_CACHE_LINE_BYTES);
     229             : 
     230          24 :   tp = (ip4_ipfix_template_packet_t *) rewrite;
     231          24 :   ip = (ip4_header_t *) & tp->ip4;
     232          24 :   udp = (udp_header_t *) (ip + 1);
     233          24 :   h = (ipfix_message_header_t *) (udp + 1);
     234          24 :   s = (ipfix_set_header_t *) (h + 1);
     235          24 :   t = (ipfix_template_header_t *) (s + 1);
     236          24 :   first_field = f = (ipfix_field_specifier_t *) (t + 1);
     237             : 
     238          24 :   ip->ip_version_and_header_length = 0x45;
     239          24 :   ip->ttl = 254;
     240          24 :   ip->protocol = IP_PROTOCOL_UDP;
     241          24 :   ip->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
     242          24 :   ip->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
     243          24 :   udp->src_port = clib_host_to_net_u16 (stream->src_port);
     244          24 :   udp->dst_port = clib_host_to_net_u16 (collector_port);
     245          24 :   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
     246             : 
     247             :   /* FIXUP: message header export_time */
     248          24 :   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
     249             : 
     250             :   /* Add TLVs to the template */
     251          24 :   if (event == NAT_ADDRESSES_EXHAUTED)
     252             :     {
     253           4 :       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
     254           4 :       f++;
     255           4 :       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
     256           4 :       f++;
     257           4 :       f->e_id_length = ipfix_e_id_length (0, natPoolId, 4);
     258           4 :       f++;
     259             :     }
     260          20 :   else if (event == NAT44_SESSION_CREATE)
     261             :     {
     262           4 :       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
     263           4 :       f++;
     264           4 :       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
     265           4 :       f++;
     266           4 :       f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
     267           4 :       f++;
     268           4 :       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
     269           4 :       f++;
     270           4 :       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
     271           4 :       f++;
     272           4 :       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
     273           4 :       f++;
     274           4 :       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
     275           4 :       f++;
     276           4 :       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
     277           4 :       f++;
     278             :     }
     279          16 :   else if (event == NAT64_BIB_CREATE)
     280             :     {
     281           4 :       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
     282           4 :       f++;
     283           4 :       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
     284           4 :       f++;
     285           4 :       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
     286           4 :       f++;
     287           4 :       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
     288           4 :       f++;
     289           4 :       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
     290           4 :       f++;
     291           4 :       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
     292           4 :       f++;
     293           4 :       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
     294           4 :       f++;
     295           4 :       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
     296           4 :       f++;
     297             :     }
     298          12 :   else if (event == NAT64_SESSION_CREATE)
     299             :     {
     300           4 :       f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
     301           4 :       f++;
     302           4 :       f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
     303           4 :       f++;
     304           4 :       f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
     305           4 :       f++;
     306           4 :       f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
     307           4 :       f++;
     308           4 :       f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
     309           4 :       f++;
     310           4 :       f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
     311           4 :       f++;
     312           4 :       f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
     313           4 :       f++;
     314           4 :       f->e_id_length = ipfix_e_id_length (0, destinationIPv6Address, 16);
     315           4 :       f++;
     316           4 :       f->e_id_length = ipfix_e_id_length (0, postNATDestinationIPv4Address, 4);
     317           4 :       f++;
     318           4 :       f->e_id_length = ipfix_e_id_length (0, destinationTransportPort, 2);
     319           4 :       f++;
     320           4 :       f->e_id_length = ipfix_e_id_length (0, postNAPTDestinationTransportPort,
     321             :                                           2);
     322           4 :       f++;
     323           4 :       f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
     324           4 :       f++;
     325             :     }
     326           8 :   else if (event == QUOTA_EXCEEDED)
     327             :     {
     328           8 :       if (quota_event == MAX_ENTRIES_PER_USER)
     329             :         {
     330           0 :           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
     331             :                                               8);
     332           0 :           f++;
     333           0 :           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
     334           0 :           f++;
     335           0 :           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
     336           0 :           f++;
     337           0 :           f->e_id_length = ipfix_e_id_length (0, maxEntriesPerUser, 4);
     338           0 :           f++;
     339           0 :           f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
     340           0 :           f++;
     341             :         }
     342           8 :       else if (quota_event == MAX_SESSION_ENTRIES)
     343             :         {
     344           4 :           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
     345             :                                               8);
     346           4 :           f++;
     347           4 :           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
     348           4 :           f++;
     349           4 :           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
     350           4 :           f++;
     351           4 :           f->e_id_length = ipfix_e_id_length (0, maxSessionEntries, 4);
     352           4 :           f++;
     353             :         }
     354           4 :       else if (quota_event == MAX_BIB_ENTRIES)
     355             :         {
     356           4 :           f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
     357             :                                               8);
     358           4 :           f++;
     359           4 :           f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
     360           4 :           f++;
     361           4 :           f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
     362           4 :           f++;
     363           4 :           f->e_id_length = ipfix_e_id_length (0, maxBIBEntries, 4);
     364           4 :           f++;
     365             :         }
     366             :     }
     367             : 
     368             :   /* Back to the template packet... */
     369          24 :   ip = (ip4_header_t *) & tp->ip4;
     370          24 :   udp = (udp_header_t *) (ip + 1);
     371             : 
     372          24 :   ASSERT (f - first_field);
     373             :   /* Field count in this template */
     374          24 :   t->id_count = ipfix_id_count (fr->template_id, f - first_field);
     375             : 
     376             :   /* set length in octets */
     377          24 :   s->set_id_length =
     378          24 :     ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
     379             : 
     380             :   /* message length in octets */
     381          24 :   h->version_length = version_length ((u8 *) f - (u8 *) h);
     382             : 
     383          24 :   ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
     384          24 :   ip->checksum = ip4_header_checksum (ip);
     385             : 
     386          24 :   return rewrite;
     387             : }
     388             : 
     389             : u8 *
     390           4 : nat_template_rewrite_addr_exhausted (ipfix_exporter_t *exp, flow_report_t *fr,
     391             :                                      u16 collector_port,
     392             :                                      ipfix_report_element_t *elts, u32 n_elts,
     393             :                                      u32 *stream_index)
     394             : {
     395           4 :   return nat_template_rewrite (exp, fr, collector_port, NAT_ADDRESSES_EXHAUTED,
     396             :                                0);
     397             : }
     398             : 
     399             : u8 *
     400           4 : nat_template_rewrite_nat44_session (ipfix_exporter_t *exp, flow_report_t *fr,
     401             :                                     u16 collector_port,
     402             :                                     ipfix_report_element_t *elts, u32 n_elts,
     403             :                                     u32 *stream_index)
     404             : {
     405           4 :   return nat_template_rewrite (exp, fr, collector_port, NAT44_SESSION_CREATE,
     406             :                                0);
     407             : }
     408             : 
     409             : u8 *
     410           0 : nat_template_rewrite_max_entries_per_usr (
     411             :   ipfix_exporter_t *exp, flow_report_t *fr, ip4_address_t *collector_address,
     412             :   ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts,
     413             :   u32 n_elts, u32 *stream_index)
     414             : {
     415           0 :   return nat_template_rewrite (exp, fr, collector_port, QUOTA_EXCEEDED,
     416             :                                MAX_ENTRIES_PER_USER);
     417             : }
     418             : 
     419             : u8 *
     420           4 : nat_template_rewrite_max_sessions (ipfix_exporter_t *exp, flow_report_t *fr,
     421             :                                    u16 collector_port,
     422             :                                    ipfix_report_element_t *elts, u32 n_elts,
     423             :                                    u32 *stream_index)
     424             : {
     425           4 :   return nat_template_rewrite (exp, fr, collector_port, QUOTA_EXCEEDED,
     426             :                                MAX_SESSION_ENTRIES);
     427             : }
     428             : 
     429             : u8 *
     430           4 : nat_template_rewrite_max_bibs (ipfix_exporter_t *exp, flow_report_t *fr,
     431             :                                u16 collector_port,
     432             :                                ipfix_report_element_t *elts, u32 n_elts,
     433             :                                u32 *stream_index)
     434             : {
     435           4 :   return nat_template_rewrite (exp, fr, collector_port, QUOTA_EXCEEDED,
     436             :                                MAX_BIB_ENTRIES);
     437             : }
     438             : 
     439             : u8 *
     440           4 : nat_template_rewrite_nat64_bib (ipfix_exporter_t *exp, flow_report_t *fr,
     441             :                                 u16 collector_port,
     442             :                                 ipfix_report_element_t *elts, u32 n_elts,
     443             :                                 u32 *stream_index)
     444             : {
     445           4 :   return nat_template_rewrite (exp, fr, collector_port, NAT64_BIB_CREATE, 0);
     446             : }
     447             : 
     448             : u8 *
     449           4 : nat_template_rewrite_nat64_session (ipfix_exporter_t *exp, flow_report_t *fr,
     450             :                                     u16 collector_port,
     451             :                                     ipfix_report_element_t *elts, u32 n_elts,
     452             :                                     u32 *stream_index)
     453             : {
     454           4 :   return nat_template_rewrite (exp, fr, collector_port, NAT64_SESSION_CREATE,
     455             :                                0);
     456             : }
     457             : 
     458             : static inline void
     459          17 : nat_ipfix_header_create (flow_report_main_t * frm,
     460             :                           vlib_buffer_t * b0, u32 * offset)
     461             : {
     462          17 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
     463             :   flow_report_stream_t *stream;
     464             :   ip4_ipfix_template_packet_t *tp;
     465          17 :   ipfix_message_header_t *h = 0;
     466          17 :   ipfix_set_header_t *s = 0;
     467             :   u32 sequence_number;
     468             :   u32 stream_index;
     469             :   ip4_header_t *ip;
     470             :   udp_header_t *udp;
     471          17 :   vlib_main_t *vm = vlib_get_main ();
     472          17 :   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
     473             : 
     474          17 :   stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
     475          17 :   stream = &exp->streams[stream_index];
     476             : 
     477          17 :   b0->current_data = 0;
     478          17 :   b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
     479             :     sizeof (*s);
     480          17 :   b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_FLOW_REPORT);
     481          17 :   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
     482          17 :   vnet_buffer (b0)->sw_if_index[VLIB_TX] = exp->fib_index;
     483          17 :   tp = vlib_buffer_get_current (b0);
     484          17 :   ip = (ip4_header_t *) & tp->ip4;
     485          17 :   udp = (udp_header_t *) (ip + 1);
     486          17 :   h = (ipfix_message_header_t *) (udp + 1);
     487          17 :   s = (ipfix_set_header_t *) (h + 1);
     488             : 
     489          17 :   ip->ip_version_and_header_length = 0x45;
     490          17 :   ip->ttl = 254;
     491          17 :   ip->protocol = IP_PROTOCOL_UDP;
     492          17 :   ip->flags_and_fragment_offset = 0;
     493          17 :   ip->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
     494          17 :   ip->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
     495          17 :   udp->src_port = clib_host_to_net_u16 (stream->src_port);
     496          17 :   udp->dst_port = clib_host_to_net_u16 (exp->collector_port);
     497          17 :   udp->checksum = 0;
     498             : 
     499          34 :   h->export_time = clib_host_to_net_u32 ((u32)
     500          34 :                                          (((f64) frm->unix_time_0) +
     501          17 :                                           (vlib_time_now (vm) -
     502          17 :                                            frm->vlib_time_0)));
     503             : 
     504          17 :   sequence_number = clib_atomic_fetch_add (&stream->sequence_number, 1);
     505          17 :   h->sequence_number = clib_host_to_net_u32 (sequence_number);
     506          17 :   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
     507             : 
     508          17 :   *offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
     509          17 : }
     510             : 
     511             : static inline void
     512          15 : nat_ipfix_send (flow_report_main_t *frm, vlib_frame_t *f, vlib_buffer_t *b0,
     513             :                 u16 template_id)
     514             : {
     515             :   ip4_ipfix_template_packet_t *tp;
     516          15 :   ipfix_message_header_t *h = 0;
     517          15 :   ipfix_set_header_t *s = 0;
     518             :   ip4_header_t *ip;
     519             :   udp_header_t *udp;
     520          15 :   vlib_main_t *vm = vlib_get_main ();
     521          15 :   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
     522             : 
     523          15 :   tp = vlib_buffer_get_current (b0);
     524          15 :   ip = (ip4_header_t *) & tp->ip4;
     525          15 :   udp = (udp_header_t *) (ip + 1);
     526          15 :   h = (ipfix_message_header_t *) (udp + 1);
     527          15 :   s = (ipfix_set_header_t *) (h + 1);
     528             : 
     529          30 :   s->set_id_length = ipfix_set_id_length (template_id,
     530          15 :                                           b0->current_length -
     531             :                                           (sizeof (*ip) + sizeof (*udp) +
     532             :                                            sizeof (*h)));
     533          15 :   h->version_length = version_length (b0->current_length -
     534             :                                       (sizeof (*ip) + sizeof (*udp)));
     535             : 
     536          15 :   ip->length = clib_host_to_net_u16 (b0->current_length);
     537          15 :   ip->checksum = ip4_header_checksum (ip);
     538          15 :   udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
     539             : 
     540          15 :   if (exp->udp_checksum)
     541             :     {
     542           0 :       udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
     543           0 :       if (udp->checksum == 0)
     544           0 :         udp->checksum = 0xffff;
     545             :     }
     546             : 
     547          15 :   ASSERT (ip4_header_checksum_is_valid (ip));
     548             : 
     549          15 :   vlib_put_frame_to_node (vm, ip4_lookup_node.index, f);
     550          15 : }
     551             : 
     552             : static void
     553          16 : nat_ipfix_logging_nat44_ses (u32 thread_index, u8 nat_event, u32 src_ip,
     554             :                              u32 nat_src_ip, ip_protocol_t proto, u16 src_port,
     555             :                              u16 nat_src_port, u32 fib_index, int do_flush)
     556             : {
     557          16 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
     558          16 :   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
     559          16 :   flow_report_main_t *frm = &flow_report_main;
     560             :   vlib_frame_t *f;
     561          16 :   vlib_buffer_t *b0 = 0;
     562          16 :   u32 bi0 = ~0;
     563             :   u32 offset;
     564          16 :   vlib_main_t *vm = vlib_get_main ();
     565             :   u64 now;
     566             :   u16 template_id;
     567             :   u32 vrf_id;
     568          16 :   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
     569             : 
     570          16 :   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
     571          16 :   now += silm->milisecond_time_0;
     572             : 
     573          16 :   b0 = sitd->nat44_session_buffer;
     574             : 
     575          16 :   if (PREDICT_FALSE (b0 == 0))
     576             :     {
     577          10 :       if (do_flush)
     578           9 :         return;
     579             : 
     580           1 :       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
     581             :         {
     582             :           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
     583           0 :           return;
     584             :         }
     585             : 
     586           1 :       b0 = sitd->nat44_session_buffer = vlib_get_buffer (vm, bi0);
     587           1 :       offset = 0;
     588             :     }
     589             :   else
     590             :     {
     591           6 :       bi0 = vlib_get_buffer_index (vm, b0);
     592           6 :       offset = sitd->nat44_session_next_record_offset;
     593             :     }
     594             : 
     595           7 :   f = sitd->nat44_session_frame;
     596           7 :   if (PREDICT_FALSE (f == 0))
     597             :     {
     598             :       u32 *to_next;
     599           1 :       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
     600           1 :       sitd->nat44_session_frame = f;
     601           1 :       to_next = vlib_frame_vector_args (f);
     602           1 :       to_next[0] = bi0;
     603           1 :       f->n_vectors = 1;
     604             :     }
     605             : 
     606           7 :   if (PREDICT_FALSE (offset == 0))
     607           1 :     nat_ipfix_header_create (frm, b0, &offset);
     608             : 
     609           7 :   if (PREDICT_TRUE (do_flush == 0))
     610             :     {
     611           6 :       u64 time_stamp = clib_host_to_net_u64 (now);
     612           6 :       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
     613           6 :       offset += sizeof (time_stamp);
     614             : 
     615           6 :       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
     616           6 :       offset += sizeof (nat_event);
     617             : 
     618           6 :       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
     619           6 :       offset += sizeof (src_ip);
     620             : 
     621           6 :       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
     622           6 :       offset += sizeof (nat_src_ip);
     623             : 
     624           6 :       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
     625           6 :       offset += sizeof (proto);
     626             : 
     627           6 :       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
     628           6 :       offset += sizeof (src_port);
     629             : 
     630           6 :       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
     631           6 :       offset += sizeof (nat_src_port);
     632             : 
     633           6 :       vrf_id = fib_table_get_table_id (fib_index, FIB_PROTOCOL_IP4);
     634           6 :       vrf_id = clib_host_to_net_u32 (vrf_id);
     635           6 :       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
     636           6 :       offset += sizeof (vrf_id);
     637             : 
     638           6 :       b0->current_length += NAT44_SESSION_CREATE_LEN;
     639             :     }
     640             : 
     641           7 :   if (PREDICT_FALSE (do_flush ||
     642             :                      (offset + NAT44_SESSION_CREATE_LEN) > exp->path_mtu))
     643             :     {
     644           1 :       template_id = clib_atomic_fetch_or (
     645             :         &silm->nat44_session_template_id,
     646             :         0);
     647           1 :       nat_ipfix_send (frm, f, b0, template_id);
     648           1 :       sitd->nat44_session_frame = 0;
     649           1 :       sitd->nat44_session_buffer = 0;
     650           1 :       offset = 0;
     651             :     }
     652           7 :   sitd->nat44_session_next_record_offset = offset;
     653             : }
     654             : 
     655             : static void
     656          11 : nat_ipfix_logging_addr_exhausted (u32 thread_index, u32 pool_id, int do_flush)
     657             : {
     658          11 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
     659          11 :   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
     660          11 :   flow_report_main_t *frm = &flow_report_main;
     661             :   vlib_frame_t *f;
     662          11 :   vlib_buffer_t *b0 = 0;
     663          11 :   u32 bi0 = ~0;
     664             :   u32 offset;
     665          11 :   vlib_main_t *vm = vlib_get_main ();
     666             :   u64 now;
     667          11 :   u8 nat_event = NAT_ADDRESSES_EXHAUTED;
     668             :   u16 template_id;
     669          11 :   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
     670             : 
     671          11 :   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
     672          11 :   now += silm->milisecond_time_0;
     673             : 
     674          11 :   b0 = sitd->addr_exhausted_buffer;
     675             : 
     676          11 :   if (PREDICT_FALSE (b0 == 0))
     677             :     {
     678          10 :       if (do_flush)
     679           9 :         return;
     680             : 
     681           1 :       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
     682             :         {
     683             :           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
     684           0 :           return;
     685             :         }
     686             : 
     687           1 :       b0 = sitd->addr_exhausted_buffer = vlib_get_buffer (vm, bi0);
     688           1 :       offset = 0;
     689             :     }
     690             :   else
     691             :     {
     692           1 :       bi0 = vlib_get_buffer_index (vm, b0);
     693           1 :       offset = sitd->addr_exhausted_next_record_offset;
     694             :     }
     695             : 
     696           2 :   f = sitd->addr_exhausted_frame;
     697           2 :   if (PREDICT_FALSE (f == 0))
     698             :     {
     699             :       u32 *to_next;
     700           1 :       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
     701           1 :       sitd->addr_exhausted_frame = f;
     702           1 :       to_next = vlib_frame_vector_args (f);
     703           1 :       to_next[0] = bi0;
     704           1 :       f->n_vectors = 1;
     705             :     }
     706             : 
     707           2 :   if (PREDICT_FALSE (offset == 0))
     708           1 :     nat_ipfix_header_create (frm, b0, &offset);
     709             : 
     710           2 :   if (PREDICT_TRUE (do_flush == 0))
     711             :     {
     712           1 :       u64 time_stamp = clib_host_to_net_u64 (now);
     713           1 :       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
     714           1 :       offset += sizeof (time_stamp);
     715             : 
     716           1 :       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
     717           1 :       offset += sizeof (nat_event);
     718             : 
     719           1 :       clib_memcpy_fast (b0->data + offset, &pool_id, sizeof (pool_id));
     720           1 :       offset += sizeof (pool_id);
     721             : 
     722           1 :       b0->current_length += NAT_ADDRESSES_EXHAUTED_LEN;
     723             :     }
     724             : 
     725           2 :   if (PREDICT_FALSE (do_flush ||
     726             :                      (offset + NAT_ADDRESSES_EXHAUTED_LEN) > exp->path_mtu))
     727             :     {
     728           1 :       template_id = clib_atomic_fetch_or (
     729             :           &silm->addr_exhausted_template_id,
     730             :           0);
     731           1 :       nat_ipfix_send (frm, f, b0, template_id);
     732           1 :       sitd->addr_exhausted_frame = 0;
     733           1 :       sitd->addr_exhausted_buffer = 0;
     734           1 :       offset = 0;
     735             :     }
     736           2 :   sitd->addr_exhausted_next_record_offset = offset;
     737             : }
     738             : 
     739             : static void
     740          10 : nat_ipfix_logging_max_entries_per_usr (u32 thread_index,
     741             :                                         u32 limit, u32 src_ip, int do_flush)
     742             : {
     743          10 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
     744          10 :   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
     745          10 :   flow_report_main_t *frm = &flow_report_main;
     746             :   vlib_frame_t *f;
     747          10 :   vlib_buffer_t *b0 = 0;
     748          10 :   u32 bi0 = ~0;
     749             :   u32 offset;
     750          10 :   vlib_main_t *vm = vlib_get_main ();
     751             :   u64 now;
     752          10 :   u8 nat_event = QUOTA_EXCEEDED;
     753          10 :   u32 quota_event = clib_host_to_net_u32 (MAX_ENTRIES_PER_USER);
     754             :   u16 template_id;
     755          10 :   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
     756             : 
     757          10 :   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
     758          10 :   now += silm->milisecond_time_0;
     759             : 
     760          10 :   b0 = sitd->max_entries_per_user_buffer;
     761             : 
     762          10 :   if (PREDICT_FALSE (b0 == 0))
     763             :     {
     764          10 :       if (do_flush)
     765          10 :         return;
     766             : 
     767           0 :       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
     768             :         {
     769             :           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
     770           0 :           return;
     771             :         }
     772             : 
     773           0 :       b0 = sitd->max_entries_per_user_buffer = vlib_get_buffer (vm, bi0);
     774           0 :       offset = 0;
     775             :     }
     776             :   else
     777             :     {
     778           0 :       bi0 = vlib_get_buffer_index (vm, b0);
     779           0 :       offset = sitd->max_entries_per_user_next_record_offset;
     780             :     }
     781             : 
     782           0 :   f = sitd->max_entries_per_user_frame;
     783           0 :   if (PREDICT_FALSE (f == 0))
     784             :     {
     785             :       u32 *to_next;
     786           0 :       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
     787           0 :       sitd->max_entries_per_user_frame = f;
     788           0 :       to_next = vlib_frame_vector_args (f);
     789           0 :       to_next[0] = bi0;
     790           0 :       f->n_vectors = 1;
     791             :     }
     792             : 
     793           0 :   if (PREDICT_FALSE (offset == 0))
     794           0 :     nat_ipfix_header_create (frm, b0, &offset);
     795             : 
     796           0 :   if (PREDICT_TRUE (do_flush == 0))
     797             :     {
     798           0 :       u64 time_stamp = clib_host_to_net_u64 (now);
     799           0 :       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
     800           0 :       offset += sizeof (time_stamp);
     801             : 
     802           0 :       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
     803           0 :       offset += sizeof (nat_event);
     804             : 
     805           0 :       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
     806           0 :       offset += sizeof (quota_event);
     807             : 
     808           0 :       limit = clib_host_to_net_u32 (limit);
     809           0 :       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
     810           0 :       offset += sizeof (limit);
     811             : 
     812           0 :       clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
     813           0 :       offset += sizeof (src_ip);
     814             : 
     815           0 :       b0->current_length += MAX_ENTRIES_PER_USER_LEN;
     816             :     }
     817             : 
     818           0 :   if (PREDICT_FALSE (do_flush ||
     819             :                      (offset + MAX_ENTRIES_PER_USER_LEN) > exp->path_mtu))
     820             :     {
     821           0 :       template_id = clib_atomic_fetch_or (
     822             :           &silm->max_entries_per_user_template_id,
     823             :           0);
     824           0 :       nat_ipfix_send (frm, f, b0, template_id);
     825           0 :       sitd->max_entries_per_user_frame = 0;
     826           0 :       sitd->max_entries_per_user_buffer = 0;
     827           0 :       offset = 0;
     828             :     }
     829           0 :   sitd->max_entries_per_user_next_record_offset = offset;
     830             : }
     831             : 
     832             : static void
     833          11 : nat_ipfix_logging_max_ses (u32 thread_index, u32 limit, int do_flush)
     834             : {
     835          11 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
     836          11 :   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
     837          11 :   flow_report_main_t *frm = &flow_report_main;
     838             :   vlib_frame_t *f;
     839          11 :   vlib_buffer_t *b0 = 0;
     840          11 :   u32 bi0 = ~0;
     841             :   u32 offset;
     842          11 :   vlib_main_t *vm = vlib_get_main ();
     843             :   u64 now;
     844          11 :   u8 nat_event = QUOTA_EXCEEDED;
     845          11 :   u32 quota_event = clib_host_to_net_u32 (MAX_SESSION_ENTRIES);
     846             :   u16 template_id;
     847          11 :   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
     848             : 
     849          11 :   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
     850          11 :   now += silm->milisecond_time_0;
     851             : 
     852          11 :   b0 = sitd->max_sessions_buffer;
     853             : 
     854          11 :   if (PREDICT_FALSE (b0 == 0))
     855             :     {
     856          10 :       if (do_flush)
     857           9 :         return;
     858             : 
     859           1 :       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
     860             :         {
     861             :           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
     862           0 :           return;
     863             :         }
     864             : 
     865           1 :       b0 = sitd->max_sessions_buffer = vlib_get_buffer (vm, bi0);
     866           1 :       offset = 0;
     867             :     }
     868             :   else
     869             :     {
     870           1 :       bi0 = vlib_get_buffer_index (vm, b0);
     871           1 :       offset = sitd->max_sessions_next_record_offset;
     872             :     }
     873             : 
     874           2 :   f = sitd->max_sessions_frame;
     875           2 :   if (PREDICT_FALSE (f == 0))
     876             :     {
     877             :       u32 *to_next;
     878           1 :       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
     879           1 :       sitd->max_sessions_frame = f;
     880           1 :       to_next = vlib_frame_vector_args (f);
     881           1 :       to_next[0] = bi0;
     882           1 :       f->n_vectors = 1;
     883             :     }
     884             : 
     885           2 :   if (PREDICT_FALSE (offset == 0))
     886           1 :     nat_ipfix_header_create (frm, b0, &offset);
     887             : 
     888           2 :   if (PREDICT_TRUE (do_flush == 0))
     889             :     {
     890           1 :       u64 time_stamp = clib_host_to_net_u64 (now);
     891           1 :       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
     892           1 :       offset += sizeof (time_stamp);
     893             : 
     894           1 :       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
     895           1 :       offset += sizeof (nat_event);
     896             : 
     897           1 :       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
     898           1 :       offset += sizeof (quota_event);
     899             : 
     900           1 :       limit = clib_host_to_net_u32 (limit);
     901           1 :       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
     902           1 :       offset += sizeof (limit);
     903             : 
     904           1 :       b0->current_length += MAX_SESSIONS_LEN;
     905             :     }
     906             : 
     907           2 :   if (PREDICT_FALSE (do_flush || (offset + MAX_SESSIONS_LEN) > exp->path_mtu))
     908             :     {
     909           1 :       template_id = clib_atomic_fetch_or (
     910             :         &silm->max_sessions_template_id,
     911             :         0);
     912           1 :       nat_ipfix_send (frm, f, b0, template_id);
     913           1 :       sitd->max_sessions_frame = 0;
     914           1 :       sitd->max_sessions_buffer = 0;
     915           1 :       offset = 0;
     916             :     }
     917           2 :   sitd->max_sessions_next_record_offset = offset;
     918             : }
     919             : 
     920             : static void
     921          10 : nat_ipfix_logging_max_bib (u32 thread_index, u32 limit, int do_flush)
     922             : {
     923          10 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
     924          10 :   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
     925          10 :   flow_report_main_t *frm = &flow_report_main;
     926             :   vlib_frame_t *f;
     927          10 :   vlib_buffer_t *b0 = 0;
     928          10 :   u32 bi0 = ~0;
     929             :   u32 offset;
     930          10 :   vlib_main_t *vm = vlib_get_main ();
     931             :   u64 now;
     932          10 :   u8 nat_event = QUOTA_EXCEEDED;
     933          10 :   u32 quota_event = clib_host_to_net_u32 (MAX_BIB_ENTRIES);
     934             :   u16 template_id;
     935          10 :   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
     936             : 
     937          10 :   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
     938          10 :   now += silm->milisecond_time_0;
     939             : 
     940          10 :   b0 = sitd->max_bibs_buffer;
     941             : 
     942          10 :   if (PREDICT_FALSE (b0 == 0))
     943             :     {
     944          10 :       if (do_flush)
     945          10 :         return;
     946             : 
     947           0 :       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
     948             :         {
     949             :           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
     950           0 :           return;
     951             :         }
     952             : 
     953           0 :       b0 = sitd->max_bibs_buffer = vlib_get_buffer (vm, bi0);
     954           0 :       offset = 0;
     955             :     }
     956             :   else
     957             :     {
     958           0 :       bi0 = vlib_get_buffer_index (vm, b0);
     959           0 :       offset = sitd->max_bibs_next_record_offset;
     960             :     }
     961             : 
     962           0 :   f = sitd->max_bibs_frame;
     963           0 :   if (PREDICT_FALSE (f == 0))
     964             :     {
     965             :       u32 *to_next;
     966           0 :       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
     967           0 :       sitd->max_bibs_frame = f;
     968           0 :       to_next = vlib_frame_vector_args (f);
     969           0 :       to_next[0] = bi0;
     970           0 :       f->n_vectors = 1;
     971             :     }
     972             : 
     973           0 :   if (PREDICT_FALSE (offset == 0))
     974           0 :     nat_ipfix_header_create (frm, b0, &offset);
     975             : 
     976           0 :   if (PREDICT_TRUE (do_flush == 0))
     977             :     {
     978           0 :       u64 time_stamp = clib_host_to_net_u64 (now);
     979           0 :       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
     980           0 :       offset += sizeof (time_stamp);
     981             : 
     982           0 :       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
     983           0 :       offset += sizeof (nat_event);
     984             : 
     985           0 :       clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
     986           0 :       offset += sizeof (quota_event);
     987             : 
     988           0 :       limit = clib_host_to_net_u32 (limit);
     989           0 :       clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
     990           0 :       offset += sizeof (limit);
     991             : 
     992           0 :       b0->current_length += MAX_BIBS_LEN;
     993             :     }
     994             : 
     995           0 :   if (PREDICT_FALSE (do_flush || (offset + MAX_BIBS_LEN) > exp->path_mtu))
     996             :     {
     997           0 :       template_id = clib_atomic_fetch_or (
     998             :         &silm->max_bibs_template_id,
     999             :         0);
    1000           0 :       nat_ipfix_send (frm, f, b0, template_id);
    1001           0 :       sitd->max_bibs_frame = 0;
    1002           0 :       sitd->max_bibs_buffer = 0;
    1003           0 :       offset = 0;
    1004             :     }
    1005           0 :   sitd->max_bibs_next_record_offset = offset;
    1006             : }
    1007             : 
    1008             : static void
    1009          35 : nat_ipfix_logging_nat64_bibe (u32 thread_index, u8 nat_event,
    1010             :                               ip6_address_t * src_ip, u32 nat_src_ip,
    1011             :                               u8 proto, u16 src_port, u16 nat_src_port,
    1012             :                               u32 vrf_id, int do_flush)
    1013             : {
    1014          35 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
    1015          35 :   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
    1016          35 :   flow_report_main_t *frm = &flow_report_main;
    1017             :   vlib_frame_t *f;
    1018          35 :   vlib_buffer_t *b0 = 0;
    1019          35 :   u32 bi0 = ~0;
    1020             :   u32 offset;
    1021          35 :   vlib_main_t *vm = vlib_get_main ();
    1022             :   u64 now;
    1023             :   u16 template_id;
    1024          35 :   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
    1025             : 
    1026          35 :   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
    1027          35 :   now += silm->milisecond_time_0;
    1028             : 
    1029          35 :   b0 = sitd->nat64_bib_buffer;
    1030             : 
    1031          35 :   if (PREDICT_FALSE (b0 == 0))
    1032             :     {
    1033          11 :       if (do_flush)
    1034           4 :         return;
    1035             : 
    1036           7 :       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
    1037             :         {
    1038             :           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
    1039           0 :           return;
    1040             :         }
    1041             : 
    1042           7 :       b0 = sitd->nat64_bib_buffer = vlib_get_buffer (vm, bi0);
    1043           7 :       offset = 0;
    1044             :     }
    1045             :   else
    1046             :     {
    1047          24 :       bi0 = vlib_get_buffer_index (vm, b0);
    1048          24 :       offset = sitd->nat64_bib_next_record_offset;
    1049             :     }
    1050             : 
    1051          31 :   f = sitd->nat64_bib_frame;
    1052          31 :   if (PREDICT_FALSE (f == 0))
    1053             :     {
    1054             :       u32 *to_next;
    1055           7 :       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
    1056           7 :       sitd->nat64_bib_frame = f;
    1057           7 :       to_next = vlib_frame_vector_args (f);
    1058           7 :       to_next[0] = bi0;
    1059           7 :       f->n_vectors = 1;
    1060             :     }
    1061             : 
    1062          31 :   if (PREDICT_FALSE (offset == 0))
    1063           7 :     nat_ipfix_header_create (frm, b0, &offset);
    1064             : 
    1065          31 :   if (PREDICT_TRUE (do_flush == 0))
    1066             :     {
    1067          25 :       u64 time_stamp = clib_host_to_net_u64 (now);
    1068          25 :       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
    1069          25 :       offset += sizeof (time_stamp);
    1070             : 
    1071          25 :       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
    1072          25 :       offset += sizeof (nat_event);
    1073             : 
    1074          25 :       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
    1075          25 :       offset += sizeof (ip6_address_t);
    1076             : 
    1077          25 :       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
    1078          25 :       offset += sizeof (nat_src_ip);
    1079             : 
    1080          25 :       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
    1081          25 :       offset += sizeof (proto);
    1082             : 
    1083          25 :       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
    1084          25 :       offset += sizeof (src_port);
    1085             : 
    1086          25 :       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
    1087          25 :       offset += sizeof (nat_src_port);
    1088             : 
    1089          25 :       vrf_id = clib_host_to_net_u32 (vrf_id);
    1090          25 :       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
    1091          25 :       offset += sizeof (vrf_id);
    1092             : 
    1093          25 :       b0->current_length += NAT64_BIB_LEN;
    1094             :     }
    1095             : 
    1096          31 :   if (PREDICT_FALSE (do_flush || (offset + NAT64_BIB_LEN) > exp->path_mtu))
    1097             :     {
    1098           6 :       template_id = clib_atomic_fetch_or (
    1099             :         &silm->nat64_bib_template_id,
    1100             :         0);
    1101           6 :       nat_ipfix_send (frm, f, b0, template_id);
    1102           6 :       sitd->nat64_bib_frame = 0;
    1103           6 :       sitd->nat64_bib_buffer = 0;
    1104           6 :       offset = 0;
    1105             :     }
    1106          31 :   sitd->nat64_bib_next_record_offset = offset;
    1107             : }
    1108             : 
    1109             : static void
    1110          32 : nat_ipfix_logging_nat64_ses (u32 thread_index, u8 nat_event,
    1111             :                              ip6_address_t * src_ip, u32 nat_src_ip,
    1112             :                              u8 proto, u16 src_port, u16 nat_src_port,
    1113             :                              ip6_address_t * dst_ip, u32 nat_dst_ip,
    1114             :                              u16 dst_port, u16 nat_dst_port,
    1115             :                              u32 vrf_id, int do_flush)
    1116             : {
    1117          32 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
    1118          32 :   nat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
    1119          32 :   flow_report_main_t *frm = &flow_report_main;
    1120             :   vlib_frame_t *f;
    1121          32 :   vlib_buffer_t *b0 = 0;
    1122          32 :   u32 bi0 = ~0;
    1123             :   u32 offset;
    1124          32 :   vlib_main_t *vm = vlib_get_main ();
    1125             :   u64 now;
    1126             :   u16 template_id;
    1127          32 :   ipfix_exporter_t *exp = pool_elt_at_index (frm->exporters, 0);
    1128             : 
    1129          32 :   now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
    1130          32 :   now += silm->milisecond_time_0;
    1131             : 
    1132          32 :   b0 = sitd->nat64_ses_buffer;
    1133             : 
    1134          32 :   if (PREDICT_FALSE (b0 == 0))
    1135             :     {
    1136          12 :       if (do_flush)
    1137           5 :         return;
    1138             : 
    1139           7 :       if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
    1140             :         {
    1141             :           //nat_elog_err ("can't allocate buffer for NAT IPFIX event");
    1142           0 :           return;
    1143             :         }
    1144             : 
    1145           7 :       b0 = sitd->nat64_ses_buffer = vlib_get_buffer (vm, bi0);
    1146           7 :       offset = 0;
    1147             :     }
    1148             :   else
    1149             :     {
    1150          20 :       bi0 = vlib_get_buffer_index (vm, b0);
    1151          20 :       offset = sitd->nat64_ses_next_record_offset;
    1152             :     }
    1153             : 
    1154          27 :   f = sitd->nat64_ses_frame;
    1155          27 :   if (PREDICT_FALSE (f == 0))
    1156             :     {
    1157             :       u32 *to_next;
    1158           7 :       f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
    1159           7 :       sitd->nat64_ses_frame = f;
    1160           7 :       to_next = vlib_frame_vector_args (f);
    1161           7 :       to_next[0] = bi0;
    1162           7 :       f->n_vectors = 1;
    1163             :     }
    1164             : 
    1165          27 :   if (PREDICT_FALSE (offset == 0))
    1166           7 :     nat_ipfix_header_create (frm, b0, &offset);
    1167             : 
    1168          27 :   if (PREDICT_TRUE (do_flush == 0))
    1169             :     {
    1170          22 :       u64 time_stamp = clib_host_to_net_u64 (now);
    1171          22 :       clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
    1172          22 :       offset += sizeof (time_stamp);
    1173             : 
    1174          22 :       clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
    1175          22 :       offset += sizeof (nat_event);
    1176             : 
    1177          22 :       clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
    1178          22 :       offset += sizeof (ip6_address_t);
    1179             : 
    1180          22 :       clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
    1181          22 :       offset += sizeof (nat_src_ip);
    1182             : 
    1183          22 :       clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
    1184          22 :       offset += sizeof (proto);
    1185             : 
    1186          22 :       clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
    1187          22 :       offset += sizeof (src_port);
    1188             : 
    1189          22 :       clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
    1190          22 :       offset += sizeof (nat_src_port);
    1191             : 
    1192          22 :       clib_memcpy_fast (b0->data + offset, dst_ip, sizeof (ip6_address_t));
    1193          22 :       offset += sizeof (ip6_address_t);
    1194             : 
    1195          22 :       clib_memcpy_fast (b0->data + offset, &nat_dst_ip, sizeof (nat_dst_ip));
    1196          22 :       offset += sizeof (nat_dst_ip);
    1197             : 
    1198          22 :       clib_memcpy_fast (b0->data + offset, &dst_port, sizeof (dst_port));
    1199          22 :       offset += sizeof (dst_port);
    1200             : 
    1201          22 :       clib_memcpy_fast (b0->data + offset, &nat_dst_port, sizeof (nat_dst_port));
    1202          22 :       offset += sizeof (nat_dst_port);
    1203             : 
    1204          22 :       vrf_id = clib_host_to_net_u32 (vrf_id);
    1205          22 :       clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
    1206          22 :       offset += sizeof (vrf_id);
    1207             : 
    1208          22 :       b0->current_length += NAT64_SES_LEN;
    1209             :     }
    1210             : 
    1211          27 :   if (PREDICT_FALSE (do_flush || (offset + NAT64_SES_LEN) > exp->path_mtu))
    1212             :     {
    1213           6 :       template_id = clib_atomic_fetch_or (
    1214             :         &silm->nat64_ses_template_id,
    1215             :         0);
    1216           6 :       nat_ipfix_send (frm, f, b0, template_id);
    1217           6 :       sitd->nat64_ses_frame = 0;
    1218           6 :       sitd->nat64_ses_buffer = 0;
    1219           6 :       offset = 0;
    1220             :     }
    1221          27 :   sitd->nat64_ses_next_record_offset = offset;
    1222             : }
    1223             : 
    1224             : void
    1225          10 : nat_ipfix_flush (u32 thread_index)
    1226             : {
    1227          10 :   int do_flush = 1;
    1228             : 
    1229          10 :   nat_ipfix_logging_nat44_ses (thread_index,
    1230             :                                 0, 0, 0, 0, 0, 0, 0, do_flush);
    1231          10 :   nat_ipfix_logging_addr_exhausted (thread_index, 0, do_flush);
    1232          10 :   nat_ipfix_logging_max_entries_per_usr (thread_index, 0, 0, do_flush);
    1233          10 :   nat_ipfix_logging_max_ses (thread_index, 0, do_flush);
    1234          10 :   nat_ipfix_logging_max_bib (thread_index, 0, do_flush);
    1235          10 :   nat_ipfix_logging_nat64_bibe (thread_index,
    1236             :                                 0, 0, 0, 0, 0, 0, 0, do_flush);
    1237          10 :   nat_ipfix_logging_nat64_ses (thread_index,
    1238             :                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, do_flush);
    1239          10 : }
    1240             : 
    1241             : int
    1242           5 : nat_ipfix_logging_enabled ()
    1243             : {
    1244           5 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
    1245           5 :   return !clib_atomic_fetch_or(&silm->enabled, 0);
    1246             : }
    1247             : 
    1248             : void
    1249          10 : nat_ipfix_flush_from_main (void)
    1250             : {
    1251          10 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
    1252             :   vlib_main_t *worker_vm;
    1253             :   int i;
    1254             : 
    1255          10 :   if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))
    1256           0 :     return;
    1257             : 
    1258          10 :   if (PREDICT_FALSE (!silm->worker_vms))
    1259             :     {
    1260          10 :       for (i = 1; i < vlib_get_n_threads (); i++)
    1261             :         {
    1262           0 :           worker_vm = vlib_get_main_by_index (i);
    1263           0 :           if (worker_vm)
    1264           0 :             vec_add1 (silm->worker_vms, worker_vm);
    1265             :         }
    1266             :     }
    1267             : 
    1268             :   /* Trigger flush for each worker thread */
    1269          10 :   for (i = 0; i < vec_len (silm->worker_vms); i++)
    1270             :     {
    1271           0 :       worker_vm = silm->worker_vms[i];
    1272           0 :       if (worker_vm)
    1273           0 :         vlib_node_set_interrupt_pending (worker_vm,
    1274             :                                          nat_ipfix_flush_node.index);
    1275             :     }
    1276             : 
    1277             :   /* Finally flush main thread */
    1278          10 :   nat_ipfix_flush (0);
    1279             : }
    1280             : 
    1281             : /**
    1282             :  * @brief Generate NAT44 session create event
    1283             :  */
    1284             : void
    1285       39001 : nat_ipfix_logging_nat44_ses_create (u32 thread_index, u32 src_ip,
    1286             :                                     u32 nat_src_ip, ip_protocol_t proto,
    1287             :                                     u16 src_port, u16 nat_src_port,
    1288             :                                     u32 fib_index)
    1289             : {
    1290       39001 :   skip_if_disabled ();
    1291             : 
    1292           0 :   nat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_CREATE, src_ip,
    1293             :                                nat_src_ip, proto, src_port, nat_src_port,
    1294             :                                fib_index, 0);
    1295             : }
    1296             : 
    1297             : /**
    1298             :  * @brief Generate NAT44 session delete event
    1299             :  */
    1300             : void
    1301       38784 : nat_ipfix_logging_nat44_ses_delete (u32 thread_index, u32 src_ip,
    1302             :                                     u32 nat_src_ip, ip_protocol_t proto,
    1303             :                                     u16 src_port, u16 nat_src_port,
    1304             :                                     u32 fib_index)
    1305             : {
    1306       38784 :   skip_if_disabled ();
    1307             : 
    1308           3 :   nat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_DELETE, src_ip,
    1309             :                                nat_src_ip, proto, src_port, nat_src_port,
    1310             :                                fib_index, 0);
    1311             : }
    1312             : 
    1313             : /**
    1314             :  * @brief Generate NAT addresses exhausted event
    1315             :  *
    1316             :  * @param thread_index thread index
    1317             :  * @param pool_id NAT pool ID
    1318             :  */
    1319             : void
    1320          11 : nat_ipfix_logging_addresses_exhausted (u32 thread_index, u32 pool_id)
    1321             : {
    1322             :   //TODO: This event SHOULD be rate limited
    1323          11 :   skip_if_disabled ();
    1324             : 
    1325           1 :   nat_ipfix_logging_addr_exhausted (thread_index, pool_id, 0);
    1326             : }
    1327             : 
    1328             : /**
    1329             :  * @brief Generate maximum entries per user exceeded event
    1330             :  *
    1331             :  * @param thread_index thread index
    1332             :  * @param limit maximum NAT entries that can be created per user
    1333             :  * @param src_ip source IPv4 address
    1334             :  */
    1335             : void
    1336           0 : nat_ipfix_logging_max_entries_per_user (u32 thread_index, u32 limit, u32 src_ip)
    1337             : {
    1338             :   //TODO: This event SHOULD be rate limited
    1339           0 :   skip_if_disabled ();
    1340             : 
    1341           0 :   nat_ipfix_logging_max_entries_per_usr (thread_index, limit, src_ip, 0);
    1342             : }
    1343             : 
    1344             : vlib_frame_t *
    1345           0 : deterministic_nat_data_callback
    1346             : (flow_report_main_t * frm,
    1347             :                                         flow_report_t * fr,
    1348             :                                         vlib_frame_t * f,
    1349             :                                         u32 * to_next, u32 node_index)
    1350             : {
    1351           0 :   nat_ipfix_flush_from_main();
    1352             : 
    1353           0 :   return f;
    1354             : }
    1355             : 
    1356             : /**
    1357             :  * @brief Generate maximum session entries exceeded event
    1358             :  *
    1359             :  * @param thread_index thread index
    1360             :  * @param limit configured limit
    1361             :  */
    1362             : void
    1363           6 : nat_ipfix_logging_max_sessions (u32 thread_index, u32 limit)
    1364             : {
    1365             :   //TODO: This event SHOULD be rate limited
    1366           6 :   skip_if_disabled ();
    1367             : 
    1368           1 :   nat_ipfix_logging_max_ses (thread_index, limit, 0);
    1369             : }
    1370             : 
    1371             : /**
    1372             :  * @brief Generate maximum BIB entries exceeded event
    1373             :  *
    1374             :  * @param thread_index thread index
    1375             :  * @param limit configured limit
    1376             :  */
    1377             : void
    1378           0 : nat_ipfix_logging_max_bibs (u32 thread_index, u32 limit)
    1379             : {
    1380             :   //TODO: This event SHOULD be rate limited
    1381           0 :   skip_if_disabled ();
    1382             : 
    1383           0 :   nat_ipfix_logging_max_bib (thread_index, limit, 0);
    1384             : }
    1385             : 
    1386             : /**
    1387             :  * @brief Generate NAT64 BIB create and delete events
    1388             :  *
    1389             :  * @param thread_index thread index
    1390             :  * @param src_ip       source IPv6 address
    1391             :  * @param nat_src_ip   transaltes source IPv4 address
    1392             :  * @param proto        L4 protocol
    1393             :  * @param src_port     source port
    1394             :  * @param nat_src_port translated source port
    1395             :  * @param vrf_id       VRF ID
    1396             :  * @param is_create    non-zero value if create event otherwise delete event
    1397             :  */
    1398             : void
    1399          44 : nat_ipfix_logging_nat64_bib (u32 thread_index, ip6_address_t * src_ip,
    1400             :                              ip4_address_t * nat_src_ip, u8 proto,
    1401             :                              u16 src_port, u16 nat_src_port, u32 vrf_id,
    1402             :                              u8 is_create)
    1403             : {
    1404             :   u8 nat_event;
    1405             : 
    1406          44 :   skip_if_disabled ();
    1407             : 
    1408          25 :   nat_event = is_create ? NAT64_BIB_CREATE : NAT64_BIB_DELETE;
    1409             : 
    1410          25 :   nat_ipfix_logging_nat64_bibe (thread_index, nat_event, src_ip,
    1411             :                                 nat_src_ip->as_u32, proto, src_port,
    1412             :                                 nat_src_port, vrf_id, 0);
    1413             : }
    1414             : 
    1415             : /**
    1416             :  * @brief Generate NAT64 session create and delete events
    1417             :  *
    1418             :  * @param thread_index thread index
    1419             :  * @param src_ip       source IPv6 address
    1420             :  * @param nat_src_ip   transaltes source IPv4 address
    1421             :  * @param proto        L4 protocol
    1422             :  * @param src_port     source port
    1423             :  * @param nat_src_port translated source port
    1424             :  * @param dst_ip       destination IPv6 address
    1425             :  * @param nat_dst_ip   destination IPv4 address
    1426             :  * @param dst_port     destination port
    1427             :  * @param nat_dst_port translated destination port
    1428             :  * @param vrf_id       VRF ID
    1429             :  * @param is_create    non-zero value if create event otherwise delete event
    1430             :  */
    1431             : void
    1432          40 : nat_ipfix_logging_nat64_session (u32 thread_index,
    1433             :                                  ip6_address_t * src_ip,
    1434             :                                  ip4_address_t * nat_src_ip, u8 proto,
    1435             :                                  u16 src_port, u16 nat_src_port,
    1436             :                                  ip6_address_t * dst_ip,
    1437             :                                  ip4_address_t * nat_dst_ip, u16 dst_port,
    1438             :                                  u16 nat_dst_port, u32 vrf_id, u8 is_create)
    1439             : {
    1440             :   u8 nat_event;
    1441             : 
    1442          40 :   skip_if_disabled ();
    1443             : 
    1444          22 :   nat_event = is_create ? NAT64_SESSION_CREATE : NAT64_SESSION_DELETE;
    1445             : 
    1446          22 :   nat_ipfix_logging_nat64_ses (thread_index, nat_event, src_ip,
    1447             :                                nat_src_ip->as_u32, proto, src_port,
    1448             :                                nat_src_port, dst_ip, nat_dst_ip->as_u32,
    1449             :                                dst_port, nat_dst_port, vrf_id, 0);
    1450             : }
    1451             : 
    1452             : vlib_frame_t *
    1453          60 : data_callback (flow_report_main_t *frm, ipfix_exporter_t *exp,
    1454             :                flow_report_t *fr, vlib_frame_t *f, u32 *to_next,
    1455             :                u32 node_index)
    1456             : {
    1457          60 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
    1458             : 
    1459          60 :   if (PREDICT_FALSE (++silm->call_counter >= vec_len (exp->reports)))
    1460             :     {
    1461          10 :       nat_ipfix_flush_from_main();
    1462          10 :       silm->call_counter = 0;
    1463             :     }
    1464             : 
    1465          60 :   return f;
    1466             : }
    1467             : 
    1468             : /**
    1469             :  * @brief Enable/disable NAT plugin IPFIX logging
    1470             :  *
    1471             :  * @param enable    1 if enable, 0 if disable
    1472             :  * @param domain_id observation domain ID
    1473             :  * @param src_port  source port number
    1474             :  *
    1475             :  * @returns 0 if success
    1476             :  */
    1477             : int
    1478          61 : nat_ipfix_logging_enable_disable (int enable, u32 domain_id, u16 src_port)
    1479             : {
    1480          61 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
    1481          61 :   ipfix_exporter_t *exp = &flow_report_main.exporters[0];
    1482             :   vnet_flow_report_add_del_args_t a;
    1483             :   int rv;
    1484          61 :   u8 e = enable ? 1 : 0;
    1485             : 
    1486          61 :   if (clib_atomic_cmp_and_swap (&silm->enabled, e ^ 1, e) == e)
    1487          54 :     return 0;
    1488             : 
    1489           7 :   clib_memset (&a, 0, sizeof (a));
    1490           7 :   a.is_add = enable;
    1491           7 :   a.domain_id = domain_id ? domain_id : 1;
    1492           7 :   a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
    1493           7 :   a.flow_data_callback = data_callback;
    1494             : 
    1495           7 :   a.rewrite_callback = nat_template_rewrite_nat44_session;
    1496           7 :   rv = vnet_flow_report_add_del (exp, &a, NULL);
    1497           7 :   if (rv)
    1498             :     {
    1499             :       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
    1500           0 :       return -1;
    1501             :     }
    1502             : 
    1503           7 :   a.rewrite_callback = nat_template_rewrite_addr_exhausted;
    1504           7 :   rv = vnet_flow_report_add_del (exp, &a, NULL);
    1505           7 :   if (rv)
    1506             :     {
    1507             :       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
    1508           0 :       return -1;
    1509             :     }
    1510             : 
    1511           7 :   a.rewrite_callback = nat_template_rewrite_max_sessions;
    1512           7 :   rv = vnet_flow_report_add_del (exp, &a, NULL);
    1513           7 :   if (rv)
    1514             :     {
    1515             :       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
    1516           0 :       return -1;
    1517             :     }
    1518             : 
    1519           7 :   a.rewrite_callback = nat_template_rewrite_max_bibs;
    1520           7 :   rv = vnet_flow_report_add_del (exp, &a, NULL);
    1521           7 :   if (rv)
    1522             :     {
    1523             :       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
    1524           0 :       return -1;
    1525             :     }
    1526             : 
    1527           7 :   a.rewrite_callback = nat_template_rewrite_nat64_bib;
    1528           7 :   rv = vnet_flow_report_add_del (exp, &a, NULL);
    1529           7 :   if (rv)
    1530             :     {
    1531             :       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
    1532           0 :       return -1;
    1533             :     }
    1534             : 
    1535           7 :   a.rewrite_callback = nat_template_rewrite_nat64_session;
    1536           7 :   rv = vnet_flow_report_add_del (exp, &a, NULL);
    1537           7 :   if (rv)
    1538             :     {
    1539             :       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
    1540           0 :       return -1;
    1541             :     }
    1542             : 
    1543             :   // if endpoint dependent per user max entries is also required
    1544             :   /*
    1545             :   a.rewrite_callback = nat_template_rewrite_max_entries_per_usr;
    1546             :   rv = vnet_flow_report_add_del (exp, &a, NULL);
    1547             :   if (rv)
    1548             :     {
    1549             :       //nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
    1550             :       return -1;
    1551             :     }
    1552             :   */
    1553             : 
    1554           7 :   return 0;
    1555             : }
    1556             : 
    1557             : /**
    1558             :  * @brief Initialize NAT plugin IPFIX logging
    1559             :  *
    1560             :  * @param vm vlib main
    1561             :  */
    1562             : void
    1563        1118 : nat_ipfix_logging_init (vlib_main_t * vm)
    1564             : {
    1565        1118 :   nat_ipfix_logging_main_t *silm = &nat_ipfix_logging_main;
    1566        1118 :   vlib_thread_main_t *tm = vlib_get_thread_main ();
    1567             : 
    1568        1118 :   silm->enabled = 0;
    1569        1118 :   silm->worker_vms = 0;
    1570        1118 :   silm->call_counter = 0;
    1571             : 
    1572             :   /* Set up time reference pair */
    1573        1118 :   silm->vlib_time_0 = vlib_time_now (vm);
    1574        1118 :   silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
    1575             : 
    1576        1118 :   vec_validate (silm->per_thread_data, tm->n_vlib_mains - 1);
    1577        1118 : }
    1578             : 
    1579             : static uword
    1580           0 : ipfix_flush_process (vlib_main_t *vm,
    1581             :                      vlib_node_runtime_t *rt,
    1582             :                      vlib_frame_t *f)
    1583             : {
    1584           0 :   nat_ipfix_flush(vm->thread_index);
    1585           0 :   return 0;
    1586             : }
    1587             : 
    1588             : /* *INDENT-OFF* */
    1589       49304 : VLIB_REGISTER_NODE (nat_ipfix_flush_node) = {
    1590             :   .function = ipfix_flush_process,
    1591             :   .name = "nat-ipfix-flush",
    1592             :   .type = VLIB_NODE_TYPE_INPUT,
    1593             :   .state = VLIB_NODE_STATE_INTERRUPT,
    1594             : };
    1595             : /* *INDENT-ON* */

Generated by: LCOV version 1.14