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