mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Only show unknown IPs from the last 5 minutes.
IMPORTANT: run "remove_pinned_maps.sh" before you run the new version of lqosd. The eBPF map structure has changed. 1) Add a "last_seen" value to the map_traffic eBPF map. 2) Whenever traffic is seen, update "last_seen" to equal the result of a bpf_ktime_get_boot_ns() call. 3) When retrieving the unknown IP list, perform a syscall to obtain the time since boot in nanoseconds and subtract five minutes. 4) Filter out any unknown IPs that exceed the 5 minute window. This should solve the problem with "unknown IPs" filling up on start, and gradually accumulating.
This commit is contained in:
13
src/rust/Cargo.lock
generated
13
src/rust/Cargo.lock
generated
@@ -399,17 +399,6 @@ version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "cow_struct"
|
||||
version = "0.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "780363852334e8717416de3477ac2ce707bdf91c086daae09b80f0b354b5a6b5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.5"
|
||||
@@ -1281,13 +1270,13 @@ name = "lqosd"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cow_struct",
|
||||
"env_logger",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"lqos_bus",
|
||||
"lqos_config",
|
||||
"lqos_sys",
|
||||
"nix",
|
||||
"notify",
|
||||
"parking_lot 0.12.1",
|
||||
"serde",
|
||||
|
||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
nix = "0.25"
|
||||
nix = "0"
|
||||
libbpf-sys = "1"
|
||||
anyhow = "1"
|
||||
byteorder = "1.4"
|
||||
|
||||
@@ -15,6 +15,7 @@ struct host_counter {
|
||||
__u64 download_packets;
|
||||
__u64 upload_packets;
|
||||
__u32 tc_handle;
|
||||
__u64 last_seen;
|
||||
};
|
||||
|
||||
// Pinned map storing counters per host. its an LRU structure: if it
|
||||
@@ -38,20 +39,21 @@ static __always_inline void track_traffic(
|
||||
struct host_counter * counter =
|
||||
(struct host_counter *)bpf_map_lookup_elem(&map_traffic, key);
|
||||
if (counter) {
|
||||
counter->last_seen = bpf_ktime_get_boot_ns();
|
||||
counter->tc_handle = tc_handle;
|
||||
if (direction == 1) {
|
||||
// Download
|
||||
counter->download_packets += 1;
|
||||
counter->download_bytes += size;
|
||||
counter->tc_handle = tc_handle;
|
||||
} else {
|
||||
// Upload
|
||||
counter->upload_packets += 1;
|
||||
counter->upload_bytes += size;
|
||||
counter->tc_handle = tc_handle;
|
||||
}
|
||||
} else {
|
||||
struct host_counter new_host = {0};
|
||||
new_host.tc_handle = tc_handle;
|
||||
new_host.last_seen = bpf_ktime_get_boot_ns();
|
||||
if (direction == 1) {
|
||||
new_host.download_packets = 1;
|
||||
new_host.download_bytes = size;
|
||||
|
||||
@@ -19,6 +19,9 @@ pub struct HostCounter {
|
||||
|
||||
/// Mapped TC handle, 0 if there isn't one.
|
||||
pub tc_handle: u32,
|
||||
|
||||
/// Time last seen, in nanoseconds since kernel boot
|
||||
pub last_seen: u64,
|
||||
}
|
||||
|
||||
impl Default for HostCounter {
|
||||
@@ -29,11 +32,14 @@ impl Default for HostCounter {
|
||||
upload_bytes: 0,
|
||||
upload_packets: 0,
|
||||
tc_handle: 0,
|
||||
last_seen: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Queries the underlying `map_traffic` eBPF pinned map, and returns every entry.
|
||||
pub fn get_throughput_map() -> Result<Vec<(XdpIpAddress, Vec<HostCounter>)>> {
|
||||
Ok(BpfPerCpuMap::<XdpIpAddress, HostCounter>::from_path("/sys/fs/bpf/map_traffic")?.dump_vec())
|
||||
let result = BpfPerCpuMap::<XdpIpAddress, HostCounter>::from_path("/sys/fs/bpf/map_traffic")?.dump_vec();
|
||||
//println!("{:#?}", result);
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
@@ -21,4 +21,4 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
notify = { version = "5.0.0", default-features = false, feature=["macos_kqueue"] } # Not using crossbeam because of Tokio
|
||||
env_logger = "0"
|
||||
log = "0"
|
||||
cow_struct = "0"
|
||||
nix = "0"
|
||||
|
||||
@@ -229,12 +229,21 @@ pub fn host_counts() -> BusResponse {
|
||||
}
|
||||
|
||||
pub fn all_unknown_ips() -> BusResponse {
|
||||
let boot_time = nix::time::clock_gettime(nix::time::ClockId::CLOCK_BOOTTIME)
|
||||
.expect("Unable to obtain kernel time.");
|
||||
let time_since_boot = Duration::from(boot_time);
|
||||
let five_minutes_ago = time_since_boot - Duration::from_secs(300);
|
||||
let five_minutes_ago_nanoseconds = five_minutes_ago.as_nanos();
|
||||
|
||||
let mut full_list: Vec<(XdpIpAddress, (u64, u64), (u64, u64), f32, TcHandle, u64)> = {
|
||||
let tp = THROUGHPUT_TRACKER.read();
|
||||
tp.raw_data
|
||||
.iter()
|
||||
.filter(|(ip, _)| !ip.as_ip().is_loopback())
|
||||
.filter(|(_, d)| d.tc_handle.as_u32() == 0)
|
||||
.filter(|(_, d)| {
|
||||
d.last_seen as u128 > five_minutes_ago_nanoseconds
|
||||
})
|
||||
.map(|(ip, te)| {
|
||||
(
|
||||
*ip,
|
||||
|
||||
@@ -13,6 +13,7 @@ pub(crate) struct ThroughputEntry {
|
||||
pub(crate) tc_handle: TcHandle,
|
||||
pub(crate) recent_rtt_data: [u32; 60],
|
||||
pub(crate) last_fresh_rtt_data_cycle: u64,
|
||||
pub(crate) last_seen: u64, // Last seen in kernel time since boot
|
||||
}
|
||||
|
||||
impl ThroughputEntry {
|
||||
|
||||
@@ -63,6 +63,9 @@ impl ThroughputTracker {
|
||||
if c.tc_handle != 0 {
|
||||
entry.tc_handle = TcHandle::from_u32(c.tc_handle);
|
||||
}
|
||||
if c.last_seen != 0 {
|
||||
entry.last_seen = c.last_seen;
|
||||
}
|
||||
}
|
||||
if entry.packets != entry.prev_packets {
|
||||
entry.most_recent_cycle = self.cycle;
|
||||
@@ -80,6 +83,7 @@ impl ThroughputTracker {
|
||||
tc_handle: TcHandle::zero(),
|
||||
recent_rtt_data: [0; 60],
|
||||
last_fresh_rtt_data_cycle: 0,
|
||||
last_seen: 0,
|
||||
};
|
||||
for c in counts {
|
||||
entry.bytes.0 += c.download_bytes;
|
||||
|
||||
Reference in New Issue
Block a user