Skip to content

Limit NodeInfo discovery replies to direct neighbors#11131

Draft
RCGV1 wants to merge 8 commits into
meshtastic:developfrom
RCGV1:codex/nodeinfo-direct-neighbor-discovery
Draft

Limit NodeInfo discovery replies to direct neighbors#11131
RCGV1 wants to merge 8 commits into
meshtastic:developfrom
RCGV1:codex/nodeinfo-direct-neighbor-discovery

Conversation

@RCGV1

@RCGV1 RCGV1 commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

  • send broadcast NodeInfo discovery requests with a zero hop limit
  • accept NodeInfo discovery replies only for direct radio receptions and force their replies to zero hops
  • keep unicast NodeInfo exchange behavior unchanged, and suppress NAKs for relayed or unknown-hop discovery copies

Validation

  • trunk check
  • pio test -e native -f test_mesh_module (blocked before test compilation on macOS: Portduino requires argp.h)
  • ./bin/run-tests.sh (blocked on macOS Bash 3.2 / BSD find: mapfile and -printf unavailable)
  • pio run -e heltec-v3 (blocked by incomplete local Xtensa toolchain install; compiler not found)

Summary by CodeRabbit

  • Bug Fixes

    • Improved consistency of response hop-limit handling across modules, ensuring replies use the correct hop limit per request.
    • Updated NodeInfo behavior for broadcast discovery: only qualifying direct broadcast discovery requests now generate replies, which use a hop limit of zero; other broadcast discovery packets are ignored. Unicast NodeInfo requests keep normal routing behavior.
  • Tests

    • Extended Unity tests to validate module-controlled reply hop limits and direct vs. relayed/unknown broadcast discovery qualification, including suppression/allowance sequencing.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 75fc6cb8-1fe4-4ea4-8d90-54755076f4f1

📥 Commits

Reviewing files that changed from the base of the PR and between 4bb0f0c and 2bd54dd.

📒 Files selected for processing (1)
  • test/test_mesh_module/test_main.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/test_mesh_module/test_main.cpp

📝 Walkthrough

Walkthrough

MeshModule centralizes response hop-limit selection through an overridable hook. NodeInfoModule restricts qualifying direct broadcast discovery responses to zero hops, ignores other broadcast requests, and adds tests for these behaviors.

Changes

Response hop-limit policy

Layer / File(s) Summary
Mesh response hook
src/mesh/MeshModule.*
Adds the virtual response hop-limit hook and applies its result when allocating reply packets.
NodeInfo broadcast policy
src/modules/NodeInfoModule.*
Recognizes direct broadcast discovery requests, uses zero-hop responses for them, skips other broadcast replies, and gates suppression tracking.
Hop-limit policy tests
test/test_mesh_module/test_main.cpp
Tests response-hop overrides, discovery qualification, broadcast exclusions, unicast behavior, dispatch, fixture isolation, and suppression handling.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Requester
  participant NodeInfoModule
  participant MeshModule
  participant RoutingModule
  Requester->>NodeInfoModule: Send broadcast NodeInfo request
  NodeInfoModule->>NodeInfoModule: Check direct discovery conditions
  NodeInfoModule->>MeshModule: Allocate response
  MeshModule->>NodeInfoModule: Get response hop limit
  NodeInfoModule->>MeshModule: Return 0 for direct discovery
  MeshModule->>Requester: Send zero-hop NodeInfo response
Loading

Possibly related PRs

Suggested labels: bugfix, module, mesh

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: restricting NodeInfo discovery replies to direct neighbors.
Description check ✅ Passed The description includes a clear summary and validation notes, but omits the template's attestations section.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

⚡ Try this PR in the Web Flasher

Flash this PR in the Web Flasher

firmware commit boards expires

Warning

This is an automated, unreviewed CI test build. Back up your device configuration
before flashing, and only flash devices you are able to recover.

Supported boards built by this PR (30)
Device Board Platform
Crowpanel Adv 3.5 TFT elecrow-adv-35-tft esp32-s3
Heltec HT62 heltec-ht62-esp32c3-sx1262 esp32-c3
Heltec Mesh Node 096 heltec-mesh-node-t096 nrf52840
Heltec Mesh Node T1 heltec-mesh-node-t1 nrf52840
Heltec Mesh Node T114 heltec-mesh-node-t114 nrf52840
Heltec V3 heltec-v3 esp32-s3
Heltec V4 heltec-v4 esp32-s3
Meshnology W10 meshnology_w10 esp32-s3
Raspberry Pi Pico pico rp2040
Raspberry Pi Pico W picow rp2040
RAK WisMesh Pocket V3 rak_wismesh_pocket nrf52840
RAK WisMesh Pod rak_wismesh_pod nrf52840
RAK WisMesh Repeater Mini V2 rak_wismesh_repeater_mini nrf52840
RAK WisMesh Tag rak_wismeshtag nrf52840
RAK WisBlock 11200 rak11200 esp32
RAK WisBlock 11310 rak11310 rp2040
RAK3312 rak3312 esp32-s3
RAK WisBlock 4631 rak4631 nrf52840
Seeed SenseCAP Mesh-Tracker-X1 seeed_mesh_tracker_X1 nrf52840
Seeed Wio Tracker L1 seeed_wio_tracker_L1 nrf52840
Seeed Xiao NRF52840 Kit seeed_xiao_nrf52840_kit nrf52840
Seeed Xiao ESP32-S3 seeed-xiao-s3 esp32-s3
Station G2 station-g2 esp32-s3
Station G3 station-g3 esp32-s3
LILYGO T-Deck t-deck-tft esp32-s3
LILYGO T-Echo t-echo nrf52840
LILYGO T-Echo Plus t-echo-plus nrf52840
LILYGO T-Impulse Plus t-impulse-plus nrf52840
LilyGo T3-C6 tlora-c6 esp32-c6
Seeed SenseCAP T1000-E tracker-t1000-e nrf52840

