From 25801b6445ec317bb0711e41907fceeb0b1d7c6f Mon Sep 17 00:00:00 2001 From: "Herbert \"TheBracket" Date: Thu, 23 Mar 2023 13:49:36 -0500 Subject: [PATCH] Issue 291 capture time (#293) * Make packet capture time user configurable. * Add `packet_capture_time` to /etc/lqos.conf as a number (seconds) * Rework the capture logic to obtain the capture time and wait for the specified period. * Rename some functions that specified ten seconds in the name. Relates to ISSUE #291 * Remove a dangling dashboard link * Change libpcap download filename to Relates to ISSUE #291 * Pass the circuit_id to the ip_dump page. * Include the circuit_id in the downloaded packet capture filename. * Add starting timestamp to capture filename Adds the starting timestamp (in ns) to the capture filename when you download a libcap dump. Ending timestamp isn't included; the starting stamp is almost certainly unique. Relates to ISSUE #291 and fixes the parts that I intend to touch. --- src/lqos.example | 1 + src/rust/Cargo.lock | 1 + src/rust/lqos_bus/src/bus/response.rs | 7 ++++++- src/rust/lqos_config/src/etc.rs | 5 +++++ src/rust/lqos_heimdall/Cargo.toml | 1 + src/rust/lqos_heimdall/src/lib.rs | 2 +- src/rust/lqos_heimdall/src/timeline.rs | 18 +++++++++++++----- src/rust/lqos_node_manager/src/queue_info.rs | 13 ++++++++----- .../static/circuit_queue.html | 8 ++++---- src/rust/lqos_node_manager/static/ip_dump.html | 12 +++++++----- src/rust/lqosd/src/main.rs | 10 +++++----- 11 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/lqos.example b/src/lqos.example index e9a08a0e..4fb5806c 100644 --- a/src/lqos.example +++ b/src/lqos.example @@ -4,6 +4,7 @@ # Where is LibreQoS installed? lqos_directory = '/opt/libreqos/src' queue_check_period_ms = 1000 +packet_capture_time = 10 # Number of seconds to capture packets in an analysis session [usage_stats] send_anonymous = true diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index f2d334c8..5d681b67 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -1436,6 +1436,7 @@ dependencies = [ "dashmap", "log", "lqos_bus", + "lqos_config", "lqos_sys", "lqos_utils", "once_cell", diff --git a/src/rust/lqos_bus/src/bus/response.rs b/src/rust/lqos_bus/src/bus/response.rs index 9da91fa3..5c416b80 100644 --- a/src/rust/lqos_bus/src/bus/response.rs +++ b/src/rust/lqos_bus/src/bus/response.rs @@ -91,7 +91,12 @@ pub enum BusResponse { FlowData(Vec<(FlowTransport, Option)>), /// The index of the new packet collection session - PacketCollectionSession(usize), + PacketCollectionSession{ + /// The identifier of the capture session + session_id: usize, + /// Number of seconds for which data will be captured + countdown: usize + }, /// Packet header dump PacketDump(Option>), diff --git a/src/rust/lqos_config/src/etc.rs b/src/rust/lqos_config/src/etc.rs index 281ae179..83090d70 100644 --- a/src/rust/lqos_config/src/etc.rs +++ b/src/rust/lqos_config/src/etc.rs @@ -30,6 +30,11 @@ pub struct EtcLqos { /// If present, defined anonymous usage stat sending pub usage_stats: Option, + + /// Defines for how many seconds a libpcap compatible capture should + /// run. Short times are good, there's a real performance penalty to + /// capturing high-throughput streams. Defaults to 10 seconds. + pub packet_capture_time: Option, } /// Represents a set of `sysctl` and `ethtool` tweaks that may be diff --git a/src/rust/lqos_heimdall/Cargo.toml b/src/rust/lqos_heimdall/Cargo.toml index 925edb9f..a173525c 100644 --- a/src/rust/lqos_heimdall/Cargo.toml +++ b/src/rust/lqos_heimdall/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-2.0-only" lqos_utils = { path = "../lqos_utils" } lqos_bus = { path = "../lqos_bus" } lqos_sys = { path = "../lqos_sys" } +lqos_config = { path = "../lqos_config" } log = "0" zerocopy = {version = "0.6.1", features = [ "simd" ] } once_cell = "1.17.1" diff --git a/src/rust/lqos_heimdall/src/lib.rs b/src/rust/lqos_heimdall/src/lib.rs index b8a3e71d..267af1f8 100644 --- a/src/rust/lqos_heimdall/src/lib.rs +++ b/src/rust/lqos_heimdall/src/lib.rs @@ -9,7 +9,7 @@ pub use config::{HeimdalConfig, HeimdallMode}; mod flows; pub use flows::{expire_heimdall_flows, get_flow_stats}; mod timeline; -pub use timeline::{ten_second_packet_dump, ten_second_pcap, hyperfocus_on_target}; +pub use timeline::{n_second_packet_dump, n_second_pcap, hyperfocus_on_target}; mod pcap; mod watchlist; use lqos_utils::fdtimer::periodic; diff --git a/src/rust/lqos_heimdall/src/timeline.rs b/src/rust/lqos_heimdall/src/timeline.rs index 8f4fbc58..1be06db6 100644 --- a/src/rust/lqos_heimdall/src/timeline.rs +++ b/src/rust/lqos_heimdall/src/timeline.rs @@ -7,6 +7,7 @@ use crate::{ }; use dashmap::{DashMap, DashSet}; use lqos_bus::{tos_parser, PacketHeader}; +use lqos_config::EtcLqos; use lqos_utils::{unix_time::time_since_boot, XdpIpAddress}; use once_cell::sync::Lazy; use std::{ @@ -99,7 +100,7 @@ static FOCUS_SESSIONS: Lazy> = /// /// * Either `None` or... /// * The id number of the collection session for analysis. -pub fn hyperfocus_on_target(ip: XdpIpAddress) -> Option { +pub fn hyperfocus_on_target(ip: XdpIpAddress) -> Option<(usize, usize)> { if HYPERFOCUSED.compare_exchange( false, true, @@ -107,10 +108,17 @@ pub fn hyperfocus_on_target(ip: XdpIpAddress) -> Option { std::sync::atomic::Ordering::Relaxed, ) == Ok(false) { + // If explicitly set, obtain the capture time. Otherwise, default to + // a reasonable 10 seconds. + let capture_time = if let Ok(cfg) = EtcLqos::load() { + cfg.packet_capture_time.unwrap_or(10) + } else { + 10 + }; let new_id = FOCUS_SESSION_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed); std::thread::spawn(move || { - for _ in 0..10 { + for _ in 0..capture_time { let _ = set_heimdall_mode(HeimdallMode::Analysis); heimdall_watch_ip(ip); std::thread::sleep(Duration::from_secs(1)); @@ -133,7 +141,7 @@ pub fn hyperfocus_on_target(ip: XdpIpAddress) -> Option { HYPERFOCUSED.store(false, std::sync::atomic::Ordering::Relaxed); }); - Some(new_id) + Some((new_id, capture_time)) } else { log::warn!( "Heimdall was busy and won't start another collection session." @@ -142,7 +150,7 @@ pub fn hyperfocus_on_target(ip: XdpIpAddress) -> Option { } } -pub fn ten_second_packet_dump(session_id: usize) -> Option> { +pub fn n_second_packet_dump(session_id: usize) -> Option> { if let Some(session) = FOCUS_SESSIONS.get(&session_id) { Some(session.data.iter().map(|e| e.as_header()).collect()) } else { @@ -150,7 +158,7 @@ pub fn ten_second_packet_dump(session_id: usize) -> Option> { } } -pub fn ten_second_pcap(session_id: usize) -> Option { +pub fn n_second_pcap(session_id: usize) -> Option { if let Some(mut session) = FOCUS_SESSIONS.get_mut(&session_id) { let filename = format!("/tmp/cap_sess_{session_id}"); session.dump_filename = Some(filename.clone()); diff --git a/src/rust/lqos_node_manager/src/queue_info.rs b/src/rust/lqos_node_manager/src/queue_info.rs index 0178e8ec..57e195a9 100644 --- a/src/rust/lqos_node_manager/src/queue_info.rs +++ b/src/rust/lqos_node_manager/src/queue_info.rs @@ -118,14 +118,14 @@ pub async fn flow_stats(ip_list: String, _auth: AuthGuard) -> NoCache")] pub async fn request_analysis(ip: String) -> NoCache> { for r in bus_request(vec![BusRequest::GatherPacketData(ip)]).await.unwrap() { - if let BusResponse::PacketCollectionSession(id) = r { - return NoCache::new(Json(RequestAnalysisResult::Ok(id))); + if let BusResponse::PacketCollectionSession{session_id, countdown} = r { + return NoCache::new(Json(RequestAnalysisResult::Ok{session_id, countdown})); } } @@ -143,8 +143,11 @@ pub async fn packet_dump(id: usize, _auth: AuthGuard) -> NoCache/capture.pcap")] -pub async fn pcap(id: usize) -> Result, Status> { +#[allow(unused_variables)] +#[get("/api/pcap//")] +pub async fn pcap(id: usize, filename: String) -> Result, Status> { + // The unusued _filename parameter is there to allow the changing of the + // filename on the client side. See Github issue 291. for r in bus_request(vec![BusRequest::GetPcapDump(id)]).await.unwrap() { if let BusResponse::PcapDump(Some(filename)) = r { return Ok(NoCache::new(NamedFile::open(filename).await.unwrap())); diff --git a/src/rust/lqos_node_manager/static/circuit_queue.html b/src/rust/lqos_node_manager/static/circuit_queue.html index eea791c7..6d0e3143 100644 --- a/src/rust/lqos_node_manager/static/circuit_queue.html +++ b/src/rust/lqos_node_manager/static/circuit_queue.html @@ -195,7 +195,7 @@
Flows (Last 30 Seconds)
@@ -595,9 +595,9 @@ alert("Heimdall is busy serving other customers. Your desire is important to him, please try again later.") return; } - analysisId = data.Ok; + analysisId = data.Ok.session_id; analysisBtn = "#dumpBtn_" + id; - analysisTimer = 10; + analysisTimer = data.Ok.countdown; analyzeTick(); }); } @@ -608,7 +608,7 @@ if (analysisTimer > -1) { setTimeout(analyzeTick, 1000); } else { - window.location.href = "/ip_dump?id=" + analysisId; + window.location.href = "/ip_dump?id=" + analysisId + "&circuit_id=" + encodeURI(id); } } diff --git a/src/rust/lqos_node_manager/static/ip_dump.html b/src/rust/lqos_node_manager/static/ip_dump.html index 9c6cc9b0..4360e992 100644 --- a/src/rust/lqos_node_manager/static/ip_dump.html +++ b/src/rust/lqos_node_manager/static/ip_dump.html @@ -22,9 +22,6 @@