Skip to content

Commit 279cc41

Browse files
committed
extract shared flow accounting into account_flow
1 parent 0d03250 commit 279cc41

3 files changed

Lines changed: 135 additions & 209 deletions

File tree

src/networking/ipfix/collect.rs

Lines changed: 8 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,13 @@ use crate::networking::ipfix::templates::TemplateCache;
1515
use crate::networking::ipfix::wire::{
1616
self, FlowRecord, IPFIX_VERSION, Set, decode_data_record, format_mac, parse_message,
1717
};
18-
use crate::networking::manage_packets::{
19-
get_address_to_lookup, get_traffic_type, is_local_connection, modify_or_insert_in_map,
20-
};
18+
use crate::networking::manage_packets::{account_flow, modify_or_insert_in_map};
2119
use crate::networking::parse_packets::{
2220
AddressesResolutionState, BackendTrafficMessage, REVERSE_DNS_LOOKUP_THREADS,
2321
reverse_dns_lookups,
2422
};
2523
use crate::networking::types::address_port_pair::AddressPortPair;
2624
use crate::networking::types::arp_type::ArpType;
27-
use crate::networking::types::bogon::is_bogon;
28-
use crate::networking::types::data_info::DataInfo;
29-
use crate::networking::types::data_info_host::DataInfoHost;
3025
use crate::networking::types::icmp_type::IcmpType;
3126
use crate::networking::types::info_traffic::InfoTraffic;
3227
use crate::networking::types::ip_blacklist::IpBlacklist;
@@ -268,114 +263,16 @@ fn ingest_flow_record(
268263
timestamps_hint,
269264
);
270265

271-
info_traffic_msg.tot_data_info.add_packets(
272-
exchanged_packets,
266+
account_flow(
267+
info_traffic_msg,
268+
resolutions_state,
269+
&key,
270+
exporter_addresses,
273271
exchanged_bytes,
272+
exchanged_packets,
274273
traffic_direction,
275-
Instant::now(),
274+
service,
276275
);
277-
278-
let address_to_lookup = get_address_to_lookup(&key, traffic_direction);
279-
let already_resolved = resolutions_state
280-
.addresses_resolved
281-
.contains_key(&address_to_lookup);
282-
let waiting_resolution = resolutions_state
283-
.addresses_waiting_resolution
284-
.contains_key(&address_to_lookup);
285-
286-
match (waiting_resolution, already_resolved) {
287-
(false, false) => {
288-
let mut data_info = DataInfo::default();
289-
data_info.add_packets(
290-
exchanged_packets,
291-
exchanged_bytes,
292-
traffic_direction,
293-
Instant::now(),
294-
);
295-
resolutions_state
296-
.addresses_waiting_resolution
297-
.insert(address_to_lookup, data_info);
298-
let _ = resolutions_state.lookup_request_tx.try_send((
299-
key,
300-
traffic_direction,
301-
exporter_addresses.to_vec(),
302-
));
303-
}
304-
(true, false) => {
305-
resolutions_state
306-
.addresses_waiting_resolution
307-
.entry(address_to_lookup)
308-
.and_modify(|data_info| {
309-
data_info.add_packets(
310-
exchanged_packets,
311-
exchanged_bytes,
312-
traffic_direction,
313-
Instant::now(),
314-
);
315-
});
316-
}
317-
(_, true) => {
318-
let host = resolutions_state
319-
.addresses_resolved
320-
.get(&address_to_lookup)
321-
.cloned()
322-
.unwrap_or_default();
323-
info_traffic_msg
324-
.hosts
325-
.entry(host)
326-
.and_modify(|data_info_host| {
327-
data_info_host.data_info.add_packets(
328-
exchanged_packets,
329-
exchanged_bytes,
330-
traffic_direction,
331-
Instant::now(),
332-
);
333-
})
334-
.or_insert_with(|| {
335-
let traffic_type =
336-
get_traffic_type(&address_to_lookup, exporter_addresses, traffic_direction);
337-
let is_loopback = address_to_lookup.is_loopback();
338-
let is_local = is_local_connection(&address_to_lookup, exporter_addresses);
339-
let is_bogon = is_bogon(&address_to_lookup);
340-
let mut data_info = DataInfo::default();
341-
data_info.add_packets(
342-
exchanged_packets,
343-
exchanged_bytes,
344-
traffic_direction,
345-
Instant::now(),
346-
);
347-
DataInfoHost {
348-
data_info,
349-
is_loopback,
350-
is_local,
351-
is_bogon,
352-
traffic_type,
353-
}
354-
});
355-
}
356-
}
357-
358-
info_traffic_msg
359-
.services
360-
.entry(service)
361-
.and_modify(|data_info| {
362-
data_info.add_packets(
363-
exchanged_packets,
364-
exchanged_bytes,
365-
traffic_direction,
366-
Instant::now(),
367-
);
368-
})
369-
.or_insert_with(|| {
370-
let mut data_info = DataInfo::default();
371-
data_info.add_packets(
372-
exchanged_packets,
373-
exchanged_bytes,
374-
traffic_direction,
375-
Instant::now(),
376-
);
377-
data_info
378-
});
379276
}
380277

