Add stats for frame types and source and destination addresses
This commit is contained in:
15
src/main.rs
15
src/main.rs
@@ -20,6 +20,8 @@ use std::time::SystemTime;
|
||||
|
||||
mod print_frame;
|
||||
use print_frame::PrintFrame;
|
||||
mod stats;
|
||||
use stats::Stats;
|
||||
struct KissPkt {
|
||||
timestamp: Duration,
|
||||
orig_len: u32,
|
||||
@@ -78,6 +80,8 @@ fn tnc_loop<T: Read>(tx: Sender<KissPkt>, mut stream: T) -> Result<()> {
|
||||
struct Arg {
|
||||
#[arg(short, long, default_value_t = false)]
|
||||
verbose: bool,
|
||||
#[arg(short, long, default_value_t = false)]
|
||||
stats: bool,
|
||||
#[arg(short, long, value_name = "FILE")]
|
||||
output: Option<PathBuf>,
|
||||
input: String,
|
||||
@@ -85,6 +89,10 @@ struct Arg {
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let arg = Arg::parse();
|
||||
let mut stats = match arg.stats {
|
||||
true => Some(Stats::new()),
|
||||
false => None,
|
||||
};
|
||||
let mut output = arg.output.map(|path| {
|
||||
//TODO automatically add file extension
|
||||
let file_out = File::create(path).expect("Error opening file for writing");
|
||||
@@ -119,6 +127,9 @@ fn main() -> Result<()> {
|
||||
} else {
|
||||
frame.print_short();
|
||||
}
|
||||
if let Some(stats) = stats.as_mut() {
|
||||
stats.record(&frame);
|
||||
}
|
||||
} else {
|
||||
let mut s = String::new();
|
||||
for byte in pkt.data.iter() {
|
||||
@@ -138,5 +149,9 @@ fn main() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(stats) = stats.take() {
|
||||
stats.dump();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
85
src/stats.rs
Normal file
85
src/stats.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ax25::frame::{Ax25Frame, FrameContent};
|
||||
|
||||
pub struct Stats {
|
||||
frame_types: [usize; FrameContent::MAX],
|
||||
dests: HashMap<String, usize>,
|
||||
srcs: HashMap<String, usize>,
|
||||
}
|
||||
impl Stats {
|
||||
pub fn new() -> Self {
|
||||
Stats {
|
||||
frame_types: [0; FrameContent::MAX],
|
||||
dests: HashMap::new(),
|
||||
srcs: HashMap::new(),
|
||||
}
|
||||
}
|
||||
pub fn record(&mut self, frame: &Ax25Frame) {
|
||||
self.frame_types[frame.content.get_index()] += 1;
|
||||
if let Some(n) = self.srcs.get_mut(&frame.source.callsign) {
|
||||
*n += 1;
|
||||
} else {
|
||||
self.srcs.insert(frame.source.callsign.clone(), 1);
|
||||
}
|
||||
|
||||
if let Some(n) = self.dests.get_mut(&frame.destination.callsign) {
|
||||
*n += 1;
|
||||
} else {
|
||||
self.dests.insert(frame.destination.callsign.clone(), 1);
|
||||
}
|
||||
}
|
||||
pub fn dump(mut self) {
|
||||
println!("\n---Frame type counts---");
|
||||
println!(" Info: {}", self.frame_types[0]);
|
||||
println!(" RecvRdy: {}", self.frame_types[1]);
|
||||
println!(" RecvNotRdy: {}", self.frame_types[2]);
|
||||
println!(" Reject: {}", self.frame_types[3]);
|
||||
println!(" AsyncBalMode: {}", self.frame_types[4]);
|
||||
println!(" Disconnect: {}", self.frame_types[5]);
|
||||
println!(" DisconMode: {}", self.frame_types[6]);
|
||||
println!(" UnNumAck: {}", self.frame_types[7]);
|
||||
println!(" FrameReject: {}", self.frame_types[8]);
|
||||
println!(" UnNumInfo: {}", self.frame_types[9]);
|
||||
println!(" Unknown: {}", self.frame_types[10]);
|
||||
|
||||
println!("");
|
||||
let mut top_senders: Vec<(String, usize)> = self.srcs.drain().collect();
|
||||
top_senders.sort_unstable_by_key(|x| x.1);
|
||||
println!("\n--- Top Senders ---");
|
||||
for (k, v) in top_senders.iter().rev() {
|
||||
println!("{:<10}: {v}", k);
|
||||
}
|
||||
|
||||
println!("");
|
||||
let mut top_receivers: Vec<(String, usize)> = self.dests.drain().collect();
|
||||
top_receivers.sort_unstable_by_key(|x| x.1);
|
||||
println!("\n--- Top Receivers ---");
|
||||
for (k, v) in top_receivers.iter().rev() {
|
||||
println!("{:<10}: {v}", k);
|
||||
}
|
||||
}
|
||||
}
|
||||
trait Indexable {
|
||||
const MAX: usize;
|
||||
fn get_index(&self) -> usize;
|
||||
}
|
||||
impl Indexable for FrameContent {
|
||||
const MAX: usize = 11;
|
||||
|
||||
fn get_index(&self) -> usize {
|
||||
match self {
|
||||
FrameContent::Information(_) => 0,
|
||||
FrameContent::ReceiveReady(_) => 1,
|
||||
FrameContent::ReceiveNotReady(_) => 2,
|
||||
FrameContent::Reject(_) => 3,
|
||||
FrameContent::SetAsynchronousBalancedMode(_) => 4,
|
||||
FrameContent::Disconnect(_) => 5,
|
||||
FrameContent::DisconnectedMode(_) => 6,
|
||||
FrameContent::UnnumberedAcknowledge(_) => 7,
|
||||
FrameContent::FrameReject(_) => 8,
|
||||
FrameContent::UnnumberedInformation(_) => 9,
|
||||
FrameContent::UnknownContent(_) => 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user