per-peer stats

This commit is contained in:
ktims committed 2026-10-22 18:14:05 -07:00
1 parent ac154066e1
commit 8fbafa455a
2 files changed
+262 -19

No files matched your search

+29 -13
View File
@@ -3,7 +3,7 @@ use futures::future;
use rust_bfd::config::{Config, ConfigError, ResolvedConfig, ResolvedPeer};
use rust_bfd::events::{EventMessageSink, ScriptHookSink, StateChangeEvent};
use rust_bfd::{bfd::*, events::EventMessage};
use rust_bfd::{set_ttl_or_hop_limit, BfdSessionStats};
use rust_bfd::{set_ttl_or_hop_limit, AtomicInstant, AtomicIntervalStats, BfdSessionStats};
use std::{
collections::{HashMap, HashSet},
error::Error,
@@ -124,8 +124,10 @@ struct BfdSessionState {
detection_time: Atomic<BfdInterval>, // mutable by rx thread
poll_mode: Atomic<bool>, // mutable by rx thread
control_packets_rx: Atomic<u64>,
control_packets_tx: Atomic<u64>,
rx_stats: AtomicIntervalStats, // reset each time the session enters Up
tx_stats: AtomicIntervalStats, // reset each time the session enters Up
last_up: AtomicInstant,
last_down: AtomicInstant,
last_state_change: Mutex<Instant>,
last_remote_diag: Atomic<BfdDiagnostic>,
}
@@ -221,11 +223,19 @@ impl BfdSessionState {
fn set_detection_time(&self, value: BfdInterval) {
self.detection_time.store(value, ORDERING)
}
fn control_packets_rx(&self) -> u64 {
self.control_packets_rx.load(ORDERING)
fn record_rx(&self) {
self.rx_stats.record(Instant::now());
}
fn control_packets_tx(&self) -> u64 {
self.control_packets_tx.load(ORDERING)
fn record_tx(&self) {
self.tx_stats.record(Instant::now());
}
fn mark_up(&self) {
self.rx_stats.reset();
self.tx_stats.reset();
self.last_up.store(Instant::now());
}
fn mark_down(&self) {
self.last_down.store(Instant::now());
}
fn last_state_change(&self) -> Instant {
*self.last_state_change.try_lock().unwrap()
@@ -266,8 +276,10 @@ impl From<&BfdSessionState> for BfdSessionStats {
remote_discr: state.remote_discr(),
state: state.session_state(),
last_diag: state.last_remote_diag(),
control_packets_rx: state.control_packets_rx(),
control_packets_tx: state.control_packets_tx(),
rx: state.rx_stats.snapshot(),
tx: state.tx_stats.snapshot(),
last_up: state.last_up.load(),
last_down: state.last_down.load(),
last_change: state.last_state_change(),
detect_time: state.detection_time(),
base_interval: BfdInterval::from_secs(0), // TODO: This is a hack and will be patched up in the session
@@ -483,8 +495,10 @@ impl BfdSession {
detection_time: Atomic::new(BfdInterval::from_secs(0)),
poll_mode: Atomic::new(false),
control_packets_rx: Atomic::new(0),
control_packets_tx: Atomic::new(0),
rx_stats: AtomicIntervalStats::new(),
tx_stats: AtomicIntervalStats::new(),
last_up: AtomicInstant::new(),
last_down: AtomicInstant::new(),
last_state_change: Mutex::new(Instant::now()),
last_remote_diag: Atomic::new(BfdDiagnostic::None),
},
@@ -514,6 +528,7 @@ impl BfdSession {
*self.state.last_state_change.lock().await = Instant::now();
match (self.state.session_state(), new_state) {
(BfdState::Up, BfdState::AdminDown | BfdState::Down | BfdState::Init) => {
self.state.mark_down();
if let Some(watchdog) = self.rx_watchdog.as_mut() {
watchdog.send(WatchdogReset::Terminate).await.unwrap();
};
@@ -530,6 +545,7 @@ impl BfdSession {
self.update_transmit_interval().await;
}
(BfdState::AdminDown | BfdState::Down | BfdState::Init, BfdState::Up) => {
self.state.mark_up();
self.start_watchdog().await;
self.state.set_local_diag(BfdDiagnostic::None); // This doesn't seem to be required by the spec but seems sensible and at least FRR does it.
// Advertise the configured interval now, but per section 6.8.3 keep transmitting at the old (slower)
@@ -601,7 +617,7 @@ impl BfdSession {
};
let socket = self.state.control_sock.clone();
let dest = self.state.peer_addr;
self.state.control_packets_tx.fetch_add(1, ORDERING);
self.state.record_tx();
debug!("tx packet: {:?}", packet);
if let Err(e) = socket
.send_to(
@@ -674,7 +690,7 @@ impl BfdSession {
if let Some(watchdog) = self.rx_watchdog.as_ref() {
let _ = watchdog.send(WatchdogReset::ReceivedPacket).await;
}
self.state.control_packets_rx.fetch_add(1, ORDERING);
self.state.record_rx();
let received_state = match p.flags.state() {
Err(_) => {
warn!("Invalid state, discarding");