381278
fn build_key(record: &FlowRecord) -> Option<AddressPortPair> {

src/networking/manage_packets.rs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ use etherparse::{
77
use pcap::Address;
88

99
use crate::Protocol;
10+
use crate::networking::parse_packets::AddressesResolutionState;
1011
use crate::networking::types::address_port_pair::AddressPortPair;
1112
use crate::networking::types::arp_type::ArpType;
1213
use crate::networking::types::bogon::is_bogon;
14+
use crate::networking::types::data_info::DataInfo;
15+
use crate::networking::types::data_info_host::DataInfoHost;
1316
use crate::networking::types::icmp_type::{IcmpType, IcmpTypeV4, IcmpTypeV6};
1417
use crate::networking::types::info_address_port_pair::InfoAddressPortPair;
1518
use crate::networking::types::info_traffic::InfoTraffic;
@@ -356,6 +359,119 @@ pub fn modify_or_insert_in_map(
356359
(new_info.traffic_direction, new_info.service)
357360
}
358361

362+
/// Accounts an already-classified flow against the totals, the rDNS resolution
363+
/// state, the per-host map, and the per-service map.
364+
///
365+
/// Shared by both capture backends: the pcap pipeline calls it once per packet
366+
/// (`packets` = 1), the IPFIX collector once per flow record (`packets` = the
367+
/// record's packet count).
368+
#[allow(clippy::too_many_arguments)]
369+
pub fn account_flow(
370+
info_traffic_msg: &mut InfoTraffic,
371+
resolutions_state: &mut AddressesResolutionState,
372+
key: &AddressPortPair,
373+
my_interface_addresses: &[Address],
374+
bytes: u128,
375+
packets: u128,
376+
direction: TrafficDirection,
377+
service: Service,
378+
) {
379+
let now = Instant::now();
380+
381+
info_traffic_msg
382+
.tot_data_info
383+
.add_packets(packets, bytes, direction, now);
384+
385+
// check the rDNS status of this address and act accordingly
386+
let address_to_lookup = get_address_to_lookup(key, direction);
387+
let mut r_dns_waiting_resolution = false;
388+
let r_dns_already_resolved = resolutions_state
389+
.addresses_resolved
390+
.contains_key(&address_to_lookup);
391+
if !r_dns_already_resolved {
392+
r_dns_waiting_resolution = resolutions_state
393+
.addresses_waiting_resolution
394+
.contains_key(&address_to_lookup);
395+
}
396+
397+
match (r_dns_waiting_resolution, r_dns_already_resolved) {
398+
(false, false) => {
399+
// rDNS not requested yet (first occurrence of this address to lookup)
400+
401+
// Add this address to the map of addresses waiting for a resolution
402+
// Useful to NOT perform again a rDNS lookup for this entry
403+
let mut data_info = DataInfo::default();
404+
data_info.add_packets(packets, bytes, direction, now);
405+
resolutions_state
406+
.addresses_waiting_resolution
407+
.insert(address_to_lookup, data_info);
408+
409+
// send the rDNS lookup request to the thread pool
410+
let _ = resolutions_state.lookup_request_tx.try_send((
411+
*key,
412+
direction,
413+
my_interface_addresses.to_vec(),
414+
));
415+
}
416+
(true, false) => {
417+
// waiting for a previously requested rDNS resolution
418+
// update the corresponding waiting address data
419+
resolutions_state
420+
.addresses_waiting_resolution
421+
.entry(address_to_lookup)
422+
.and_modify(|data_info| {
423+
data_info.add_packets(packets, bytes, direction, now);
424+
});
425+
}
426+
(_, true) => {
427+
// rDNS already resolved
428+
// update the corresponding host's data info
429+
let host = resolutions_state
430+
.addresses_resolved
431+
.get(&address_to_lookup)
432+
.cloned()
433+
.unwrap_or_default();
434+
info_traffic_msg
435+
.hosts
436+
.entry(host)
437+
.and_modify(|data_info_host| {
438+
data_info_host
439+
.data_info
440+
.add_packets(packets, bytes, direction, now);
441+
})
442+
.or_insert_with(|| {
443+
let traffic_type =
444+
get_traffic_type(&address_to_lookup, my_interface_addresses, direction);
445+
let is_loopback = address_to_lookup.is_loopback();
446+
let is_local = is_local_connection(&address_to_lookup, my_interface_addresses);
447+
let is_bogon = is_bogon(&address_to_lookup);
448+
let mut data_info = DataInfo::default();
449+
data_info.add_packets(packets, bytes, direction, now);
450+
DataInfoHost {
451+
data_info,
452+
is_loopback,
453+
is_local,
454+
is_bogon,
455+
traffic_type,
456+
}
457+
});
458+
}
459+
}
460+
461+
//increment the packet count for the sniffed service
462+
info_traffic_msg
463+
.services
464+
.entry(service)
465+
.and_modify(|data_info| {
466+
data_info.add_packets(packets, bytes, direction, now);
467+
})
468+
.or_insert_with(|| {
469+
let mut data_info = DataInfo::default();
470+
data_info.add_packets(packets, bytes, direction, now);
471+
data_info
472+
});
473+
}
474+
359475
/// Returns the traffic direction observed (incoming or outgoing)
360476
fn get_traffic_direction(
361477
source_ip: &IpAddr,

src/networking/parse_packets.rs

Lines changed: 11 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::mmdb::asn::get_asn;
66
use crate::mmdb::country::get_country;
77
use crate::mmdb::types::mmdb_reader::MmdbReaders;
88
use crate::networking::manage_packets::{
9-
analyze_headers, get_address_to_lookup, get_traffic_type, is_local_connection,
9+
account_flow, analyze_headers, get_address_to_lookup, get_traffic_type, is_local_connection,
1010
modify_or_insert_in_map,
1111
};
1212
use crate::networking::types::address_port_pair::AddressPortPair;
@@ -197,103 +197,16 @@ pub fn parse_packets(
197197
None,
198198
);
199199

200-
info_traffic_msg
201-
.tot_data_info
202-
.add_packet(exchanged_bytes, traffic_direction);
203-
204-
// check the rDNS status of this address and act accordingly
205-
let address_to_lookup = get_address_to_lookup(&key, traffic_direction);
206-
let mut r_dns_waiting_resolution = false;
207-
let r_dns_already_resolved = resolutions_state
208-
.addresses_resolved
209-
.contains_key(&address_to_lookup);
210-
if !r_dns_already_resolved {
211-
r_dns_waiting_resolution = resolutions_state
212-
.addresses_waiting_resolution
213-
.contains_key(&address_to_lookup);
214-
}
215-
216-
match (r_dns_waiting_resolution, r_dns_already_resolved) {
217-
(false, false) => {
218-
// rDNS not requested yet (first occurrence of this address to lookup)
219-
220-
// Add this address to the map of addresses waiting for a resolution
221-
// Useful to NOT perform again a rDNS lookup for this entry
222-
resolutions_state.addresses_waiting_resolution.insert(
223-
address_to_lookup,
224-
DataInfo::new_with_first_packet(exchanged_bytes, traffic_direction),
225-
);
226-
227-
// send the rDNS lookup request to the thread pool
228-
let _ = resolutions_state.lookup_request_tx.try_send((
229-
key,
230-
traffic_direction,
231-
cs.get_addresses().clone(),
232-
));
233-
}
234-
(true, false) => {
235-
// waiting for a previously requested rDNS resolution
236-
// update the corresponding waiting address data
237-
resolutions_state
238-
.addresses_waiting_resolution
239-
.entry(address_to_lookup)
240-
.and_modify(|data_info| {
241-
data_info.add_packet(exchanged_bytes, traffic_direction);
242-
});
243-
}
244-
(_, true) => {
245-
// rDNS already resolved
246-
// update the corresponding host's data info
247-
let host = resolutions_state
248-
.addresses_resolved
249-
.get(&address_to_lookup)
250-
.unwrap_or(&Host::default())
251-
.clone();
252-
info_traffic_msg
253-
.hosts
254-
.entry(host)
255-
.and_modify(|data_info_host| {
256-
data_info_host
257-
.data_info
258-
.add_packet(exchanged_bytes, traffic_direction);
259-
})
260-
.or_insert_with(|| {
261-
let my_interface_addresses = cs.get_addresses();
262-
let traffic_type = get_traffic_type(
263-
&address_to_lookup,
264-
my_interface_addresses,
265-
traffic_direction,
266-
);
267-
let is_loopback = address_to_lookup.is_loopback();
268-
let is_local = is_local_connection(
269-
&address_to_lookup,
270-
my_interface_addresses,
271-
);
272-
let is_bogon = is_bogon(&address_to_lookup);
273-
DataInfoHost {
274-
data_info: DataInfo::new_with_first_packet(
275-
exchanged_bytes,
276-
traffic_direction,
277-
),
278-
is_loopback,
279-
is_local,
280-
is_bogon,
281-
traffic_type,
282-
}
283-
});
284-
}
285-
}
286-
287-
//increment the packet count for the sniffed service
288-
info_traffic_msg
289-
.services
290-
.entry(service)
291-
.and_modify(|data_info| {
292-
data_info.add_packet(exchanged_bytes, traffic_direction);
293-
})
294-
.or_insert_with(|| {
295-
DataInfo::new_with_first_packet(exchanged_bytes, traffic_direction)
296-
});
200+
account_flow(
201+
&mut info_traffic_msg,
202+
&mut resolutions_state,
203+
&key,
204+
cs.get_addresses(),
205+
exchanged_bytes,
206+
1,
207+
traffic_direction,
208+
service,
209+
);
297210

298211
// update dropped packets number
299212
if let Some(stats) = cap_stats {

0 commit comments

Comments
 (0)