#[cfg(feature = "statistics")]
use embassy_time::Instant;
#[cfg(feature = "statistics")]
use portable_atomic::{AtomicU32, AtomicU64, Ordering};
#[cfg(all(feature = "statistics", not(feature = "esp32c5")))]
use portable_atomic::AtomicBool;
#[cfg(feature = "statistics")]
use crate::logging::logging::reset_global_log_drops;
#[cfg(all(feature = "statistics", not(feature = "esp32c5")))]
pub(crate) const MAX_TRACKED_PEERS: usize = 16;
#[cfg(feature = "statistics")]
pub(crate) struct GlobalStats {
pub tx_count: AtomicU64,
pub rx_count: AtomicU64,
pub rx_drop_count: AtomicU32,
pub capture_start_time: AtomicU64,
pub tx_rate_hz: AtomicU32,
pub rx_rate_hz: AtomicU32,
}
#[cfg(feature = "statistics")]
pub(crate) static STATS: GlobalStats = GlobalStats {
tx_count: AtomicU64::new(0),
rx_count: AtomicU64::new(0),
rx_drop_count: AtomicU32::new(0),
capture_start_time: AtomicU64::new(0),
tx_rate_hz: AtomicU32::new(0),
rx_rate_hz: AtomicU32::new(0),
};
#[cfg(all(feature = "statistics", not(feature = "esp32c5")))]
pub(crate) static RESET_SEQ_TRACKER: AtomicBool = AtomicBool::new(false);
#[cfg(all(feature = "statistics", not(feature = "esp32c5")))]
static SEQ_DROP_DETECTION_ENABLED: AtomicBool = AtomicBool::new(false);
pub(crate) fn set_seq_drop_detection(enabled: bool) {
#[cfg(all(feature = "statistics", not(feature = "esp32c5")))]
{
SEQ_DROP_DETECTION_ENABLED.store(enabled, Ordering::Relaxed);
}
#[cfg(not(all(feature = "statistics", not(feature = "esp32c5"))))]
{
let _ = enabled;
}
}
#[cfg(all(feature = "statistics", not(feature = "esp32c5")))]
pub(crate) fn seq_drop_detection_enabled() -> bool {
SEQ_DROP_DETECTION_ENABLED.load(Ordering::Relaxed)
}
pub(crate) fn reset() {
#[cfg(feature = "statistics")]
{
STATS.tx_count.store(0, Ordering::Relaxed);
STATS.rx_count.store(0, Ordering::Relaxed);
STATS.rx_drop_count.store(0, Ordering::Relaxed);
STATS.tx_rate_hz.store(0, Ordering::Relaxed);
STATS.rx_rate_hz.store(0, Ordering::Relaxed);
reset_global_log_drops();
}
}
#[cfg(feature = "statistics")]
pub fn get_total_rx_packets() -> u64 {
STATS.rx_count.load(Ordering::Relaxed)
}
#[cfg(feature = "statistics")]
pub fn get_total_tx_packets() -> u64 {
STATS.tx_count.load(Ordering::Relaxed)
}
#[cfg(feature = "statistics")]
pub fn get_rx_rate_hz() -> u32 {
STATS.rx_rate_hz.load(Ordering::Relaxed)
}
#[cfg(feature = "statistics")]
pub fn get_tx_rate_hz() -> u32 {
STATS.tx_rate_hz.load(Ordering::Relaxed)
}
#[cfg(feature = "statistics")]
pub fn get_pps_rx() -> u64 {
let start_time = Instant::from_ticks(STATS.capture_start_time.load(Ordering::Relaxed));
let elapsed_secs = start_time.elapsed().as_secs();
let total_packets = STATS.rx_count.load(Ordering::Relaxed);
if elapsed_secs == 0 {
return total_packets;
}
total_packets / elapsed_secs
}
#[cfg(feature = "statistics")]
pub fn get_pps_tx() -> u64 {
let start_time = Instant::from_ticks(STATS.capture_start_time.load(Ordering::Relaxed));
let elapsed_secs = start_time.elapsed().as_secs();
let total_packets = STATS.tx_count.load(Ordering::Relaxed);
if elapsed_secs == 0 {
return total_packets;
}
total_packets / elapsed_secs
}
#[cfg(feature = "statistics")]
pub fn get_dropped_packets_rx() -> u32 {
STATS.rx_drop_count.load(Ordering::Relaxed)
}