FD.io VPP  v20.05.1-6-gf53edbc3b
Vector Packet Processing
nat_ipfix_logging.c
Go to the documentation of this file.
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 
19 #include <vlibmemory/api.h>
20 #include <nat/nat_inlines.h>
21 #include <nat/nat_ipfix_logging.h>
22 #include <vppinfra/atomics.h>
23 
26 
27 #define NAT44_SESSION_CREATE_LEN 26
28 #define NAT_ADDRESSES_EXHAUTED_LEN 13
29 #define MAX_ENTRIES_PER_USER_LEN 21
30 #define MAX_SESSIONS_LEN 17
31 #define MAX_BIBS_LEN 17
32 #define MAX_FRAGMENTS_IP4_LEN 21
33 #define MAX_FRAGMENTS_IP6_LEN 33
34 #define NAT64_BIB_LEN 38
35 #define NAT64_SES_LEN 62
36 
37 #define NAT44_SESSION_CREATE_FIELD_COUNT 8
38 #define NAT_ADDRESSES_EXHAUTED_FIELD_COUNT 3
39 #define MAX_ENTRIES_PER_USER_FIELD_COUNT 5
40 #define MAX_SESSIONS_FIELD_COUNT 4
41 #define MAX_BIBS_FIELD_COUNT 4
42 #define MAX_FRAGMENTS_FIELD_COUNT 5
43 #define NAT64_BIB_FIELD_COUNT 8
44 #define NAT64_SES_FIELD_COUNT 12
45 
46 typedef struct
47 {
56 
57 typedef struct
58 {
61 
62 typedef struct
63 {
67 
68 typedef struct
69 {
72 
73 typedef struct
74 {
77 
78 typedef struct
79 {
83 
84 typedef struct
85 {
87  u64 src[2];
89 
90 typedef struct
91 {
93  u64 src_ip[2];
98  u64 dst_ip[2];
104 
105 typedef struct
106 {
115 
116 #define skip_if_disabled() \
117 do { \
118  snat_ipfix_logging_main_t *silm = &snat_ipfix_logging_main; \
119  if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0))) \
120  return; \
121 } while (0)
122 
123 #define update_template_id(old_id, new_id) \
124 do { \
125  u16 template_id = clib_atomic_fetch_or(old_id, 0); \
126  clib_atomic_cmp_and_swap(old_id, template_id, new_id); \
127 } while (0)
128 
129 /**
130  * @brief Create an IPFIX template packet rewrite string
131  *
132  * @param frm flow report main
133  * @param fr flow report
134  * @param collector_address collector address
135  * @param src_address source address
136  * @param collector_port collector
137  * @param event NAT event ID
138  * @param quota_event NAT quota exceeded event ID
139  *
140  * @returns template packet
141  */
142 static inline u8 *
144  flow_report_t * fr,
145  ip4_address_t * collector_address,
147  u16 collector_port,
148  nat_event_t event, quota_exceed_event_t quota_event)
149 {
151  ip4_header_t *ip;
152  udp_header_t *udp;
157  ipfix_field_specifier_t *first_field;
158  u8 *rewrite = 0;
160  u32 field_count = 0;
161  flow_report_stream_t *stream;
162  u32 stream_index;
163 
164  stream = &frm->streams[fr->stream_index];
165 
166  stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
168  stream_index, fr->stream_index);
169 
170  if (event == NAT_ADDRESSES_EXHAUTED)
171  {
173 
175  fr->template_id);
176  }
177  else if (event == NAT44_SESSION_CREATE)
178  {
179  field_count = NAT44_SESSION_CREATE_FIELD_COUNT;
180 
182  fr->template_id);
183  }
184  else if (event == NAT64_BIB_CREATE)
185  {
186  field_count = NAT64_BIB_FIELD_COUNT;
187 
189  fr->template_id);
190  }
191  else if (event == NAT64_SESSION_CREATE)
192  {
193  field_count = NAT64_SES_FIELD_COUNT;
194 
196  fr->template_id);
197  }
198  else if (event == QUOTA_EXCEEDED)
199  {
200  if (quota_event == MAX_ENTRIES_PER_USER)
201  {
202  field_count = MAX_ENTRIES_PER_USER_FIELD_COUNT;
203 
205  fr->template_id);
206 
207  }
208  else if (quota_event == MAX_SESSION_ENTRIES)
209  {
210  field_count = MAX_SESSIONS_FIELD_COUNT;
211 
213  fr->template_id);
214  }
215  else if (quota_event == MAX_BIB_ENTRIES)
216  {
217  field_count = MAX_BIBS_FIELD_COUNT;
218 
220  fr->template_id);
221  }
222  }
223 
224  /* allocate rewrite space */
225  vec_validate_aligned (rewrite,
227  + field_count * sizeof (ipfix_field_specifier_t) - 1,
229 
230  tp = (ip4_ipfix_template_packet_t *) rewrite;
231  ip = (ip4_header_t *) & tp->ip4;
232  udp = (udp_header_t *) (ip + 1);
233  h = (ipfix_message_header_t *) (udp + 1);
234  s = (ipfix_set_header_t *) (h + 1);
235  t = (ipfix_template_header_t *) (s + 1);
236  first_field = f = (ipfix_field_specifier_t *) (t + 1);
237 
238  ip->ip_version_and_header_length = 0x45;
239  ip->ttl = 254;
240  ip->protocol = IP_PROTOCOL_UDP;
241  ip->src_address.as_u32 = src_address->as_u32;
242  ip->dst_address.as_u32 = collector_address->as_u32;
243  udp->src_port = clib_host_to_net_u16 (stream->src_port);
244  udp->dst_port = clib_host_to_net_u16 (collector_port);
245  udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
246 
247  /* FIXUP: message header export_time */
248  h->domain_id = clib_host_to_net_u32 (stream->domain_id);
249 
250  /* Add TLVs to the template */
251  if (event == NAT_ADDRESSES_EXHAUTED)
252  {
253  f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
254  f++;
255  f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
256  f++;
257  f->e_id_length = ipfix_e_id_length (0, natPoolId, 4);
258  f++;
259  }
260  else if (event == NAT44_SESSION_CREATE)
261  {
262  f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
263  f++;
264  f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
265  f++;
266  f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
267  f++;
268  f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
269  f++;
270  f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
271  f++;
272  f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
273  f++;
274  f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
275  f++;
276  f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
277  f++;
278  }
279  else if (event == NAT64_BIB_CREATE)
280  {
281  f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
282  f++;
283  f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
284  f++;
285  f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
286  f++;
287  f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
288  f++;
289  f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
290  f++;
291  f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
292  f++;
293  f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
294  f++;
295  f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
296  f++;
297  }
298  else if (event == NAT64_SESSION_CREATE)
299  {
300  f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds, 8);
301  f++;
302  f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
303  f++;
304  f->e_id_length = ipfix_e_id_length (0, sourceIPv6Address, 16);
305  f++;
306  f->e_id_length = ipfix_e_id_length (0, postNATSourceIPv4Address, 4);
307  f++;
308  f->e_id_length = ipfix_e_id_length (0, protocolIdentifier, 1);
309  f++;
310  f->e_id_length = ipfix_e_id_length (0, sourceTransportPort, 2);
311  f++;
312  f->e_id_length = ipfix_e_id_length (0, postNAPTSourceTransportPort, 2);
313  f++;
314  f->e_id_length = ipfix_e_id_length (0, destinationIPv6Address, 16);
315  f++;
316  f->e_id_length = ipfix_e_id_length (0, postNATDestinationIPv4Address, 4);
317  f++;
318  f->e_id_length = ipfix_e_id_length (0, destinationTransportPort, 2);
319  f++;
320  f->e_id_length = ipfix_e_id_length (0, postNAPTDestinationTransportPort,
321  2);
322  f++;
323  f->e_id_length = ipfix_e_id_length (0, ingressVRFID, 4);
324  f++;
325  }
326  else if (event == QUOTA_EXCEEDED)
327  {
328  if (quota_event == MAX_ENTRIES_PER_USER)
329  {
330  f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
331  8);
332  f++;
333  f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
334  f++;
335  f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
336  f++;
337  f->e_id_length = ipfix_e_id_length (0, maxEntriesPerUser, 4);
338  f++;
339  f->e_id_length = ipfix_e_id_length (0, sourceIPv4Address, 4);
340  f++;
341  }
342  else if (quota_event == MAX_SESSION_ENTRIES)
343  {
344  f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
345  8);
346  f++;
347  f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
348  f++;
349  f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
350  f++;
351  f->e_id_length = ipfix_e_id_length (0, maxSessionEntries, 4);
352  f++;
353  }
354  else if (quota_event == MAX_BIB_ENTRIES)
355  {
356  f->e_id_length = ipfix_e_id_length (0, observationTimeMilliseconds,
357  8);
358  f++;
359  f->e_id_length = ipfix_e_id_length (0, natEvent, 1);
360  f++;
361  f->e_id_length = ipfix_e_id_length (0, natQuotaExceededEvent, 4);
362  f++;
363  f->e_id_length = ipfix_e_id_length (0, maxBIBEntries, 4);
364  f++;
365  }
366  }
367 
368  /* Back to the template packet... */
369  ip = (ip4_header_t *) & tp->ip4;
370  udp = (udp_header_t *) (ip + 1);
371 
372  ASSERT (f - first_field);
373  /* Field count in this template */
374  t->id_count = ipfix_id_count (fr->template_id, f - first_field);
375 
376  /* set length in octets */
377  s->set_id_length =
378  ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
379 
380  /* message length in octets */
381  h->version_length = version_length ((u8 *) f - (u8 *) h);
382 
383  ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
384  ip->checksum = ip4_header_checksum (ip);
385 
386  return rewrite;
387 }
388 
389 u8 *
391  flow_report_t * fr,
392  ip4_address_t * collector_address,
394  u16 collector_port,
396  u32 n_elts, u32 *stream_index)
397 {
398  return snat_template_rewrite (frm, fr, collector_address, src_address,
399  collector_port, NAT_ADDRESSES_EXHAUTED, 0);
400 }
401 
402 u8 *
404  flow_report_t * fr,
405  ip4_address_t * collector_address,
407  u16 collector_port,
409  u32 n_elts, u32 *stream_index)
410 {
411  return snat_template_rewrite (frm, fr, collector_address, src_address,
412  collector_port, NAT44_SESSION_CREATE, 0);
413 }
414 
415 u8 *
417  flow_report_t * fr,
418  ip4_address_t * collector_address,
420  u16 collector_port,
422  u32 n_elts, u32 *stream_index)
423 {
424  return snat_template_rewrite (frm, fr, collector_address, src_address,
425  collector_port, QUOTA_EXCEEDED,
427 }
428 
429 u8 *
431  flow_report_t * fr,
432  ip4_address_t * collector_address,
434  u16 collector_port,
436  u32 n_elts, u32 *stream_index)
437 {
438  return snat_template_rewrite (frm, fr, collector_address, src_address,
439  collector_port, QUOTA_EXCEEDED,
441 }
442 
443 u8 *
445  flow_report_t * fr,
446  ip4_address_t * collector_address,
448  u16 collector_port,
450  u32 n_elts, u32 *stream_index)
451 {
452  return snat_template_rewrite (frm, fr, collector_address, src_address,
453  collector_port, QUOTA_EXCEEDED,
455 }
456 
457 u8 *
459  flow_report_t * fr,
460  ip4_address_t * collector_address,
462  u16 collector_port,
464  u32 n_elts, u32 *stream_index)
465 {
466  return snat_template_rewrite (frm, fr, collector_address, src_address,
467  collector_port, NAT64_BIB_CREATE, 0);
468 }
469 
470 u8 *
472  flow_report_t * fr,
473  ip4_address_t * collector_address,
475  u16 collector_port,
477  u32 n_elts, u32 *stream_index)
478 {
479  return snat_template_rewrite (frm, fr, collector_address, src_address,
480  collector_port, NAT64_SESSION_CREATE, 0);
481 }
482 
483 static inline void
485  vlib_buffer_t * b0, u32 * offset)
486 {
488  flow_report_stream_t *stream;
491  ipfix_set_header_t *s = 0;
492  u32 sequence_number;
493  u32 stream_index;
494  ip4_header_t *ip;
495  udp_header_t *udp;
497 
498  stream_index = clib_atomic_fetch_or(&silm->stream_index, 0);
499  stream = &frm->streams[stream_index];
500 
501  b0->current_data = 0;
502  b0->current_length = sizeof (*ip) + sizeof (*udp) + sizeof (*h) +
503  sizeof (*s);
504  b0->flags |= (VLIB_BUFFER_TOTAL_LENGTH_VALID | VNET_BUFFER_F_FLOW_REPORT);
505  vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
506  vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
507  tp = vlib_buffer_get_current (b0);
508  ip = (ip4_header_t *) & tp->ip4;
509  udp = (udp_header_t *) (ip + 1);
510  h = (ipfix_message_header_t *) (udp + 1);
511  s = (ipfix_set_header_t *) (h + 1);
512 
513  ip->ip_version_and_header_length = 0x45;
514  ip->ttl = 254;
515  ip->protocol = IP_PROTOCOL_UDP;
519  udp->src_port = clib_host_to_net_u16 (stream->src_port);
520  udp->dst_port = clib_host_to_net_u16 (frm->collector_port);
521  udp->checksum = 0;
522 
523  h->export_time = clib_host_to_net_u32 ((u32)
524  (((f64) frm->unix_time_0) +
525  (vlib_time_now (vm) -
526  frm->vlib_time_0)));
527 
528  sequence_number = clib_atomic_fetch_add (&stream->sequence_number, 1);
529  h->sequence_number = clib_host_to_net_u32 (sequence_number);
530  h->domain_id = clib_host_to_net_u32 (stream->domain_id);
531 
532  *offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
533 }
534 
535 static inline void
537  vlib_frame_t * f, vlib_buffer_t * b0, u16 template_id)
538 {
541  ipfix_set_header_t *s = 0;
542  ip4_header_t *ip;
543  udp_header_t *udp;
544  vlib_main_t *vm = vlib_mains[thread_index];
545 
546  tp = vlib_buffer_get_current (b0);
547  ip = (ip4_header_t *) & tp->ip4;
548  udp = (udp_header_t *) (ip + 1);
549  h = (ipfix_message_header_t *) (udp + 1);
550  s = (ipfix_set_header_t *) (h + 1);
551 
552  s->set_id_length = ipfix_set_id_length (template_id,
553  b0->current_length -
554  (sizeof (*ip) + sizeof (*udp) +
555  sizeof (*h)));
557  (sizeof (*ip) + sizeof (*udp)));
558 
559  ip->length = clib_host_to_net_u16 (b0->current_length);
560  ip->checksum = ip4_header_checksum (ip);
561  udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
562 
563  if (frm->udp_checksum)
564  {
565  udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
566  if (udp->checksum == 0)
567  udp->checksum = 0xffff;
568  }
569 
570  ASSERT (ip->checksum == ip4_header_checksum (ip));
571 
573 }
574 
575 static void
576 snat_ipfix_logging_nat44_ses (u32 thread_index, u8 nat_event, u32 src_ip,
577  u32 nat_src_ip, nat_protocol_t nat_proto,
578  u16 src_port, u16 nat_src_port, u32 vrf_id,
579  int do_flush)
580 {
582  snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
584  vlib_frame_t *f;
585  vlib_buffer_t *b0 = 0;
586  u32 bi0 = ~0;
587  u32 offset;
588  vlib_main_t *vm = vlib_mains[thread_index];
589  u64 now;
590  u8 proto;
591  u16 template_id;
592 
593  proto = nat_proto_to_ip_proto (nat_proto);
594 
595  now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
596  now += silm->milisecond_time_0;
597 
598  b0 = sitd->nat44_session_buffer;
599 
600  if (PREDICT_FALSE (b0 == 0))
601  {
602  if (do_flush)
603  return;
604 
605  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
606  {
607  nat_elog_err ("can't allocate buffer for NAT IPFIX event");
608  return;
609  }
610 
611  b0 = sitd->nat44_session_buffer = vlib_get_buffer (vm, bi0);
613  offset = 0;
614  }
615  else
616  {
617  bi0 = vlib_get_buffer_index (vm, b0);
618  offset = sitd->nat44_session_next_record_offset;
619  }
620 
621  f = sitd->nat44_session_frame;
622  if (PREDICT_FALSE (f == 0))
623  {
624  u32 *to_next;
625  f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
626  sitd->nat44_session_frame = f;
627  to_next = vlib_frame_vector_args (f);
628  to_next[0] = bi0;
629  f->n_vectors = 1;
630  }
631 
632  if (PREDICT_FALSE (offset == 0))
633  snat_ipfix_header_create (frm, b0, &offset);
634 
635  if (PREDICT_TRUE (do_flush == 0))
636  {
637  u64 time_stamp = clib_host_to_net_u64 (now);
638  clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
639  offset += sizeof (time_stamp);
640 
641  clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
642  offset += sizeof (nat_event);
643 
644  clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
645  offset += sizeof (src_ip);
646 
647  clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
648  offset += sizeof (nat_src_ip);
649 
650  clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
651  offset += sizeof (proto);
652 
653  clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
654  offset += sizeof (src_port);
655 
656  clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
657  offset += sizeof (nat_src_port);
658 
659  clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
660  offset += sizeof (vrf_id);
661 
663  }
664 
665  if (PREDICT_FALSE
666  (do_flush || (offset + NAT44_SESSION_CREATE_LEN) > frm->path_mtu))
667  {
668  template_id = clib_atomic_fetch_or (
670  0);
671  snat_ipfix_send (thread_index, frm, f, b0, template_id);
672  sitd->nat44_session_frame = 0;
673  sitd->nat44_session_buffer = 0;
674  offset = 0;
675  }
677 }
678 
679 static void
680 snat_ipfix_logging_addr_exhausted (u32 thread_index, u32 pool_id, int do_flush)
681 {
683  snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
685  vlib_frame_t *f;
686  vlib_buffer_t *b0 = 0;
687  u32 bi0 = ~0;
688  u32 offset;
689  vlib_main_t *vm = vlib_mains[thread_index];
690  u64 now;
691  u8 nat_event = NAT_ADDRESSES_EXHAUTED;
692  u16 template_id;
693 
694  now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
695  now += silm->milisecond_time_0;
696 
697  b0 = sitd->addr_exhausted_buffer;
698 
699  if (PREDICT_FALSE (b0 == 0))
700  {
701  if (do_flush)
702  return;
703 
704  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
705  {
706  nat_elog_err ("can't allocate buffer for NAT IPFIX event");
707  return;
708  }
709 
710  b0 = sitd->addr_exhausted_buffer = vlib_get_buffer (vm, bi0);
712  offset = 0;
713  }
714  else
715  {
716  bi0 = vlib_get_buffer_index (vm, b0);
717  offset = sitd->addr_exhausted_next_record_offset;
718  }
719 
720  f = sitd->addr_exhausted_frame;
721  if (PREDICT_FALSE (f == 0))
722  {
723  u32 *to_next;
724  f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
725  sitd->addr_exhausted_frame = f;
726  to_next = vlib_frame_vector_args (f);
727  to_next[0] = bi0;
728  f->n_vectors = 1;
729  }
730 
731  if (PREDICT_FALSE (offset == 0))
732  snat_ipfix_header_create (frm, b0, &offset);
733 
734  if (PREDICT_TRUE (do_flush == 0))
735  {
736  u64 time_stamp = clib_host_to_net_u64 (now);
737  clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
738  offset += sizeof (time_stamp);
739 
740  clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
741  offset += sizeof (nat_event);
742 
743  clib_memcpy_fast (b0->data + offset, &pool_id, sizeof (pool_id));
744  offset += sizeof (pool_id);
745 
747  }
748 
749  if (PREDICT_FALSE
750  (do_flush || (offset + NAT_ADDRESSES_EXHAUTED_LEN) > frm->path_mtu))
751  {
752  template_id = clib_atomic_fetch_or (
754  0);
755  snat_ipfix_send (thread_index, frm, f, b0, template_id);
756  sitd->addr_exhausted_frame = 0;
757  sitd->addr_exhausted_buffer = 0;
758  offset = 0;
759  }
761 }
762 
763 static void
765  u32 limit, u32 src_ip, int do_flush)
766 {
768  snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
770  vlib_frame_t *f;
771  vlib_buffer_t *b0 = 0;
772  u32 bi0 = ~0;
773  u32 offset;
774  vlib_main_t *vm = vlib_mains[thread_index];
775  u64 now;
776  u8 nat_event = QUOTA_EXCEEDED;
777  u32 quota_event = MAX_ENTRIES_PER_USER;
778  u16 template_id;
779 
780  now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
781  now += silm->milisecond_time_0;
782 
783  b0 = sitd->max_entries_per_user_buffer;
784 
785  if (PREDICT_FALSE (b0 == 0))
786  {
787  if (do_flush)
788  return;
789 
790  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
791  {
792  nat_elog_err ("can't allocate buffer for NAT IPFIX event");
793  return;
794  }
795 
796  b0 = sitd->max_entries_per_user_buffer = vlib_get_buffer (vm, bi0);
798  offset = 0;
799  }
800  else
801  {
802  bi0 = vlib_get_buffer_index (vm, b0);
804  }
805 
806  f = sitd->max_entries_per_user_frame;
807  if (PREDICT_FALSE (f == 0))
808  {
809  u32 *to_next;
810  f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
811  sitd->max_entries_per_user_frame = f;
812  to_next = vlib_frame_vector_args (f);
813  to_next[0] = bi0;
814  f->n_vectors = 1;
815  }
816 
817  if (PREDICT_FALSE (offset == 0))
818  snat_ipfix_header_create (frm, b0, &offset);
819 
820  if (PREDICT_TRUE (do_flush == 0))
821  {
822  u64 time_stamp = clib_host_to_net_u64 (now);
823  clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
824  offset += sizeof (time_stamp);
825 
826  clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
827  offset += sizeof (nat_event);
828 
829  clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
830  offset += sizeof (quota_event);
831 
832  clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
833  offset += sizeof (limit);
834 
835  clib_memcpy_fast (b0->data + offset, &src_ip, sizeof (src_ip));
836  offset += sizeof (src_ip);
837 
839  }
840 
841  if (PREDICT_FALSE
842  (do_flush || (offset + MAX_ENTRIES_PER_USER_LEN) > frm->path_mtu))
843  {
844  template_id = clib_atomic_fetch_or (
846  0);
847  snat_ipfix_send (thread_index, frm, f, b0, template_id);
848  sitd->max_entries_per_user_frame = 0;
849  sitd->max_entries_per_user_buffer = 0;
850  offset = 0;
851  }
853 }
854 
855 static void
856 nat_ipfix_logging_max_ses (u32 thread_index, u32 limit, int do_flush)
857 {
859  snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
861  vlib_frame_t *f;
862  vlib_buffer_t *b0 = 0;
863  u32 bi0 = ~0;
864  u32 offset;
865  vlib_main_t *vm = vlib_mains[thread_index];
866  u64 now;
867  u8 nat_event = QUOTA_EXCEEDED;
868  u32 quota_event = MAX_SESSION_ENTRIES;
869  u16 template_id;
870 
871  now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
872  now += silm->milisecond_time_0;
873 
874  b0 = sitd->max_sessions_buffer;
875 
876  if (PREDICT_FALSE (b0 == 0))
877  {
878  if (do_flush)
879  return;
880 
881  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
882  {
883  nat_elog_err ("can't allocate buffer for NAT IPFIX event");
884  return;
885  }
886 
887  b0 = sitd->max_sessions_buffer = vlib_get_buffer (vm, bi0);
889  offset = 0;
890  }
891  else
892  {
893  bi0 = vlib_get_buffer_index (vm, b0);
894  offset = sitd->max_sessions_next_record_offset;
895  }
896 
897  f = sitd->max_sessions_frame;
898  if (PREDICT_FALSE (f == 0))
899  {
900  u32 *to_next;
901  f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
902  sitd->max_sessions_frame = f;
903  to_next = vlib_frame_vector_args (f);
904  to_next[0] = bi0;
905  f->n_vectors = 1;
906  }
907 
908  if (PREDICT_FALSE (offset == 0))
909  snat_ipfix_header_create (frm, b0, &offset);
910 
911  if (PREDICT_TRUE (do_flush == 0))
912  {
913  u64 time_stamp = clib_host_to_net_u64 (now);
914  clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
915  offset += sizeof (time_stamp);
916 
917  clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
918  offset += sizeof (nat_event);
919 
920  clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
921  offset += sizeof (quota_event);
922 
923  clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
924  offset += sizeof (limit);
925 
927  }
928 
929  if (PREDICT_FALSE
930  (do_flush || (offset + MAX_SESSIONS_LEN) > frm->path_mtu))
931  {
932  template_id = clib_atomic_fetch_or (
934  0);
935  snat_ipfix_send (thread_index, frm, f, b0, template_id);
936  sitd->max_sessions_frame = 0;
937  sitd->max_sessions_buffer = 0;
938  offset = 0;
939  }
941 }
942 
943 static void
944 nat_ipfix_logging_max_bib (u32 thread_index, u32 limit, int do_flush)
945 {
947  snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
949  vlib_frame_t *f;
950  vlib_buffer_t *b0 = 0;
951  u32 bi0 = ~0;
952  u32 offset;
953  vlib_main_t *vm = vlib_mains[thread_index];
954  u64 now;
955  u8 nat_event = QUOTA_EXCEEDED;
956  u32 quota_event = MAX_BIB_ENTRIES;
957  u16 template_id;
958 
959  now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
960  now += silm->milisecond_time_0;
961 
962  b0 = sitd->max_bibs_buffer;
963 
964  if (PREDICT_FALSE (b0 == 0))
965  {
966  if (do_flush)
967  return;
968 
969  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
970  {
971  nat_elog_err ("can't allocate buffer for NAT IPFIX event");
972  return;
973  }
974 
975  b0 = sitd->max_bibs_buffer = vlib_get_buffer (vm, bi0);
977  offset = 0;
978  }
979  else
980  {
981  bi0 = vlib_get_buffer_index (vm, b0);
982  offset = sitd->max_bibs_next_record_offset;
983  }
984 
985  f = sitd->max_bibs_frame;
986  if (PREDICT_FALSE (f == 0))
987  {
988  u32 *to_next;
989  f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
990  sitd->max_bibs_frame = f;
991  to_next = vlib_frame_vector_args (f);
992  to_next[0] = bi0;
993  f->n_vectors = 1;
994  }
995 
996  if (PREDICT_FALSE (offset == 0))
997  snat_ipfix_header_create (frm, b0, &offset);
998 
999  if (PREDICT_TRUE (do_flush == 0))
1000  {
1001  u64 time_stamp = clib_host_to_net_u64 (now);
1002  clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1003  offset += sizeof (time_stamp);
1004 
1005  clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1006  offset += sizeof (nat_event);
1007 
1008  clib_memcpy_fast (b0->data + offset, &quota_event, sizeof (quota_event));
1009  offset += sizeof (quota_event);
1010 
1011  clib_memcpy_fast (b0->data + offset, &limit, sizeof (limit));
1012  offset += sizeof (limit);
1013 
1015  }
1016 
1017  if (PREDICT_FALSE
1018  (do_flush || (offset + MAX_BIBS_LEN) > frm->path_mtu))
1019  {
1020  template_id = clib_atomic_fetch_or (
1021  &silm->max_bibs_template_id,
1022  0);
1023  snat_ipfix_send (thread_index, frm, f, b0, template_id);
1024  sitd->max_bibs_frame = 0;
1025  sitd->max_bibs_buffer = 0;
1026  offset = 0;
1027  }
1029 }
1030 
1031 static void
1032 nat_ipfix_logging_nat64_bibe (u32 thread_index, u8 nat_event,
1033  ip6_address_t * src_ip, u32 nat_src_ip,
1034  u8 proto, u16 src_port, u16 nat_src_port,
1035  u32 vrf_id, int do_flush)
1036 {
1038  snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1040  vlib_frame_t *f;
1041  vlib_buffer_t *b0 = 0;
1042  u32 bi0 = ~0;
1043  u32 offset;
1044  vlib_main_t *vm = vlib_mains[thread_index];
1045  u64 now;
1046  u16 template_id;
1047 
1048  now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1049  now += silm->milisecond_time_0;
1050 
1051  b0 = sitd->nat64_bib_buffer;
1052 
1053  if (PREDICT_FALSE (b0 == 0))
1054  {
1055  if (do_flush)
1056  return;
1057 
1058  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1059  {
1060  nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1061  return;
1062  }
1063 
1064  b0 = sitd->nat64_bib_buffer = vlib_get_buffer (vm, bi0);
1066  offset = 0;
1067  }
1068  else
1069  {
1070  bi0 = vlib_get_buffer_index (vm, b0);
1071  offset = sitd->nat64_bib_next_record_offset;
1072  }
1073 
1074  f = sitd->nat64_bib_frame;
1075  if (PREDICT_FALSE (f == 0))
1076  {
1077  u32 *to_next;
1078  f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1079  sitd->nat64_bib_frame = f;
1080  to_next = vlib_frame_vector_args (f);
1081  to_next[0] = bi0;
1082  f->n_vectors = 1;
1083  }
1084 
1085  if (PREDICT_FALSE (offset == 0))
1086  snat_ipfix_header_create (frm, b0, &offset);
1087 
1088  if (PREDICT_TRUE (do_flush == 0))
1089  {
1090  u64 time_stamp = clib_host_to_net_u64 (now);
1091  clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1092  offset += sizeof (time_stamp);
1093 
1094  clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1095  offset += sizeof (nat_event);
1096 
1097  clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1098  offset += sizeof (ip6_address_t);
1099 
1100  clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1101  offset += sizeof (nat_src_ip);
1102 
1103  clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1104  offset += sizeof (proto);
1105 
1106  clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1107  offset += sizeof (src_port);
1108 
1109  clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1110  offset += sizeof (nat_src_port);
1111 
1112  clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1113  offset += sizeof (vrf_id);
1114 
1116  }
1117 
1118  if (PREDICT_FALSE
1119  (do_flush || (offset + NAT64_BIB_LEN) > frm->path_mtu))
1120  {
1121  template_id = clib_atomic_fetch_or (
1122  &silm->nat64_bib_template_id,
1123  0);
1124  snat_ipfix_send (thread_index, frm, f, b0, template_id);
1125  sitd->nat64_bib_frame = 0;
1126  sitd->nat64_bib_buffer = 0;
1127  offset = 0;
1128  }
1130 }
1131 
1132 static void
1133 nat_ipfix_logging_nat64_ses (u32 thread_index, u8 nat_event,
1134  ip6_address_t * src_ip, u32 nat_src_ip,
1135  u8 proto, u16 src_port, u16 nat_src_port,
1136  ip6_address_t * dst_ip, u32 nat_dst_ip,
1137  u16 dst_port, u16 nat_dst_port,
1138  u32 vrf_id, int do_flush)
1139 {
1141  snat_ipfix_per_thread_data_t *sitd = &silm->per_thread_data[thread_index];
1143  vlib_frame_t *f;
1144  vlib_buffer_t *b0 = 0;
1145  u32 bi0 = ~0;
1146  u32 offset;
1147  vlib_main_t *vm = vlib_mains[thread_index];
1148  u64 now;
1149  u16 template_id;
1150 
1151  now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
1152  now += silm->milisecond_time_0;
1153 
1154  b0 = sitd->nat64_ses_buffer;
1155 
1156  if (PREDICT_FALSE (b0 == 0))
1157  {
1158  if (do_flush)
1159  return;
1160 
1161  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
1162  {
1163  nat_elog_err ("can't allocate buffer for NAT IPFIX event");
1164  return;
1165  }
1166 
1167  b0 = sitd->nat64_ses_buffer = vlib_get_buffer (vm, bi0);
1169  offset = 0;
1170  }
1171  else
1172  {
1173  bi0 = vlib_get_buffer_index (vm, b0);
1174  offset = sitd->nat64_ses_next_record_offset;
1175  }
1176 
1177  f = sitd->nat64_ses_frame;
1178  if (PREDICT_FALSE (f == 0))
1179  {
1180  u32 *to_next;
1181  f = vlib_get_frame_to_node (vm, ip4_lookup_node.index);
1182  sitd->nat64_ses_frame = f;
1183  to_next = vlib_frame_vector_args (f);
1184  to_next[0] = bi0;
1185  f->n_vectors = 1;
1186  }
1187 
1188  if (PREDICT_FALSE (offset == 0))
1189  snat_ipfix_header_create (frm, b0, &offset);
1190 
1191  if (PREDICT_TRUE (do_flush == 0))
1192  {
1193  u64 time_stamp = clib_host_to_net_u64 (now);
1194  clib_memcpy_fast (b0->data + offset, &time_stamp, sizeof (time_stamp));
1195  offset += sizeof (time_stamp);
1196 
1197  clib_memcpy_fast (b0->data + offset, &nat_event, sizeof (nat_event));
1198  offset += sizeof (nat_event);
1199 
1200  clib_memcpy_fast (b0->data + offset, src_ip, sizeof (ip6_address_t));
1201  offset += sizeof (ip6_address_t);
1202 
1203  clib_memcpy_fast (b0->data + offset, &nat_src_ip, sizeof (nat_src_ip));
1204  offset += sizeof (nat_src_ip);
1205 
1206  clib_memcpy_fast (b0->data + offset, &proto, sizeof (proto));
1207  offset += sizeof (proto);
1208 
1209  clib_memcpy_fast (b0->data + offset, &src_port, sizeof (src_port));
1210  offset += sizeof (src_port);
1211 
1212  clib_memcpy_fast (b0->data + offset, &nat_src_port, sizeof (nat_src_port));
1213  offset += sizeof (nat_src_port);
1214 
1215  clib_memcpy_fast (b0->data + offset, dst_ip, sizeof (ip6_address_t));
1216  offset += sizeof (ip6_address_t);
1217 
1218  clib_memcpy_fast (b0->data + offset, &nat_dst_ip, sizeof (nat_dst_ip));
1219  offset += sizeof (nat_dst_ip);
1220 
1221  clib_memcpy_fast (b0->data + offset, &dst_port, sizeof (dst_port));
1222  offset += sizeof (dst_port);
1223 
1224  clib_memcpy_fast (b0->data + offset, &nat_dst_port, sizeof (nat_dst_port));
1225  offset += sizeof (nat_dst_port);
1226 
1227  clib_memcpy_fast (b0->data + offset, &vrf_id, sizeof (vrf_id));
1228  offset += sizeof (vrf_id);
1229 
1231  }
1232 
1233  if (PREDICT_FALSE
1234  (do_flush || (offset + NAT64_SES_LEN) > frm->path_mtu))
1235  {
1236  template_id = clib_atomic_fetch_or (
1237  &silm->nat64_ses_template_id,
1238  0);
1239  snat_ipfix_send (thread_index, frm, f, b0, template_id);
1240  sitd->nat64_ses_frame = 0;
1241  sitd->nat64_ses_buffer = 0;
1242  offset = 0;
1243  }
1245 }
1246 
1247 void
1248 snat_ipfix_flush (u32 thread_index)
1249 {
1250  int do_flush = 1;
1251 
1252  snat_ipfix_logging_nat44_ses (thread_index,
1253  0, 0, 0, 0, 0, 0, 0, do_flush);
1254  snat_ipfix_logging_addr_exhausted (thread_index, 0, do_flush);
1255  snat_ipfix_logging_max_entries_per_usr (thread_index, 0, 0, do_flush);
1256  nat_ipfix_logging_max_ses (thread_index, 0, do_flush);
1257  nat_ipfix_logging_max_bib (thread_index, 0, do_flush);
1258  nat_ipfix_logging_nat64_bibe (thread_index,
1259  0, 0, 0, 0, 0, 0, 0, do_flush);
1260  nat_ipfix_logging_nat64_ses (thread_index,
1261  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, do_flush);
1262 }
1263 
1264 void
1266 {
1268  vlib_main_t *worker_vm;
1269  int i;
1270 
1271  if (PREDICT_TRUE (!clib_atomic_fetch_or(&silm->enabled, 0)))
1272  return;
1273 
1274  if (PREDICT_FALSE (!silm->worker_vms))
1275  {
1276  for (i = 1; i < vec_len (vlib_mains); i++)
1277  {
1278  worker_vm = vlib_mains[i];
1279  if (worker_vm)
1280  vec_add1 (silm->worker_vms, worker_vm);
1281  }
1282  }
1283 
1284  /* Trigger flush for each worker thread */
1285  for (i = 0; i < vec_len (silm->worker_vms); i++)
1286  {
1287  worker_vm = silm->worker_vms[i];
1288  if (worker_vm)
1290  snat_ipfix_flush_node.index);
1291  }
1292 
1293  /* Finally flush main thread */
1294  snat_ipfix_flush (0);
1295 }
1296 
1297 /**
1298  * @brief Generate NAT44 session create event
1299  *
1300  * @param thread_index thread index
1301  * @param src_ip source IPv4 address
1302  * @param nat_src_ip transaltes source IPv4 address
1303  * @param nat_proto NAT transport protocol
1304  * @param src_port source port
1305  * @param nat_src_port translated source port
1306  * @param vrf_id VRF ID
1307  */
1308 void
1310  u32 src_ip,
1311  u32 nat_src_ip,
1312  nat_protocol_t nat_proto,
1313  u16 src_port,
1314  u16 nat_src_port, u32 vrf_id)
1315 {
1316  skip_if_disabled ();
1317 
1318  snat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_CREATE, src_ip,
1319  nat_src_ip, nat_proto, src_port, nat_src_port,
1320  vrf_id, 0);
1321 }
1322 
1323 /**
1324  * @brief Generate NAT44 session delete event
1325  *
1326  * @param thread_index thread index
1327  * @param src_ip source IPv4 address
1328  * @param nat_src_ip transaltes source IPv4 address
1329  * @param nat_proto NAT transport protocol
1330  * @param src_port source port
1331  * @param nat_src_port translated source port
1332  * @param vrf_id VRF ID
1333  */
1334 void
1336  u32 src_ip,
1337  u32 nat_src_ip,
1338  nat_protocol_t nat_proto,
1339  u16 src_port,
1340  u16 nat_src_port, u32 vrf_id)
1341 {
1342  skip_if_disabled ();
1343 
1344  snat_ipfix_logging_nat44_ses (thread_index, NAT44_SESSION_DELETE, src_ip,
1345  nat_src_ip, nat_proto, src_port, nat_src_port,
1346  vrf_id, 0);
1347 }
1348 
1349 /**
1350  * @brief Generate NAT addresses exhausted event
1351  *
1352  * @param thread_index thread index
1353  * @param pool_id NAT pool ID
1354  */
1355 void
1357 {
1358  //TODO: This event SHOULD be rate limited
1359  skip_if_disabled ();
1360 
1361  snat_ipfix_logging_addr_exhausted (thread_index, pool_id, 0);
1362 }
1363 
1364 /**
1365  * @brief Generate maximum entries per user exceeded event
1366  *
1367  * @param thread_index thread index
1368  * @param limit maximum NAT entries that can be created per user
1369  * @param src_ip source IPv4 address
1370  */
1371 void
1373 {
1374  //TODO: This event SHOULD be rate limited
1375  skip_if_disabled ();
1376 
1377  snat_ipfix_logging_max_entries_per_usr (thread_index, limit, src_ip, 0);
1378 }
1379 
1380 vlib_frame_t *
1383  flow_report_t * fr,
1384  vlib_frame_t * f,
1385  u32 * to_next, u32 node_index)
1386 {
1388 
1389  return f;
1390 }
1391 
1392 /**
1393  * @brief Generate maximum session entries exceeded event
1394  *
1395  * @param thread_index thread index
1396  * @param limit configured limit
1397  */
1398 void
1400 {
1401  //TODO: This event SHOULD be rate limited
1402  skip_if_disabled ();
1403 
1404  nat_ipfix_logging_max_ses (thread_index, limit, 0);
1405 }
1406 
1407 /**
1408  * @brief Generate maximum BIB entries exceeded event
1409  *
1410  * @param thread_index thread index
1411  * @param limit configured limit
1412  */
1413 void
1414 nat_ipfix_logging_max_bibs (u32 thread_index, u32 limit)
1415 {
1416  //TODO: This event SHOULD be rate limited
1417  skip_if_disabled ();
1418 
1419  nat_ipfix_logging_max_bib (thread_index, limit, 0);
1420 }
1421 
1422 /**
1423  * @brief Generate NAT64 BIB create and delete events
1424  *
1425  * @param thread_index thread index
1426  * @param src_ip source IPv6 address
1427  * @param nat_src_ip transaltes source IPv4 address
1428  * @param proto L4 protocol
1429  * @param src_port source port
1430  * @param nat_src_port translated source port
1431  * @param vrf_id VRF ID
1432  * @param is_create non-zero value if create event otherwise delete event
1433  */
1434 void
1435 nat_ipfix_logging_nat64_bib (u32 thread_index, ip6_address_t * src_ip,
1436  ip4_address_t * nat_src_ip, u8 proto,
1437  u16 src_port, u16 nat_src_port, u32 vrf_id,
1438  u8 is_create)
1439 {
1440  u8 nat_event;
1441 
1442  skip_if_disabled ();
1443 
1444  nat_event = is_create ? NAT64_BIB_CREATE : NAT64_BIB_DELETE;
1445 
1446  nat_ipfix_logging_nat64_bibe (thread_index, nat_event, src_ip,
1447  nat_src_ip->as_u32, proto, src_port,
1448  nat_src_port, vrf_id, 0);
1449 }
1450 
1451 /**
1452  * @brief Generate NAT64 session create and delete events
1453  *
1454  * @param thread_index thread index
1455  * @param src_ip source IPv6 address
1456  * @param nat_src_ip transaltes source IPv4 address
1457  * @param proto L4 protocol
1458  * @param src_port source port
1459  * @param nat_src_port translated source port
1460  * @param dst_ip destination IPv6 address
1461  * @param nat_dst_ip destination IPv4 address
1462  * @param dst_port destination port
1463  * @param nat_dst_port translated destination port
1464  * @param vrf_id VRF ID
1465  * @param is_create non-zero value if create event otherwise delete event
1466  */
1467 void
1469  ip6_address_t * src_ip,
1470  ip4_address_t * nat_src_ip, u8 proto,
1471  u16 src_port, u16 nat_src_port,
1472  ip6_address_t * dst_ip,
1473  ip4_address_t * nat_dst_ip, u16 dst_port,
1474  u16 nat_dst_port, u32 vrf_id, u8 is_create)
1475 {
1476  u8 nat_event;
1477 
1478  skip_if_disabled ();
1479 
1480  nat_event = is_create ? NAT64_SESSION_CREATE : NAT64_SESSION_DELETE;
1481 
1482  nat_ipfix_logging_nat64_ses (thread_index, nat_event, src_ip,
1483  nat_src_ip->as_u32, proto, src_port,
1484  nat_src_port, dst_ip, nat_dst_ip->as_u32,
1485  dst_port, nat_dst_port, vrf_id, 0);
1486 }
1487 
1488 vlib_frame_t *
1490  vlib_frame_t * f, u32 * to_next, u32 node_index)
1491 {
1493 
1494  if (PREDICT_FALSE (++silm->call_counter >= vec_len (frm->reports)))
1495  {
1497  silm->call_counter = 0;
1498  }
1499 
1500  return f;
1501 }
1502 
1503 /**
1504  * @brief Enable/disable NAT plugin IPFIX logging
1505  *
1506  * @param enable 1 if enable, 0 if disable
1507  * @param domain_id observation domain ID
1508  * @param src_port source port number
1509  *
1510  * @returns 0 if success
1511  */
1512 int
1514 {
1515  snat_main_t *sm = &snat_main;
1519  int rv;
1520  u8 e = enable ? 1 : 0;
1521 
1522  if (clib_atomic_cmp_and_swap (&silm->enabled, e ^ 1, e) == e)
1523  return 0;
1524 
1525  clib_memset (&a, 0, sizeof (a));
1526  a.is_add = enable;
1527  a.domain_id = domain_id ? domain_id : 1;
1528  a.src_port = src_port ? src_port : UDP_DST_PORT_ipfix;
1530 
1531  if (sm->deterministic)
1532  {
1534 
1535  rv = vnet_flow_report_add_del (frm, &a, NULL);
1536  if (rv)
1537  {
1538  nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1539  return -1;
1540  }
1541  }
1542  else
1543  {
1545 
1546  rv = vnet_flow_report_add_del (frm, &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 
1554 
1555  rv = vnet_flow_report_add_del (frm, &a, NULL);
1556  if (rv)
1557  {
1558  nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1559  return -1;
1560  }
1561 
1563 
1564  rv = vnet_flow_report_add_del (frm, &a, NULL);
1565  if (rv)
1566  {
1567  nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1568  return -1;
1569  }
1570 
1572 
1573  rv = vnet_flow_report_add_del (frm, &a, NULL);
1574  if (rv)
1575  {
1576  nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1577  return -1;
1578  }
1579 
1581 
1582  rv = vnet_flow_report_add_del (frm, &a, NULL);
1583  if (rv)
1584  {
1585  nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1586  return -1;
1587  }
1588 
1590 
1591  rv = vnet_flow_report_add_del (frm, &a, NULL);
1592  if (rv)
1593  {
1594  nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1595  return -1;
1596  }
1597 
1598  if (sm->endpoint_dependent)
1599  {
1601 
1602  rv = vnet_flow_report_add_del (frm, &a, NULL);
1603  if (rv)
1604  {
1605  nat_elog_warn_X1 ("vnet_flow_report_add_del returned %d", "i4", rv);
1606  return -1;
1607  }
1608  }
1609  }
1610 
1611  return 0;
1612 }
1613 
1614 /**
1615  * @brief Initialize NAT plugin IPFIX logging
1616  *
1617  * @param vm vlib main
1618  */
1619 void
1621 {
1624 
1625  silm->enabled = 0;
1626  silm->worker_vms = 0;
1627  silm->call_counter = 0;
1628 
1629  /* Set up time reference pair */
1630  silm->vlib_time_0 = vlib_time_now (vm);
1631  silm->milisecond_time_0 = unix_time_now_nsec () * 1e-6;
1632 
1633  vec_validate (silm->per_thread_data, tm->n_vlib_mains - 1);
1634 }
1635 
1636 static uword
1638  vlib_node_runtime_t *rt,
1639  vlib_frame_t *f)
1640 {
1642  return 0;
1643 }
1644 
1645 /* *INDENT-OFF* */
1646 VLIB_REGISTER_NODE (snat_ipfix_flush_node) = {
1647  .function = ipfix_flush_process,
1648  .name = "snat-ipfix-flush",
1649  .type = VLIB_NODE_TYPE_INPUT,
1650  .state = VLIB_NODE_STATE_INTERRUPT,
1651 };
1652 /* *INDENT-ON* */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:507
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
void snat_ipfix_logging_max_entries_per_user(u32 thread_index, u32 limit, u32 src_ip)
Generate maximum entries per user exceeded event.
u8 * snat_template_rewrite_addr_exhausted(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)
a
Definition: bitmap.h:538
ip4_address_t src_address
Definition: ip4_packet.h:170
u8 * nat_template_rewrite_max_sessions(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)
void snat_ipfix_flush_from_main(void)
#define PREDICT_TRUE(x)
Definition: clib.h:119
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
unsigned long u64
Definition: types.h:89
static void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:197
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
static u32 ipfix_e_id_length(int e, u16 id, u16 length)
Definition: ipfix_packet.h:77
vlib_buffer_t * addr_exhausted_buffer
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:291
#define NAT44_SESSION_CREATE_FIELD_COUNT
u32 stream_index
Definition: flow_report.h:91
int vnet_flow_report_add_del(flow_report_main_t *frm, vnet_flow_report_add_del_args_t *a, u16 *template_id)
Definition: flow_report.c:334
u32 thread_index
Definition: main.h:218
u8 * nat_template_rewrite_max_bibs(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:590
vl_api_address_t src
Definition: gre.api:54
static uword ipfix_flush_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
ip4_address_t src_address
Definition: flow_report.h:119
static void nat_ipfix_logging_nat64_bibe(u32 thread_index, u8 nat_event, ip6_address_t *src_ip, u32 nat_src_ip, u8 proto, u16 src_port, u16 nat_src_port, u32 vrf_id, int do_flush)
u16 flags_and_fragment_offset
Definition: ip4_packet.h:151
u8 enabled
NAT plugin IPFIX logging enabled.
nat_protocol_t
Definition: lib.h:41
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:518
void snat_ipfix_logging_nat44_ses_create(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session create event.
#define MAX_SESSIONS_FIELD_COUNT
vlib_main_t ** vlib_mains
Definition: buffer.c:332
snat_ipfix_per_thread_data_t * per_thread_data
unsigned char u8
Definition: types.h:56
u8 deterministic
Definition: nat.h:629
ip4_address_t ipfix_collector
Definition: flow_report.h:117
double f64
Definition: types.h:142
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:104
#define NAT64_SES_LEN
u8 * snat_template_rewrite_nat44_session(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)
u16 src_port
Definition: udp.api:41
flow_report_stream_t * streams
Definition: flow_report.h:114
#define update_template_id(old_id, new_id)
vlib_frame_t * deterministic_nat_data_callback(flow_report_main_t *frm, flow_report_t *fr, vlib_frame_t *f, u32 *to_next, u32 node_index)
void nat_ipfix_logging_max_bibs(u32 thread_index, u32 limit)
Generate maximum BIB entries exceeded event.
ip4_address_t dst_address
Definition: ip4_packet.h:170
vnet_flow_rewrite_callback_t * rewrite_callback
Definition: flow_report.h:149
snat_ipfix_logging_main_t snat_ipfix_logging_main
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
#define clib_atomic_fetch_or(a, b)
Definition: atomics.h:27
void snat_ipfix_logging_init(vlib_main_t *vm)
Initialize NAT plugin IPFIX logging.
int snat_ipfix_logging_enable_disable(int enable, u32 domain_id, u16 src_port)
Enable/disable NAT plugin IPFIX logging.
#define NAT44_SESSION_CREATE_LEN
void snat_ipfix_logging_addresses_exhausted(u32 thread_index, u32 pool_id)
Generate NAT addresses exhausted event.
unsigned int u32
Definition: types.h:88
u8 * snat_template_rewrite_max_entries_per_usr(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)
static u8 * snat_template_rewrite(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, nat_event_t event, quota_exceed_event_t quota_event)
Create an IPFIX template packet rewrite string.
void nat_ipfix_logging_max_sessions(u32 thread_index, u32 limit)
Generate maximum session entries exceeded event.
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
Definition: buffer_funcs.h:293
flow_report_t * reports
Definition: flow_report.h:113
static void snat_ipfix_logging_nat44_ses(u32 thread_index, u8 nat_event, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id, int do_flush)
void snat_ipfix_flush(u32 thread_index)
static void nat_ipfix_logging_max_bib(u32 thread_index, u32 limit, int do_flush)
#define nat_elog_warn_X1(nat_elog_fmt_str, nat_elog_fmt_arg, nat_elog_val1)
Definition: nat.h:999
flow_report_main_t flow_report_main
Definition: flow_report.c:21
quota_exceed_event_t
vlib_main_t ** worker_vms
vector of worker vlib mains
vl_api_ip_proto_t proto
Definition: acl_types.api:50
vlib_frame_t * data_callback(flow_report_main_t *frm, flow_report_t *fr, vlib_frame_t *f, u32 *to_next, u32 node_index)
#define NAT_ADDRESSES_EXHAUTED_LEN
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:216
vec_header_t h
Definition: buffer.c:322
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
#define PREDICT_FALSE(x)
Definition: clib.h:118
vlib_frame_t * max_entries_per_user_frame
vl_api_address_union_t src_address
Definition: ip_types.api:99
void nat_ipfix_logging_nat64_bib(u32 thread_index, ip6_address_t *src_ip, ip4_address_t *nat_src_ip, u8 proto, u16 src_port, u16 nat_src_port, u32 vrf_id, u8 is_create)
Generate NAT64 BIB create and delete events.
static u32 version_length(u16 length)
Definition: ipfix_packet.h:33
u16 call_counter
nat data callbacks call counter
vlib_main_t * vm
Definition: in2out_ed.c:1599
#define MAX_BIBS_LEN
u64 milisecond_time_0
Time reference pair.
vlib_node_registration_t snat_ipfix_flush_node
(constructor) VLIB_REGISTER_NODE (snat_ipfix_flush_node)
snat_main_t snat_main
Definition: nat.c:41
static void nat_ipfix_logging_nat64_ses(u32 thread_index, u8 nat_event, ip6_address_t *src_ip, u32 nat_src_ip, u8 proto, u16 src_port, u16 nat_src_port, ip6_address_t *dst_ip, u32 nat_dst_ip, u16 dst_port, u16 nat_dst_port, u32 vrf_id, int do_flush)
static void snat_ipfix_logging_addr_exhausted(u32 thread_index, u32 pool_id, int do_flush)
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:399
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
vlib_buffer_t * max_entries_per_user_buffer
static u32 ipfix_id_count(u16 id, u16 count)
Definition: ipfix_packet.h:184
u8 data[]
Packet data.
Definition: buffer.h:181
static void nat_ipfix_logging_max_ses(u32 thread_index, u32 limit, int do_flush)
static u64 unix_time_now_nsec(void)
Definition: time.h:270
void nat_ipfix_logging_nat64_session(u32 thread_index, ip6_address_t *src_ip, ip4_address_t *nat_src_ip, u8 proto, u16 src_port, u16 nat_src_port, ip6_address_t *dst_ip, ip4_address_t *nat_dst_ip, u16 dst_port, u16 nat_dst_port, u32 vrf_id, u8 is_create)
Generate NAT64 session create and delete events.
u16 nat44_session_template_id
template IDs
u8 * nat_template_rewrite_nat64_session(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)
#define clib_atomic_cmp_and_swap(addr, old, new)
Definition: atomics.h:37
#define MAX_BIBS_FIELD_COUNT
#define ASSERT(truth)
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1367
vlib_frame_t * nat44_session_frame
frames containing ipfix buffers
u16 template_id
Definition: flow_report.h:90
u8 * nat_template_rewrite_nat64_bib(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)
static void snat_ipfix_send(u32 thread_index, flow_report_main_t *frm, vlib_frame_t *f, vlib_buffer_t *b0, u16 template_id)
void snat_ipfix_logging_nat44_ses_delete(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 vrf_id)
Generate NAT44 session delete event.
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#define clib_atomic_fetch_add(a, b)
Definition: atomics.h:23
vlib_buffer_t * nat44_session_buffer
ipfix buffers under construction
vl_api_address_t src_ip
Definition: udp.api:43
struct _vlib_node_registration vlib_node_registration_t
template key/value backing page structure
Definition: bihash_doc.h:44
static u32 ipfix_set_id_length(u16 set_id, u16 length)
Definition: ipfix_packet.h:121
Definition: defs.h:47
nat_event_t
#define nat_elog_err(nat_elog_str)
Definition: nat.h:990
vl_api_address_t ip
Definition: l2.api:501
#define MAX_ENTRIES_PER_USER_LEN
#define MAX_ENTRIES_PER_USER_FIELD_COUNT
u32 nat44_session_next_record_offset
next record offset
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static_always_inline u8 nat_proto_to_ip_proto(nat_protocol_t nat_proto)
Definition: inlines.h:35
static void snat_ipfix_logging_max_entries_per_usr(u32 thread_index, u32 limit, u32 src_ip, int do_flush)
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:492
VLIB buffer representation.
Definition: buffer.h:102
#define skip_if_disabled()
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
vnet_flow_data_callback_t * flow_data_callback
Definition: flow_report.h:148
struct clib_bihash_value offset
template key/value backing page structure
vl_api_address_t dst_ip
Definition: udp.api:44
#define NAT_ADDRESSES_EXHAUTED_FIELD_COUNT
#define vnet_buffer(b)
Definition: buffer.h:417
#define NAT64_SES_FIELD_COUNT
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
#define NAT64_BIB_LEN
static void snat_ipfix_header_create(flow_report_main_t *frm, vlib_buffer_t *b0, u32 *offset)
#define MAX_SESSIONS_LEN
u32 vrf_id
Definition: nat.api:856
u8 endpoint_dependent
Definition: nat.h:631
u16 dst_port
Definition: udp.api:42
u8 ip_version_and_header_length
Definition: ip4_packet.h:138
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:677
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
Definition: defs.h:46
#define NAT64_BIB_FIELD_COUNT