Skip to content

The return path is not the forward path

Here is a physical reality of LoRa that mesh stacks routinely ignore: the two directions of a link are different links.

Picture a router on a hill with line-of-sight over a valley, and a client tucked behind terrain at the valley’s edge. The router — elevated, well powered, decent antenna — can reach the client on SF5 (LoRa’s fastest spreading factor: ~39 kbps in LRC’s BURST preset, short “range” on paper but loud when you have the high ground). The client, transmitting back uphill from behind an obstruction on a 20 mW radio, might only close the link at SF12 — LRC’s ANCHOR preset, ~180 bps, the maximum-range/minimum-rate corner of the modulation space. Same pair of radios. Forty-times-plus difference in usable rate, depending on which way the packet is going.

Single-preset meshes can’t even express this situation: the whole network runs one spreading factor, so the link either works symmetric-slow or doesn’t work. LRC’s radio layer is built on lane plans — routers operate several concurrent (frequency, preset, schedule) lanes, from the always-on SF12 anchor (the dial tone everyone can hear) up through faster presets — so the question “which lane should this client’s return traffic use?” actually has more than one possible answer. That makes it a routing problem, and an interesting one.

The tempting policy is: probe the link, pick the fastest preset that worked. That’s wrong on a lossy shared medium, and the reason is the retry economics. A preset whose SNR floor the link barely clears will drop a meaningful fraction of frames; every retransmission burns airtime — the one resource a LoRa network truly shares — and adds seconds of latency at low rates. A message that rides a slower preset once and is delivered frequently costs less airtime than one that rides a fast preset three times.

So LRC’s return-lane selector optimizes delivery-probability-per-airtime, not link speed: pick the slowest preset whose measured probe floor the return link clears with margin, breaking ties toward fewer hops and lower total airtime. The margin is the point — it’s what keeps the choice stable when the link flickers, instead of oscillating between “fast and failing” and “slow and working”. The router computes this from the uplink SNR it has itself measured for that client; it is not trusting anyone’s self-report.

The decision policy is host-tested code on the router today, and the wire format carries its output: LPP v2 frames include an Edge Routing Block with a return-descriptor — mode, lane id, preset, TTL — so a forward packet can carry “and here is how to reach me back” metadata that relays/edges act on. Per the project’s rules, the honest status label: policy built and tested, wire carriage landed, the actual RF retune actuation on real radios pending bench time — RF-touching changes need human sign-off, and the bench campaign is scheduled work, not done work.

One more honest note: the return descriptor travels in a mutable, unauthenticated block, and the routing redesign’s threat-model review caught exactly the risk you’d expect. The consolidated verdict demoted all such hints to diagnostics only — return-path trust derives exclusively from what the router itself observed deliver. That review is published, NEEDS-ROUNDTRIP verdicts and all, in the research section.

Deeper reading: the engineering deep dive §4.3, and Radio: lanes & presets.