Replies: 1 comment 1 reply
-
|
I propose a routing system based upon link strength. Each node reports the strength of its links to a central coordinating node that then constructs a set of known good link paths through the region. These paths are then distributed back to the nodes. When messages arrive at nodes from companion devices, they include a region and a destination location. The first node that receives the message calculates a route to the destination using these simple routing tables. |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Current behavior - v1.14
The current path selection is "first packet wins" — when a flood packet arrives at its destination, the first copy to arrive is processed and all duplicates are discarded via hasSeen(). The path from that first copy becomes the stored out_path for direct messaging.
From Mesh.cpp:
// NOTE: this is a 'first packet wins' impl. When receiving from multiple paths, the first to arrive wins.
// For flood mode, the path may not be the 'best' in terms of hops.
// FUTURE: could send back multiple paths, using createPathReturn(), and let sender choose which to use(?)
From BaseChatMesh.cpp:
// NOTE: default impl, we just replace the current 'out_path' regardless, whenever sender sends us a new out_path.
// FUTURE: could store multiple out_paths per contact, and try to find which is the 'best'(?)
The existing rxdelay mechanism provides implicit quality weighting — repeaters with stronger received signals forward faster, so the "first to arrive" tends to correlate with path quality. But this is not guaranteed and doesn't account for link asymmetry or path staleness - manual tests (when checking manually by logging into repeaters and checking signal to noise) show much better quality of connection thus less noise generated.
Problems this causes
Open PRs addressing this
PR, Approach, Complexity, RAM cost
#1911 │ Gate path updates: accept only if unknown, fewer hops, or stale (>60s) │ Low (~30 lines) │ ~0 bytes/contact
#1908 │ Active + backup path with failure tracking, cooldowns, and failover │ High (~350 lines changed) │ ~78 bytes/contact
#1782 │ Passive path candidates from overheard traffic │ Medium │ Varies
#1911 is the simplest — it prevents the "last path overwrites a working route" problem with three rules: accept if (a) no current path, (b) fewer hops, (c) current path older than 60 seconds. No backup storage, no failure tracking.
#1908 is comprehensive — dual active/backup path storage, failure counting (2 failures triggers switch), 10s switch cooldown, 30min backup expiry, 15s direct-block window forcing flood rediscovery. It fixes real correctness bugs (encoded path_len misuse in memcpy, stale pointer risk). But the RAM overhead is ~78 bytes/contact — with MAX_CONTACTS=350 that's ~27 KB, which may be tight on nRF52/RP2040.
What's missing: signal quality - and honestly, after last improvement (mesh path 2/3 bytes) it could be the biggest impact to limit unnecessary noise.
None of the current proposals consider signal quality. isPathBetter() in PR #1908 compares only hop count and path byte length. A 2-hop path through a marginal link will always beat a 3-hop path through strong links.
Proposal 1 (no changes): Add last-hop SNR to path acceptance (zero protocol changes)
When a destination endpoint receives a flood packet, it already has access to:
The rxdelay mechanism already ensures that at each repeater hop, the strongest-signal copy wins the forwarding race. By the time the packet reaches the destination, the last-hop SNR is a reasonable proxy for overall path health.
Concrete change: Store last_hop_snr (1 byte, SNR*4 as int8_t) alongside out_path in ContactInfo. Use it as a tiebreaker in path acceptance:
bool isPathBetter(uint8_t candidate_len, int8_t candidate_snr,
uint8_t current_len, int8_t current_snr) {
uint8_t candidate_hops = candidate_len & 63;
uint8_t current_hops = current_len & 63;
if (candidate_hops != current_hops) {
return candidate_hops < current_hops; // fewer hops wins
}
return candidate_snr > current_snr + 3; // same hops: better SNR wins (with hysteresis)
}
This adds 1 byte per contact, requires zero protocol changes, and works with both PR #1911 and #1908.
Suggested incremental path
Future (and important!) consideration: min-SNR tracking (requires protocol change) (edit: - as well as balance the track considering how priorities were assigned - very good SNR does not mean - high router availability)
For true bottleneck detection, a 1-byte min_snr field could be added to flood packets, updated by each repeater: min_snr = min(current, this_hop_snr).
This would let the destination see the weakest link in the entire chain, not just the last hop. This would be a wire format change and should be bundled with other breaking changes (e.g., a future protocol version bump).
Beta Was this translation helpful? Give feedback.
All reactions