MacCounters

Struct MacCounters 

Source
pub struct MacCounters {
    pub tx_frames: u32,
    pub tx_abandoned: u32,
    pub rx_frames: u32,
    pub rx_accepted: u32,
    pub forwarded: u32,
    pub forward_cancelled: u32,
}
Expand description

Central MAC coordinator that owns and drives the full UMSH radio-facing state machine.

Mac is the top-level entry point for UMSH protocol operation. It combines a radio driver, cryptographic engine, clock, RNG, counter store, and all protocol state into a single fully-typed, allocation-free structure. All const-generic capacity parameters are enforced at compile time via heapless collections — there are no heap allocations inside Mac.

§Generic parameters

  • P: Platform — a trait bundle supplying the concrete driver types for Radio, Aes/Sha (crypto), Clock, Rng, and CounterStore. Implement Platform once per deployment target to swap in real hardware drivers, software stubs, or test doubles.
  • IDENTITIES — maximum simultaneously active local identities (default DEFAULT_IDENTITIES).
  • PEERS — maximum known remote peers and their per-identity pairwise key entries (default DEFAULT_PEERS).
  • CHANNELS — maximum registered multicast channel keys (default DEFAULT_CHANNELS).
  • ACKS — maximum simultaneously in-flight ACK-requested sends per identity (default DEFAULT_ACKS).
  • TX — depth of the transmit queue (default DEFAULT_TX). Must be large enough to absorb a burst of control frames (MAC ACKs + forwarded frames) alongside any backlogged application sends.
  • FRAME — maximum byte length of a stored frame buffer for retransmission (default [MAX_RESEND_FRAME_LEN]).
  • DUP — capacity of the duplicate-detection cache (default DEFAULT_DUP).

§Lifecycle

  1. Construct with Mac::new, supplying concrete driver instances and policy.
  2. Register identities via Mac::add_identity; call Mac::load_persisted_counter on each long-term identity to restore the safe frame-counter start point from non-volatile storage.
  3. Register peers via Mac::add_peer. Secure unicast and blind-unicast state is derived lazily from the local private key and peer public key on first use.
  4. Register channels via Mac::add_channel or Mac::add_named_channel.
  5. Drive the event loop via Mac::run / Mac::run_quiet for long-lived tasks, or by awaiting Mac::next_event when you need to multiplex MAC progress with other async work. The coordinator handles incoming frames, outgoing transmits, forwarding, ACK matching, retransmission scheduling, and timer deadlines — no external polling required.
  6. Send traffic by calling queue_broadcast, queue_unicast, queue_multicast, etc. from application code between (or concurrent with) event-loop iterations.
  7. Persist counters by calling Mac::service_counter_persistence whenever next_event signals that pending persistence work is ready to flush.

§Example (pseudo-code)

let mut mac = Mac::<MyPlatform>::new(
    radio, crypto, clock, rng, counter_store,
    RepeaterConfig::default(), OperatingPolicy::default(),
);
let id = mac.add_identity(my_identity)?;
mac.load_persisted_counter(id).await?;

mac.run(|id, event| {
    let _ = (id, event);
    // handle deliveries / ACKs here and schedule persistence work as needed
}).await?;

Cumulative frame tallies for the coordinator, since construction.

Diagnostic only: nothing in the protocol depends on them, and they are deliberately not persisted. They exist so an operator can tell a working node from a deaf one without a capture — a radio whose rx_frames never moves is not hearing anybody.

Every field saturates rather than wraps. A counter that rolled over would make a long-running node look freshly booted; pinning at the maximum is at least monotone, which is the property a reader is actually using them for.

Fields§

§tx_frames: u32

Frames the radio accepted for transmission, including forwards.

§tx_abandoned: u32

Frames given up on after MAX_CAD_ATTEMPTS busy channels.

§rx_frames: u32

Frames the radio handed up, whoever they were addressed to.

§rx_accepted: u32

Receptions that produced an event or a side effect. The shortfall against Self::rx_frames is other people’s traffic, duplicates, and undecodable noise.

§forwarded: u32

Receptions this node repeated onward.

§forward_cancelled: u32

Queued forwards dropped because the destination’s ack was overheard before they went out. Airtime this node did not have to spend.

Trait Implementations§

Source§

impl Clone for MacCounters

Source§

fn clone(&self) -> MacCounters

Returns a duplicate of the value. Read more
1.0.0§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MacCounters

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for MacCounters

Source§

fn default() -> MacCounters

Returns the “default value” for a type. Read more
Source§

impl PartialEq for MacCounters

Source§

fn eq(&self, other: &MacCounters) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for MacCounters

Source§

impl Eq for MacCounters

Source§

impl StructuralPartialEq for MacCounters

Auto Trait Implementations§

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> CloneToUninit for T
where T: Clone,

§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.