Skip to main content

bacnet_bip_core/node/
counters.rs

1//! What a [`Node`](super::Node) counts, drained by
2//! [`Node::take_counters`](super::Node::take_counters) into the host's own
3//! totals.
4
5use core::net::SocketAddrV4;
6
7use bacnet_bip_codec::BvlcResultCode;
8
9use super::exchange::Operation;
10use super::registration::AttemptOutcome;
11
12/// One operation's exchanges since the counters were last taken, manual
13/// and automatic alike. Counts saturate.
14#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
15#[non_exhaustive]
16pub struct ExchangeCounters {
17    /// Requests the caller reported sent.
18    pub sent: u32,
19    /// Matched, accepted table ACKs.
20    pub acknowledgements: u32,
21    /// Matched, well-formed BVLC-Results: success or the operation's NAK.
22    pub results: u32,
23    /// The newest of those results' codes.
24    pub last_result: Option<BvlcResultCode>,
25    /// Sent requests whose response timeout passed unanswered.
26    pub timeouts: u32,
27    /// Requests refused because their exchange's slot was taken.
28    pub busy: u32,
29    /// Requests whose send the caller reported failed.
30    pub local_errors: u32,
31    /// Malformed responses from the peer of a live exchange of this
32    /// operation, counted against the first such exchange in slot order.
33    pub malformed_responses: u32,
34}
35
36/// A Register-Foreign-Device attempt, manual or automatic, as it stands.
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38#[non_exhaustive]
39pub struct RegisterAttempt {
40    /// The BBMD it went to.
41    pub bbmd: SocketAddrV4,
42    /// The time-to-live it asked for.
43    pub ttl: u16,
44    /// What it came to.
45    pub outcome: AttemptOutcome,
46    /// The result code that answered it, when one did.
47    pub result: Option<BvlcResultCode>,
48}
49
50/// Everything a node counts, since the counters were last taken. Counts
51/// saturate; the `last_` fields hold the newest value seen since, if any.
52#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
53#[non_exhaustive]
54pub struct NodeCounters {
55    /// Read-Broadcast-Distribution-Table exchanges.
56    pub read_bdt: ExchangeCounters,
57    /// Write-Broadcast-Distribution-Table exchanges.
58    pub write_bdt: ExchangeCounters,
59    /// Read-Foreign-Device-Table exchanges.
60    pub read_fdt: ExchangeCounters,
61    /// Delete-Foreign-Device-Table-Entry exchanges.
62    pub delete_fdt_entry: ExchangeCounters,
63    /// Register-Foreign-Device exchanges.
64    pub register_foreign_device: ExchangeCounters,
65    /// Register-Foreign-Device attempts admitted, manual and automatic.
66    pub registration_attempts: u32,
67    /// Of those, answered with success.
68    pub registrations_accepted: u32,
69    /// Of those, answered with the Register-Foreign-Device NAK.
70    pub registrations_refused: u32,
71    /// The newest attempt, whenever it changed.
72    pub last_registration_attempt: Option<RegisterAttempt>,
73    /// Well-formed responses that matched no live exchange.
74    pub unmatched_responses: u32,
75    /// Of those, the ones within one response timeout of an exchange they
76    /// fit ending.
77    pub late_responses: u32,
78    /// The newest unmatched BVLC-Result's code.
79    pub last_unmatched_result: Option<BvlcResultCode>,
80    /// Malformed responses, matched or not: refused by the codec or by
81    /// [`Policy::accept_table`](super::Policy::accept_table).
82    pub malformed_responses: u32,
83    /// Distribute-Broadcast-To-Network NAKs from the foreign device's own
84    /// BBMD, taken as a sign it lost the registration: with
85    /// [`Retry::Backoff`](super::Retry::Backoff) only.
86    pub renewal_hints: u32,
87    /// Leases that ended with nothing newer proven.
88    pub lapses: u32,
89    /// Broadcasts held for the first registration attempt.
90    pub broadcasts_held: u32,
91    /// Held broadcasts released when that attempt succeeded or went
92    /// unanswered.
93    pub broadcasts_released: u32,
94    /// Held broadcasts discarded when the BBMD refused that attempt.
95    pub broadcasts_discarded: u32,
96    /// Broadcasts refused because the hold was full.
97    pub broadcasts_hold_full: u32,
98    /// Broadcasts sent while no lease was live.
99    pub broadcasts_unregistered: u32,
100}
101
102impl NodeCounters {
103    /// The counters of `operation`'s exchanges.
104    #[must_use]
105    pub const fn exchange(&self, operation: Operation) -> &ExchangeCounters {
106        match operation {
107            Operation::ReadBdt => &self.read_bdt,
108            Operation::WriteBdt => &self.write_bdt,
109            Operation::ReadFdt => &self.read_fdt,
110            Operation::DeleteFdtEntry => &self.delete_fdt_entry,
111            Operation::RegisterForeignDevice => &self.register_foreign_device,
112        }
113    }
114
115    pub(crate) fn exchange_mut(&mut self, operation: Operation) -> &mut ExchangeCounters {
116        match operation {
117            Operation::ReadBdt => &mut self.read_bdt,
118            Operation::WriteBdt => &mut self.write_bdt,
119            Operation::ReadFdt => &mut self.read_fdt,
120            Operation::DeleteFdtEntry => &mut self.delete_fdt_entry,
121            Operation::RegisterForeignDevice => &mut self.register_foreign_device,
122        }
123    }
124}
125
126/// Add one, saturating.
127pub(crate) fn bump(counter: &mut u32) {
128    *counter = counter.saturating_add(1);
129}
130
131/// Add `count`, saturating.
132pub(crate) fn add(counter: &mut u32, count: u16) {
133    *counter = counter.saturating_add(u32::from(count));
134}