Skip to content

fix: zerohop also zeros hop_start to prevent traceroute ghost hops (#46)#47

Open
eric-becker wants to merge 6 commits into
mainfrom
fix/zerohop-traceroute
Open

fix: zerohop also zeros hop_start to prevent traceroute ghost hops (#46)#47
eric-becker wants to merge 6 commits into
mainfrom
fix/zerohop-traceroute

Conversation

@eric-becker
Copy link
Copy Markdown
Owner

Summary

Closes #46.

Floodgate previously set only MeshPacket.hop_limit = 0 while leaving hop_start untouched. Receiving Meshtastic firmware computes hopsTaken = hop_start - hop_limit and pads RouteDiscovery.route[] with 0xFFFFFFFF sentinels for the difference, which the phone apps render as Meshtastic ffff (ffff) ghost hops in traceroutes (6 entries between the real endpoints, hop count inflated to ~7).

This PR also zeros hop_start (and JSON hops_away). Setting hop_start = 0 triggers a documented special case in firmware (NodeDB.cpp:1684): getHopsAway returns -1 ("unknown"), and insertUnknownHops (TraceRouteModule.cpp:362) guards on hopsTaken >= 0 so the padding loop doesn't fire. Rebroadcast suppression behaviour is unchanged (NextHopRouter.cpp:144 still gates on hop_limit > 0 only).

Per-message log records continue to show the original sender values for observability — metadata is extracted before mutation.

Changes

  • src/floodgate/zerohop.py — zero hop_start in zerohop_protobuf; zero hop_start and hops_away (when present) in zerohop_json.
  • tests/test_zerohop.py — new TestZerohopProtobufHopFields class; new JSON parity tests; tightened existing synthetic round-trip to assert hop_start == 0.
  • tests/test_portnum.py — backward-compatible: _build_encrypted_envelope gains optional hop_start param (default None, no behaviour change for existing callers).
  • tests/integration/test-driver/run.pycase_zerohop now asserts delivered hop_start == 0 end-to-end through ExHook + EMQX.
  • README.md, src/floodgate/__main__.py — describe both fields are zeroed.

Test plan

  • Unit suite: 204 passed (was 201 baseline; +3 new tests). Run: pytest tests/ --ignore=tests/test_container_smoke.py -q
  • No regressions in any existing test.
  • Integration harness (./scripts/run-integration.sh) — verified in CI. (Local Docker is constrained on the maintainer's host due to k3s networking.)
  • Manual: traceroute through a floodgate-zerohopped MQTT gateway no longer shows Meshtastic ffff (ffff) ghost hops in the phone apps. To verify post-merge on the production deployment using the screenshots in fix: zerohop inflates traceroute hop count and shows 'Meshtastic ffff (ffff)' ghost hops #46 as the baseline.

🤖 Generated with Claude Code

Eric Becker and others added 6 commits May 10, 2026 01:57
Receiving firmware computes hopsTaken = hop_start - hop_limit and pads
RouteDiscovery.route[] with 0xFFFFFFFF sentinels for the difference,
which apps render as 'Meshtastic ffff (ffff)' ghost hops in traceroutes.
Setting hop_start = 0 hits a documented special case in getHopsAway
(returns -1 'unknown'), so the padding loop never fires.

Refs #46

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mirrors the zerohop_protobuf fix for JSON-encoded packets. Consumers
computing hops-taken from hop_start (or hop_start - hops_away) would
otherwise see a non-zero value and could render the same ghost hops
that motivated the protobuf fix.

Refs #46
The synthetic envelope round-trip already verified hop_limit was
zeroed; extend it to also verify hop_start ends at 0, and pass an
explicit hop_start=3 in construction so the assertion has bite.

Refs #46
End-to-end verification through ExHook + EMQX that floodgate zeros
hop_start alongside hop_limit. Local Docker verification is constrained
on this host (k3s networking); CI is authoritative.

Refs #46
Updates the lead description, before/after examples, config table
entry, and JSON-mirror note to reflect that both hop_limit and
hop_start are now zeroed. Per-message log examples are unchanged
because they show original pre-modification sender values for
observability.

Refs #46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: zerohop inflates traceroute hop count and shows 'Meshtastic ffff (ffff)' ghost hops

1 participant