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