Build artifacts expire on 2026-08-20. Updated for 2bd54dd.

@RCGV1

RCGV1 commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/test_mesh_module/test_main.cpp (1)

455-492: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an end-to-end NodeInfo regression test.

These tests exercise the predicate and hook directly, but not NodeInfoModule::allocReply() or MeshModule::sendResponse(). Add coverage for a relayed/unknown broadcast followed by a valid direct broadcast from the same sender, asserting that the direct request still receives a zero-hop reply and invalid requests produce no NAK.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/test_mesh_module/test_main.cpp` around lines 455 - 492, Add an
end-to-end NodeInfo regression test that drives relayed/unknown and valid direct
broadcast requests from the same sender through NodeInfoModule::allocReply() and
MeshModule::sendResponse(). Assert invalid requests produce no NAK, then verify
the subsequent valid direct broadcast receives a zero-hop reply, covering the
full response path rather than only NodeInfoPolicyShim.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/modules/NodeInfoModule.cpp`:
- Around line 163-169: Update handleReceivedProtobuf so rejected non-direct
broadcast requests do not update lastNodeInfoSeen before the suppression check.
Perform the isBroadcastRequest/isDirectBroadcastDiscoveryRequest qualification
before recording the request, or explicitly bypass the cache update for rejected
broadcasts, while preserving the existing ignoreRequest behavior and valid
direct-discovery reply flow.

---

Nitpick comments:
In `@test/test_mesh_module/test_main.cpp`:
- Around line 455-492: Add an end-to-end NodeInfo regression test that drives
relayed/unknown and valid direct broadcast requests from the same sender through
NodeInfoModule::allocReply() and MeshModule::sendResponse(). Assert invalid
requests produce no NAK, then verify the subsequent valid direct broadcast
receives a zero-hop reply, covering the full response path rather than only
NodeInfoPolicyShim.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2818a64d-05a4-4f29-8d3a-43ee3d2ccae0

📥 Commits

Reviewing files that changed from the base of the PR and between 6e48fac and 9e54a9f.

📒 Files selected for processing (5)
  • src/mesh/MeshModule.cpp
  • src/mesh/MeshModule.h
  • src/modules/NodeInfoModule.cpp
  • src/modules/NodeInfoModule.h
  • test/test_mesh_module/test_main.cpp

Comment thread src/modules/NodeInfoModule.cpp
@RCGV1

RCGV1 commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/modules/NodeInfoModule.cpp (1)

34-44: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Validate the request before updating suppression state.

This cache update still happens before the later is_licensed and unsigned-signed broadcast checks. A qualifying but rejected direct broadcast can therefore poison lastNodeInfoSeen and suppress the next valid discovery from that sender for 12 hours. Move suppression tracking after those rejection checks, or explicitly avoid caching rejected requests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/NodeInfoModule.cpp` around lines 34 - 44, Move the
`lastNodeInfoSeen` lookup, suppression decision, and cache update out of the
initial request block so they run only after the later `is_licensed` and
unsigned-signed broadcast rejection checks. Ensure rejected direct broadcasts do
not set `suppressReplyForCurrentRequest` or update `lastNodeInfoSeen`, while
valid discovery requests retain the existing suppression behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/modules/NodeInfoModule.cpp`:
- Around line 34-44: Move the `lastNodeInfoSeen` lookup, suppression decision,
and cache update out of the initial request block so they run only after the
later `is_licensed` and unsigned-signed broadcast rejection checks. Ensure
rejected direct broadcasts do not set `suppressReplyForCurrentRequest` or update
`lastNodeInfoSeen`, while valid discovery requests retain the existing
suppression behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 15cdbbb5-1a0a-42ba-a527-fead54ae88bb

📥 Commits

Reviewing files that changed from the base of the PR and between 9e54a9f and 31821c4.

📒 Files selected for processing (2)
  • src/modules/NodeInfoModule.cpp
  • test/test_mesh_module/test_main.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/test_mesh_module/test_main.cpp

@RCGV1

RCGV1 commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@RCGV1

RCGV1 commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@jp-bennett

Copy link
Copy Markdown
Collaborator

For a while we talked about dynamically detecting we were on a busy mesh. This seems like another optimization that should be gated to busy meshes, EG, when the nodedb is full and nodes are regularly falling off the end of the DB.

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.

2 participants