pub struct Table<const R: usize, const H: usize> { /* private fields */ }Expand description
A routing table of up to R routes and H hold-down records.
A full table refuses a new network: add_direct
and add_learned return false, and
learn and apply_claim return
LearnRefusal::Full. Routes it holds can still be refreshed, moved and
removed. A router keeps its route cap at or below R, so the cap, which
it counts, is met first.
A Route is a copy of a row, so a route changes only through the
table’s calls, each of which keeps its rules: add_direct
and add_learned install one;
learn and apply_claim learn one,
with flap detection and convergence; mark_busy,
mark_available and
mark_unreachable set its state;
touch notes its use; and remove and
purge_stale take it out. None of them makes a
learned route direct, or a direct one learned, except by replacing it.
new is a const fn whose result is all zero bits, so a
table can live in a zero-initialized static (.bss).
Implementations§
Source§impl<const R: usize, const H: usize> Table<R, H>
impl<const R: usize, const H: usize> Table<R, H>
Sourcepub fn apply_claim(
&mut self,
network: u16,
port: PortId,
next_hop: Mac,
now: Instant,
timing: &Timing,
) -> Learned
pub fn apply_claim( &mut self, network: u16, port: PortId, next_hop: Mac, now: Instant, timing: &Timing, ) -> Learned
Apply a learning claim from an I-Am-Router or an Init-RT-Ack entry:
network is reachable through the router at next_hop on port.
Under Convergence::Standard it is learn, and any
pending claim for the network is dropped without counting. Under
Convergence::Hardened, a claim that would move a learned route to
another port is held until a second claim for the same network and
port arrives within Timing::corroboration, inclusive; the second
supplies the next hop. A claim for another port takes the pending
slot over, and one past the window starts it again. The held route
keeps forwarding as it was.
Sourcepub fn learn(
&mut self,
network: u16,
port: PortId,
next_hop: Mac,
now: Instant,
) -> Learned
pub fn learn( &mut self, network: u16, port: PortId, next_hop: Mac, now: Instant, ) -> Learned
Install or refresh a learned route at once, with flap detection.
A move to another port sets last_seen and the move time to now,
clears last_used, any mark, the pending claim and the hold-down, and
counts the move toward the flap warning when it comes within 60 s of
the last. A new network or a refresh through the same port is
add_learned.
Sourcepub fn expire_pending(
&mut self,
now: Instant,
timing: &Timing,
expired: impl FnMut(u16),
) -> usize
pub fn expire_pending( &mut self, now: Instant, timing: &Timing, expired: impl FnMut(u16), ) -> usize
Drop every pending claim older than Timing::corroboration at
now, calling expired with each network in ascending order, and
return how many. Each counts as expired. A claim is dropped and
counted before its call, so an expired that panics leaves the table
consistent.
Sourcepub fn pending(&self, network: u16) -> Option<Pending>
pub fn pending(&self, network: u16) -> Option<Pending>
The claim pending for network under hardened convergence.
Sourcepub fn pending_count(&self) -> usize
pub fn pending_count(&self) -> usize
How many claims are pending: at most one per learned route.
Sourcepub fn apply_management_update(
&mut self,
network: u16,
port: PortId,
next_hop: Mac,
now: Instant,
) -> bool
pub fn apply_management_update( &mut self, network: u16, port: PortId, next_hop: Mac, now: Instant, ) -> bool
Apply one Initialize-Routing-Table entry with a nonzero Port ID:
install network as a learned route through next_hop on port,
replacing any learned route it had or adding a new one, at once and
without corroboration (Clause 6.4.7). A direct route, network 0 and
0xFFFF are left alone. false when nothing was installed.
Sourcepub fn apply_management_removal(&mut self, network: u16) -> bool
pub fn apply_management_removal(&mut self, network: u16) -> bool
Apply one Initialize-Routing-Table entry with Port ID 0: delete the
network’s learned route. Direct routes stay. true only when a route
was removed.
Source§impl<const R: usize, const H: usize> Table<R, H>
impl<const R: usize, const H: usize> Table<R, H>
Sourcepub fn apply_reject(
&mut self,
network: u16,
port: PortId,
reason: RejectMessageReason,
now: Instant,
timing: &Timing,
) -> RejectEffect
pub fn apply_reject( &mut self, network: u16, port: PortId, reason: RejectMessageReason, now: Instant, timing: &Timing, ) -> RejectEffect
Apply what a received reject says about the route to network,
arriving on port with reason (Clause 6.6.3.5). Relaying the
reject is the router’s business, not the table’s.
Reason 1 marks a learned route unreachable. Reason 2 marks it busy
for Timing::busy_for, unless it is unreachable or still busy: a
repeat never extends the deadline. Any other reason leaves a learned
route as it is (RejectEffect::Kept, counted in
ClaimCounters::reject_kept),
since the clause changes the table for those two only. A reject that
would change nothing, or one within Timing::hold_down of the last
change applied from the same port, is ignored and counted, and moves
neither the window nor the deadline. Direct routes never change.
Source§impl<const R: usize, const H: usize> Table<R, H>
impl<const R: usize, const H: usize> Table<R, H>
Sourcepub const fn set_convergence(&mut self, convergence: Convergence)
pub const fn set_convergence(&mut self, convergence: Convergence)
Choose the convergence mode for later claims. Routes stay; a pending
claim waits for its next claim or the sweep, as before. It is a
const fn, so a table in a static can start hardened.
Sourcepub const fn convergence(&self) -> Convergence
pub const fn convergence(&self) -> Convergence
The convergence mode.
Sourcepub const fn claim_counters(&self) -> ClaimCounters
pub const fn claim_counters(&self) -> ClaimCounters
The claim counts so far.
Sourcepub fn remove(&mut self, network: u16) -> Option<Route>
pub fn remove(&mut self, network: u16) -> Option<Route>
Remove the route to network, with its pending claim and its
hold-down records.
Sourcepub fn routes(&self) -> impl Iterator<Item = (u16, &Route)> + Clone
pub fn routes(&self) -> impl Iterator<Item = (u16, &Route)> + Clone
Every route, in ascending network order. This and the other listings can be cloned, so a writer can count before it writes.
Sourcepub fn networks_on_port(
&self,
port: PortId,
) -> impl Iterator<Item = u16> + Clone
pub fn networks_on_port( &self, port: PortId, ) -> impl Iterator<Item = u16> + Clone
The networks reached through port, in ascending order.
Sourcepub fn networks_not_on_port(
&self,
port: PortId,
) -> impl Iterator<Item = u16> + Clone
pub fn networks_not_on_port( &self, port: PortId, ) -> impl Iterator<Item = u16> + Clone
The networks reached through any port but port, in ascending order.
Sourcepub fn add_direct(&mut self, network: u16, port: PortId) -> bool
pub fn add_direct(&mut self, network: u16, port: PortId) -> bool
Install a directly attached network on port, replacing whatever
route it had and clearing its records. Network 0 and 0xFFFF are
ignored. false when nothing was installed.
Sourcepub fn add_learned(
&mut self,
network: u16,
port: PortId,
next_hop: Mac,
now: Instant,
) -> bool
pub fn add_learned( &mut self, network: u16, port: PortId, next_hop: Mac, now: Instant, ) -> bool
Install or refresh a learned route at once, without corroboration or flap detection: a management write, or a call on the table itself.
It sets last_seen, keeps last_used on a refresh through the same
port and clears it otherwise, clears any mark, and re-arms the
hold-down. A direct route, network 0 and 0xFFFF are left alone.
false when nothing was installed.
Sourcepub fn mark_busy(&mut self, network: u16, deadline: Instant)
pub fn mark_busy(&mut self, network: u16, deadline: Instant)
Mark a learned route busy until deadline, unless it is unreachable:
congestion never revives a failed route. Direct routes are never
marked, and neither timestamp moves.
Sourcepub fn mark_available(&mut self, network: u16)
pub fn mark_available(&mut self, network: u16)
Make a learned route reachable, lifting a busy or unreachable mark. Direct routes and timestamps are untouched.
Sourcepub fn mark_busy_via_peer(
&mut self,
port: PortId,
peer: &[u8],
deadline: Instant,
) -> usize
pub fn mark_busy_via_peer( &mut self, port: PortId, peer: &[u8], deadline: Instant, ) -> usize
mark_busy every route served via the router at
peer on port, as a Router-Busy from it that lists no network asks,
and return how many were marked. Unreachable routes stay unreachable.
Sourcepub fn mark_available_via_peer(&mut self, port: PortId, peer: &[u8]) -> usize
pub fn mark_available_via_peer(&mut self, port: PortId, peer: &[u8]) -> usize
mark_available every route served via the
router at peer on port, as a Router-Available from it that lists
no network asks, and return how many there were.
Sourcepub fn mark_unreachable(&mut self, network: u16)
pub fn mark_unreachable(&mut self, network: u16)
Mark a learned route unreachable, keeping it in the table. Direct routes are untouched.
Sourcepub fn is_served_via_peer(
&self,
network: u16,
port: PortId,
peer: &[u8],
) -> bool
pub fn is_served_via_peer( &self, network: u16, port: PortId, peer: &[u8], ) -> bool
Whether network is served by the router at peer on port: a
learned route through that port to that next router. This is the
scope of a flow-control message from peer, whose own list, when it
has one, is intersected with it.
Sourcepub fn routes_served_via_peer<'t>(
&'t self,
port: PortId,
peer: &'t [u8],
) -> impl Iterator<Item = u16> + Clone + 't
pub fn routes_served_via_peer<'t>( &'t self, port: PortId, peer: &'t [u8], ) -> impl Iterator<Item = u16> + Clone + 't
The networks is_served_via_peer holds
for, in ascending order: the scope of a flow-control message from
peer that lists none.
Sourcepub fn clear_expired_busy(&mut self, now: Instant) -> usize
pub fn clear_expired_busy(&mut self, now: Instant) -> usize
Clear every busy mark whose deadline has come, returning how many.
Sourcepub fn effective_reachability(
&self,
network: u16,
now: Instant,
) -> Option<Reachability>
pub fn effective_reachability( &self, network: u16, now: Instant, ) -> Option<Reachability>
The reachability of network at now: a busy mark reads
Reachable from its deadline on, whether or not the sweep has run.
Sourcepub fn touch(&mut self, network: u16, now: Instant)
pub fn touch(&mut self, network: u16, now: Instant)
Note that a learned route carried traffic now. Only last_used
moves, so traffic never keeps a route alive.
Sourcepub fn purge_stale(
&mut self,
now: Instant,
max_age: Duration,
purged: impl FnMut(u16),
) -> usize
pub fn purge_stale( &mut self, now: Instant, max_age: Duration, purged: impl FnMut(u16), ) -> usize
Remove every learned route last confirmed more than max_age before
now, calling purged with each network in ascending order, and
return how many. Direct routes never age.
Every call comes before anything is removed, so a purged that
panics leaves the table as it was.