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