fix: correct traceroute path orientation when building graph edges

A completed traceroute is observed as a response packet, whose from/to are
reversed with respect to the path being traced: `to` is the node that started
the traceroute and `from` is the node that answered. Meshview assembled paths
as [from, *route, to], so both endpoint-adjacent edges were wrong for every
completed traceroute with at least one intermediate hop. Because the false
edges always attach to the endpoints, a busy initiator or gateway accumulated
false direct links to every remote target it ever traced.

Confirmed against TraceRouteModule::alterReceivedProtobuf, which renders a
response as printRoute(r, p.to, p.from, false), against the meshtastic python
CLI, which starts the forward path at p["to"] and the return path at p["from"],
and against real recorded traceroutes where a request's route[] is a prefix of
the matching response's route[].

Add meshview/traceroute.py and use it from /api/edges, /api/traceroute and
graph_traceroute, which had three separate copies of this logic that had all
drifted. /api/traceroute also gains initiator/target so the traceroute page
stops re-deriving the endpoints itself, which is where a fourth copy lived.

While in /api/edges, skip the NODENUM_BROADCAST placeholders that
insertUnknownHops() writes into route[] (they became a pseudo-node hub in the
graph) and guard against the (gateway, gateway) self edge that
graph_traceroute already guarded against.
This commit is contained in:
giannoug committed 2026-09-04 23:28:04 +00:00
1 parent 992296b0c1
commit becf4a8a42
5 files changed
+97 -37

No files matched your search

+22 -9
View File
@@ -203,6 +203,10 @@ Returns network edges (connections between nodes) based on traceroutes and neigh
Traceroute edges are collected over the last 12 hours. Neighbor edges are based on
port 71 packets.
A completed traceroute is observed as a response packet, whose `from`/`to` are reversed
with respect to the traced path, so edges are built as `to -> route[] -> from`. Unknown
hop placeholders (`0xFFFFFFFF`) are skipped.
Query Parameters
- `type` (optional, string): `traceroute` or `neighbor`. If omitted, returns both.
- `node_id` (optional, int): Filter edges to only those touching a node.
@@ -324,13 +328,21 @@ Returns traceroute details and derived paths for a packet.
Path Parameters
- `packet_id` (required, int): Packet ID.
A completed traceroute is observed as a response packet, whose `from`/`to` are reversed
with respect to the traced path. `initiator` and `target` resolve this: the forward path
runs `initiator -> forward_hops -> target` and the return path runs
`target -> reverse_hops -> initiator`, in both directions of travel. `forward_hops` and
`reverse_hops` contain only the intermediate hops, never the endpoints.
Response Example
```json
{
"packet": {
"id": 123,
"from": 111,
"to": 222,
"from": 222,
"to": 111,
"initiator": 111,
"target": 222,
"channel": "main"
},
"traceroute_packets": [
@@ -338,19 +350,20 @@ Response Example
"index": 0,
"gateway_node_id": 333,
"done": true,
"forward_hops": [111, 444, 222],
"reverse_hops": [222, 444, 111]
"forward_hops": [444, 555],
"reverse_hops": [555, 444]
}
],
"unique_forward_paths": [
{ "path": [111, 444, 222], "count": 2 }
{ "path": [444, 555], "count": 2 }
],
"unique_reverse_paths": [
[222, 444, 111]
[555, 444]
],
"winning_paths": [
[111, 444, 222]
]
"winning_paths": {
"forward": [[111, 444, 555, 222]],
"reverse": [[222, 555, 444, 111]]
}
}
```