Beacons & Path Discovery
Beacons
A Beacon is defined as either:
- a broadcast packet with no payload, or
- a multicast packet with no payload
Beacons are used to announce the presence of a node on the network without carrying additional data. Because beacons have no payload, they omit the 0xFF end-of-options marker; the options block is parsed until the end of the packet. The minimum beacon size is unchanged.
A beacon with a Trace option can inform listeners of both:
- the node’s presence
- a repeater path that may be usable to reach it
This is particularly useful when a receiver already knows the node’s identity information.
A trace that carries signal reports the quality of each hop as well as its identity, which is what distinguishes a path that merely works from one worth using.
Advertisements
An advertisement is a broadcast or multicast packet whose payload is a node identity payload—a beacon that additionally identifies and describes its sender. Advertisements are sent unsolicited, announcing presence, name, role, and capabilities. An advertisement carries a frame signature, which is what authenticates the identity it carries (see Signature Usage). To obtain a specific node’s identity, use the Identity Request MAC command, which is answered with a targeted unicast identity response rather than a broadcast advertisement.
Announcing on a Schedule
A node MAY emit beacons and advertisements on periods of its own. The two are configured separately because they announce different things at very different costs: a beacon publishes a path for a handful of bytes, while an advertisement carries an identity in a signed frame and is the largest frame a node originates unprompted. A mesh is normally best served by refreshing the path often and restating the identity rarely.
A scheduled advertisement SHOULD be sent without flood hops. What it carries is a standing statement rather than news, so flooding it across the mesh on every period spends airtime out of proportion to what a distant listener learns; a node that wants to be findable further away publishes a path with a beacon instead.
A configured period is a minimum rather than an exact cadence. A node SHOULD scatter each period by a random fraction of it—a quarter is a reasonable choice—and that scatter MUST only delay an announcement, never bring it forward, so the configured value remains a floor on how often the node transmits unasked. Nodes commissioned alike and powered on together otherwise stay in step for as long as they run, colliding every period and colliding again on each retry, since a shared schedule makes them contend from the same instant every time. Carrier sensing resolves the individual collision; the scatter is what keeps the mesh from having to resolve one on every period.
A node that has just restarted is the node whose neighbors hold the stalest paths to it, so emitting one beacon at bring-up is RECOMMENDED. That beacon is not delayed: nodes do not restart in unison, so bring-up is already scattered by whatever staggered it.
On a device managed over ULCP, these periods are the advertisement-policy properties.
Path Discovery
UMSH does not define a dedicated path-discovery packet type. Instead, path discovery is performed using existing primitives:
-
Outbound discovery: Node A sends a unicast packet to Node B with the Trace option present and an appropriate flood hop count. The packet floods through the mesh; repeaters prepend their records to the Trace option as they forward.
-
Path learning: When Node B receives the packet, the Trace option contains the sequence of repeaters traversed, ordered most-recent first. If the trace is complete, Node B can use its router hints directly as a candidate source route back to Node A.
-
Return path: Node B can now send unicast packets to Node A using the learned source route. If the packet was ack-requested, Node B’s MAC ack also traverses the mesh, allowing Node A to confirm reachability.
-
Bidirectional establishment: The trace Node A sent taught Node B a path back, and nothing else. Node B’s response—MAC ack, beacon, or application payload—teaches Node A a path only if it carries a trace of its own. Where the response is a MAC ack, that ack is the whole of what Node A receives.
When to Include a Trace
A beacon or advertisement that permits flooding SHOULD always carry a trace: publishing a path back to its sender is much of what it is for, and every listener it reaches may lack one.
A trace gives the destination a path back to the sender, so a sender spends one when the destination may not hold a working path back. A sender SHOULD include a trace on a unicast or blind unicast when any of the following holds:
- it holds no route to the destination
- the packet answers one from the destination that arrived with
FHOPS_ACCgreater than zero; a MAC ack is such an answer - no packet from the destination has arrived with
FHOPS_ACCof zero in the last 5 minutes; a MAC ack correlated to the destination counts as a packet from it - it is a Route Retry resend
A packet that arrives with FHOPS_ACC of zero, off the sender’s own transmitter or along a source route, shows that its sender holds a working path to the receiver. That is what a trace would otherwise give it. A packet that had to flood to arrive shows the opposite. The 5-minute window bounds how long the evidence is trusted, since a path that worked can stop working.
A response to a packet that carried a trace MAY carry one. Any other packet MAY carry one, but a sender SHOULD otherwise prefer the smaller frame.
A packet carrying neither flood hops nor a source route SHOULD NOT carry a trace at all, whatever the sender knows. No repeater may forward such a packet, so the option can only arrive as empty as it left, and its arrival already proves what an empty trace would have said.
Because router hints are only two bytes, different repeaters may share the same hint, which may result in redundant (but harmless) forwarding along a source route.
Route Learning
A destination may overhear a frame while source-route hints remain unconsumed. The way back is then the remaining hints in reverse, followed by the trace: the whole path the sender chose, through the repeaters still to forward it. The trace alone would describe a shortcut past those repeaters, and a repeater being audible at the destination does not establish that it hears the destination. Historical buffered frames do not establish current reachability.
Copies of one packet, or of one MAC ack, that arrive over different paths each describe a path, and the first to arrive is not necessarily the best. A node MAY weigh them against each other and against the route it holds, using the per-hop signal of their traces where the copies carry it. A copy that arrives long after the first is a replay rather than evidence of a current path.
When a node successfully processes other live incoming packets, it can update its routing state for the sender:
-
Trace: if the packet contains a complete trace, with signal or hints only, the node caches its router hints as a source route for future packets back to the sender. Because the trace is accumulated most-recent first, it already describes the return path from the receiver back toward the original sender. This is the primary mechanism for learning precise multi-hop paths. A truncated trace is not a complete path, and no route is learned from it.
-
Flood hop count: if the packet contains a flood hop count, the node caches the sender’s
FHOPS_ACCvalue together with any region-code options that arrived on the packet. When no source route is available, these cached flood parameters can be reused for flood responses—scoping the flood to approximately the right radius and regional domain rather than flooding the entire network. -
Neither: a packet that arrives carrying no flood hop count and no source route was one that no repeater had permission to forward, so it reached the receiver off the sender’s own transmitter. The node SHOULD cache the sender as a direct neighbor. This is the same conclusion an empty trace supports, drawn from the packet’s structure rather than from an option, which is what lets an unforwardable packet leave the trace off.
A MAC ack can also supply routing evidence. It names no source, but its ack trailer correlates it to an outstanding request and so to the peer that sent it. Its trace can establish a route or replace a provisional direct observation with a repeater path. An ACK confirms that the exchange succeeded; its return path may differ from the outbound path, so it need not replace a working source route. Route selection and retention are local policy.
A packet that arrives carrying a source-route option—including one whose hints are all consumed—spends flood hops only after the route runs out, so its FHOPS_ACC counts the tail of the path rather than its length. Such a packet SHOULD NOT be used to derive a flood-distance estimate.
This routing state applies to all subsequent communication with the sender—replies, acknowledgments, and new messages alike. A node MAY replace a cached route when a newer packet provides a fresher trace, and SHOULD discard cached routes that have proven unreachable.
An ACK timeout is evidence that the exchange failed, not proof that the outbound leg alone failed. When an ACK-requested packet exhausts its retry budget on a cached route, the sender can return to route discovery:
- discard or demote the cached source route
- send the same logical packet again using flood hops instead of the stale source route
- include a Trace option so that a fresh source route can be learned from the peer’s reply
- set the Route Retry option so intermediate repeaters treat the rerouted attempt as a new forwarding opportunity even though the packet’s MIC and frame counter are unchanged
Trading a source route for flood hops rewrites only fields the associated data excludes. Adding FHOPS sets the FCF’s H bit, which the AAD clears, so the MIC carries over unchanged.
Recovery stays within the sender’s original flood ceiling; disabled flooding does not authorize a flooded retry. Once a replacement route is learned, normal routed transmission can resume. An ACK following Route Retry confirms delivery of the logical packet but does not identify which attempt delivered it.
A sender that held no route and flooded at its whole budget has no route to discard, yet the timeout may still be the destination’s fault: a route back to the sender that no longer works, on which the ACK died. When it has heard from the destination recently, the sender sends one Route Retry anyway, at the same budget and with a trace. A logical packet gets at most one Route Retry.
The destination learns from that retry. A Route Retry duplicating a packet it already acknowledged shows the ACK was lost, so the destination retires or demotes the route the ACK followed and re-acknowledges by a flood scoped to the retry’s FHOPS_ACC plus one hop, within the retry’s regions, carrying a trace. A path the retry traced may become an ordinary route candidate; the re-acknowledgment does not follow it. See Lost Acknowledgments.
Scoping Flood Hops to a Known Route
A wide flood hop count is a first-contact cost. Once routing state exists for a destination, the sender SHOULD scope FHOPS_REM to what the known path actually costs, plus a margin where the far end of the path is in doubt:
- Source route: named repeaters consume hints without spending flood budget; the margin is available only after all hints are consumed.
- Flood distance: the cached
FHOPS_ACCis the radius at which the destination was last heard. - Direct observation: no repeater carried the observed packet.
The margin is one flood hop. It keeps delivery self-healing when the destination has moved since the path was learned, without paying for a mesh-wide flood on every packet. What decides it is the path’s last hop: the link between the destination and the first node that heard it. For a direct observation that node is the sender itself; for a traced path it is the earliest repeater in the trace, whose trace record holds how it heard the destination, when the trace still carries signal. A cached flood distance names no last hop. The sender SHOULD include the margin when:
- the destination advertises itself as mobile (the
MOBbit of its capabilities), unless it was observed directly and strongly; - the last hop was never measured; or
- the last hop was measured weak.
The sender MAY omit the margin when the destination was observed directly and strongly or across a point-to-point link, when the last hop was measured without being weak, or when the application chose the path rather than learned it. Stronger than −75 dBm is a reasonable bar for a strong direct observation, and −96 dBm or weaker a reasonable bar for a weak last hop. A later packet whose path ends at the same last hop refreshes its measurement, whether or not that path replaces the one in use. A route that has failed outright is repaired through the route-retry behavior above, which floods at the sender’s full budget rather than the narrowed one.
A weak direct observation keeps the margin partly because the reverse direction may need a repeater the observed packet did not. ACKs can use the same margin, judged from the path the request taught, retaining the request’s region codes to scope any flooding even when the ACK also follows a source route. A strong link can still be one-way, so an ACK for a retransmission of a packet already acknowledged SHOULD carry the margin whatever its path: the retransmission shows the earlier ACK did not arrive. A consumed source route without a usable return trace supplies no total distance; a direct observation alone is insufficient to bound that ACK’s return path. The request’s flood ceiling governs the request, not the ACK’s independently selected return path.
An optional hop does not imply that a repeater is present. Not hearing a repeat is therefore insufficient reason to retransmit a directly addressed packet that requests no ACK, or an ACK sent directly with that allowance. A successful exchange with the margin does not show it was unnecessary.
Potential Improvement: Proactive Route Refresh
The recovery behavior above is reactive: a node continues using a cached source route until that route appears to have failed. In mobile scenarios, this may mean the sender does not attempt to discover a fresher route until after packets have already stopped flowing end-to-end.
One possible future improvement would be to allow a sender to occasionally perform a low-rate exploratory route refresh even when there is no strong indication of failure. This behavior is not part of the current specified protocol behavior and has not been validated with real-world measurements. It is described here only as a possible future optimization.
A conservative version of this idea would look like:
- only perform exploratory refresh when the sender is believed to be mobile or moving
- use a normal cached source route, but also include a Trace option
- allow only a small flood budget, capped at one flood hop more than the source route has hints
- perform this no more than occasionally, for example no more than once every
Nsuccessful transmissions and no more than once everyTminutes, whichever is longer
The intent would be to probe for a slightly better or fresher route without incurring the cost of a full rediscovery flood. A small tail flood could help discover alternate final hops or nearby replacement repeaters when the old route is only partially stale.
This approach has important limitations:
- if the cached source route breaks early, a small tail flood will not help, because forwarding remains constrained by the explicit source route until that route is exhausted
- excessive probing would waste airtime and increase contention, especially on busy meshes
- a newly observed route is not necessarily better and may require local policy before replacing the old route
If this idea is ever standardized, meshes should converge on the same probing policy and parameter values so that behavior remains predictable across implementations. Any such policy should be treated as provisional until it has been evaluated on real radios in mobile conditions.