gdane wrote:
First, it won't detect an asymmetry with the destination node (where C can't hear B in your example) because that node will never repeat. Active neighbor probing would detect this (assuming the destination node has probes enabled) and could potentially stop responding to path requests for C (a slow convergence).
Second, it won't work at all on non-broadcast transports of course, but I think that's ok considering those don't typically suffer from asymmetry anyway.
You are absolutely right in both points. We definitely have to consider these edge cases! Thanks for bringing that up.
Regarding your first edge case: next hop is final destination
The good thing is, we know that the next hop is the final destination. We therefore know that there won’t be a repeat of the packet. In these cases we can only use PROOF/LRPROOF packets to set the neighbor as RESPONSIVE/UNRESPONSIVE (simple PROOF can only be used to set a neighbor RESPONSIVE, LRPROOF can also be used to set a neighbor UNRESPONSIVE, since it is mandatory).
As far as I understood, the probe destination can only be enabled if the device is in transport mode, right? So as of right now, probing would also be no option in this case. But I guess that could be easily changed.
Regarding your second edge case: non broadcast transport medium
This is more tricky and also applies to a change of the transport medium. Imagine a device receives a packet over LoRa and forwards it to the next hop over TCP. This would break the passive responsiveness detection.
Maybe combining these approaches is an option: Passive listening for most of the cases and active probing for the edge cases. (As far as I know, PROOF/LRPROOF are already used as first indicator for responsiveness)
Btw: Having the probe destinations enabled by default – also for non-transport nodes – might support such a system.
gdane wrote:
Not sure I follow this exactly so could use some clarification. The neighbor responsiveness is already tracked in a separate table in microReticulum,
_neighbor_stats.
It's true however that when a neighbor is deemed to be unresponsive, it does trigger a potentially expensive walk of the full path table.
Are you proposing to track neighbor responsiveness along with destination in a separate table, or something else?
Oh, I have to admit I did not check the code. I understood your comment, that you used the existing mark_path_unresponsive() function:
Currently it just triggers the same unresponsive path handling as the Python reference implementation through
Transport.mark_path_unresponsive(), and I believe you're correct that the next announce from that node will
reset it. I think we can do better than this though, and at least compare the received announce neighbor against the neighbor that is unresponsive and reject it for some period of time.
What I meant is, that path_state and _neighbor_stats serve different purposes and should not be combined. Example: If Node A identified the neighbor transport node B as UNRESPONSIVE, ALL paths with Node B as next_hop could be allowed to be overwritten by a fresh announce from a responsive neighbor – even if the hop count is higher. The goal should be to prefer responsive neighbors somehow.
Furthermore, there might be many other paths that would also need to be set to UNRESPONSIVE (I guess this is the expensive walk of the full path table?).
It would be much easier to just check the neighbor_state if necessary, because this is one entry that has an impact on many paths at once.