Add next-hop retry for direct-path relays#2980
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Hi @benallfree , > From what I can tell, these listen for the message echo. that's right, at least #2670 and #2367 do. > That was my first instinct too, but after more thinking I feel this may actually make the problem worse on the links that need it most. It is good because it costs zero extra airtime, but it is risky on weak/problematic/busy links because the airtime needed to hear the echo dramatically increases the chance of collisions and errors. The approach of PR2670 is to listen as long as possible and keep deafness low (prevent TX, prevent calibration that blocks RX) on the sending node. If a node is stressed with TX it may not hear a downstream package repetition so it will resend its package which is unnecessary. So yes, in busy environments the error correction remains but the package frequency becomes higher. I tried to reduce the probability of collisions by checking for noise before repeating a package but yes, the more traffic the worse the quality gets. But still better for deliverability than with common MeshCore without the duplication. > In contrast, a hard ack is about 12 bytes regardless of the original message size. So for 12 extra bytes of airtime, you get the most reliable ack's possible. That means to at least double the amount of TX for a direct message plus possible repetitions if the ACK was not received by the sender. Plus special collision problems when the ACK packages cannot be heard and the sender repeats its package. Side note: package resending like with PR2670 is downwards compatible; so it works without updating all other nodes. |
|
Hi @usrflo :)
I like this! Very smart 🔥
Maybe we can both think about this, I'd like to hear your opinion. You have probably noticed like I have that smaller packets are delivered far more reliably than larger packets. Hard ACK takes advantage of this idea and is 14 bytes: If the sender can't hear a 14 byte ACK, it seems even less likely that it would hear a >14 byte echo of the original message. A separate 14 byte ACK stays small even with large 200-byte messages. For 14 extra bytes of airtime, we buy the most reliable ACK possible. At first, it does seem like increased TX compounds the problem. However, I think spending some airtime on the most reliable ACK possible will ultimately lead to the fewest resends between hops and also the fewest full path resends from the user (the worst problem), which far outweigh 15 byte ACKs. I imagine we both agree that best ACK = fewest resends. So the question is passive vs active ACK. Maybe it could be a setting, like
Sorry I didn't mention it, but this PR will not attempt resends until the first ACK is heard from the receiver. Graceful upgrade. I added the note. Thanks for the interesting conversation. Any way we improve or solve this is a win for mesh 🙏 |
Co-authored-by: Cursor <cursoragent@cursor.com>
|
@usrflo I have thought about your points more and made an update. Now we start with passive echo listening. If A does not hear an echo, it will resend. If B detects a resend, it knows A did not hear the original echo and will send a hard ACK back to hopefully prevent A from spamming more retries when B has already relayed the message. So now hard ack is reserved for only situations where passive echo fails. Do you like it? |
cf01828 to
f46aa4f
Compare
Co-authored-by: Cursor <cursoragent@cursor.com>
This is a draft for visibility. Note: this intro section will stay updated, so it may not match comments below
This is a wire-compatible PR for both passive and active direct hop ACKs.
Right now, repeaters relay-and-forget. Any missed link in the path results in a timeout and the user has to retry the entire path.
With this enhancement, repeaters will listen for an echo from the next hop. If they don't hear it, they will resend. If the receiving repeater hears a resend after it has already processed a message, it will send a hard ACK to prevent further spurious repeats.
We also add several CLI settings, including a volatile
ignoresetting to force link repeats for testing:get hop.retry20= off)set hop.retry <count>count2count + 1total TX (initial + retries)get hop.retry.ms1500set hop.retry.ms <ms>milliseconds1500direct.txdelayand packet airtimeget hop.ignore0set hop.ignore <count>count0Prior art: