Skip to content

Provide relay node info for outbound packets - #10767

Open
alecperkins wants to merge 1 commit into
meshtastic:developfrom
alecperkins:relay-info
Open

Provide relay node info for outbound packets#10767
alecperkins wants to merge 1 commit into
meshtastic:developfrom
alecperkins:relay-info

Conversation

@alecperkins

@alecperkins alecperkins commented Jun 23, 2026

Copy link
Copy Markdown

This provides the relay info in the implicit ack response to phones so the phone can know who relayed the node's own outbound packets.

Apps can then use this to show more details about which infrastructure is servicing the user’s node.

The stock 2.7.15 (2074) meshtastic/Meshtastic-Apple app, for instance:
IMG_3059

Client compatibility

  • Android: simple count
  • Apple: shows relayer and count
  • Web: does not show relay at all

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3
    • LilyGo T-Deck
    • LilyGo T-Beam
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card
    • Other (please specify below)

Summary by CodeRabbit

  • New Features

    • ACK/NACK packets can now include relay-related details from overheard packets, including the relaying node ID and received signal metrics.
  • Bug Fixes

    • Implicit acknowledgements generated from overheard rebroadcasts now carry richer routing context, improving attribution and visibility while preserving existing hop-limit and priority behavior.
    • Relay information is retained when acknowledgements are forwarded, providing more accurate details about the packet’s path and reception conditions.

@github-actions

Copy link
Copy Markdown
Contributor

@alecperkins, Welcome to Meshtastic!

Thanks for opening your first pull request. We really appreciate it.

We discuss work as a team in discord, please join us in the #firmware channel.
There's a big backlog of patches at the moment. If you have time,
please help us with some code review and testing of other PRs!

Welcome to the team 😄

Copilot AI 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.

Pull request overview

This PR extends the routing/phone notification path so clients can learn which nodes relayed a packet (including subsequent relays), by attaching relay identity + link metrics to implicit ACKs for outbound packets and by forwarding relay-info-only duplicates to the phone.

Changes:

  • Extend ACK/NAK allocation/sending APIs to optionally carry relay metadata from an observed packet.
  • Generate implicit ACK notifications for each overheard rebroadcast of our outbound packets, carrying the relayer + RSSI/SNR + hop fields.
  • When a duplicate incoming packet is ignored (not rebroadcast), forward a decoded copy to the phone so it can learn additional relayers.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/modules/RoutingModule.h Extends sendAckNak/allocAckNak to accept an optional relay-source packet.
src/modules/RoutingModule.cpp Threads the new relaySource parameter through to MeshModule::allocAckNak().
src/mesh/Router.h Extends sendAckNak signature and adds notifyPhoneOfRelayDupe() API for relay-only dupe forwarding.
src/mesh/Router.cpp Implements relay-dupe forwarding by copying, decoding, and sending the packet to the phone.
src/mesh/ReliableRouter.cpp Emits implicit-ack notifications on every overheard rebroadcast of our outbound packets (including later relays).
src/mesh/NextHopRouter.cpp Calls notifyPhoneOfRelayDupe() on duplicate packets so the phone can learn additional relayers.
src/mesh/MeshModule.h Extends allocAckNak() to accept an optional relay-source packet.
src/mesh/MeshModule.cpp Copies relay identity + RSSI/SNR + hop fields into the locally-delivered implicit ACK when relaySource is provided.
src/mesh/FloodingRouter.cpp Calls notifyPhoneOfRelayDupe() on duplicate packets so the phone can learn additional relayers.

Comment thread src/mesh/ReliableRouter.cpp Outdated
Comment on lines +58 to +61
// Use the channel of our original pending packet when we still have it. Otherwise (a plain
// broadcast with no pending retransmission, or a subsequent relayer after we already cleared it)
// the overheard copy only carries the channel hash, not a usable index, so fall back to primary.
ChannelIndex ackChannel = old ? old->packet->channel : channels.getPrimaryIndex();

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Applied in 013e0e5.

@alecperkins
alecperkins marked this pull request as ready for review June 24, 2026 01:01
@garthvh
garthvh requested a review from thebentern June 27, 2026 06:55
@garthvh

garthvh commented Jun 27, 2026

Copy link
Copy Markdown
Member

Not sure I love this approach, sending the same packet over the phone api multiple times seems like a problematic pattern, especially for diagnostic only data.

@alecperkins

alecperkins commented Jun 27, 2026

Copy link
Copy Markdown
Author

Is there a better way to provide it to the phone? It's info the node already has, that clients may find useful or can ignore if they don't.

I wouldn't call it diagnostic exactly, more a revelation of how the mesh functions at a fundamental level. "Who is hearing me?" and "How am I hearing this?" are useful information for users as they move about, or as the mesh changes around them. And it's a FAQ from those getting set up that's often hard to answer. The apps even already seem to expect the outbound relay, it just wasn't working before.

Edit: and traceroutes are a special case where the packets are not duplicates. Each transmission carries different and useful information. Path diversity is a critical concept for making a well-functioning mesh, so it's helpful to illustrate it rather than obscure it. screenshot showing an outbound traceroute with three different inbound response paths that vary

@garthvh garthvh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The need to immediately patch every client to prevent duplicate messages is a no go, this needs to be rethought. I would suggest that this is maybe a routing packet.

@alecperkins

Copy link
Copy Markdown
Author

The need to immediately patch every client to prevent duplicate messages is a no go, this needs to be rethought. I would suggest that this is maybe a routing packet.

@garthvh without the dupe notifications, is the addition of relay characteristics to the ack message acceptable? Being able to known outbound relays is the more important and more frequent feature request.

@garthvh

garthvh commented Jun 30, 2026

Copy link
Copy Markdown
Member

We can't send duplicate messages, that approach is not going to work.

@coderabbitai

coderabbitai Bot commented Jun 30, 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: d76cfff5-b1e2-4011-ad42-6aff803bdbcc

📥 Commits

Reviewing files that changed from the base of the PR and between bcf486f and 6ae0d51.

📒 Files selected for processing (7)
  • src/mesh/MeshModule.cpp
  • src/mesh/MeshModule.h
  • src/mesh/ReliableRouter.cpp
  • src/mesh/Router.cpp
  • src/mesh/Router.h
  • src/modules/RoutingModule.cpp
  • src/modules/RoutingModule.h
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/mesh/ReliableRouter.cpp
  • src/mesh/MeshModule.h
  • src/mesh/Router.h
  • src/mesh/MeshModule.cpp
  • src/modules/RoutingModule.cpp
  • src/modules/RoutingModule.h
  • src/mesh/Router.cpp

📝 Walkthrough

Walkthrough

Adds an optional relaySource parameter to ACK/NAK allocation and sending across MeshModule, RoutingModule, and Router. When provided, the generated packet copies relay node ID and received RSSI/SNR. ReliableRouter passes the overheard packet to the implicit ACK path.

Changes

Relay source in ACK/NAK flow

Layer / File(s) Summary
ACK/NAK signature updates
src/mesh/MeshModule.h, src/modules/RoutingModule.h, src/mesh/Router.h
Adds optional relaySource parameters to ACK/NAK allocation and sending declarations.
Relay metadata propagation
src/mesh/Router.cpp, src/modules/RoutingModule.cpp, src/mesh/MeshModule.cpp
Forwards relaySource through the ACK/NAK path. MeshModule::allocAckNak copies relay_node, rx_rssi, and rx_snr when provided.
Implicit ACK callsite
src/mesh/ReliableRouter.cpp
Passes the overheard rebroadcast packet as relaySource when generating an implicit ACK.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ReliableRouter
  participant Router
  participant RoutingModule
  participant MeshModule
  ReliableRouter->>Router: sendAckNak(..., relaySource)
  Router->>RoutingModule: sendAckNak(..., relaySource)
  RoutingModule->>MeshModule: allocAckNak(..., relaySource)
  MeshModule-->>RoutingModule: ACK/NAK with relay metadata
Loading

Possibly related PRs

Suggested reviewers: thebentern

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description explains the change, client compatibility, and testing status, and includes the required attestations.
Title check ✅ Passed The title clearly describes the main change: adding relay node information to outbound packet acknowledgments.
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.

@alecperkins alecperkins changed the title Provide relay info for outbound packets and about subsequent relays Provide relay node info for outbound packets Jun 30, 2026
@alecperkins

Copy link
Copy Markdown
Author

We can't send duplicate messages…

Right, I mean the addition of the relay info to the existing implicit ack notice, so the clients can know who gave them the implicit ack. I've stripped out the duplicate portion so this change is only that addition: 6555721.

Though I will note clients are already expecting to be notified about duplicates, because it’s a reasonable assumption, and already dedupe by mesh packet ID. Some of them even are relying on this in their UI, so arguably the current firmware behavior is defective from their perspective.

For example, the stock Android and Apple apps connected to a node running the now-removed changes:

IMG_3177 IMG_3179

Versus the stock Apple and 2.7.15 fw:

IMG_3182

Even though that packet was definitely RX'd at this location multiple times:

Screenshot 2026-06-30 at 08 29 44

The only change the Apple app needed for the multiple notices was a fix to prevent duplicate push notifications, it otherwise already tolerated and assumed it might hear the same packet repeatedly.

@GUVWAF GUVWAF left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The current implementation without duplicated packets looks fine to me.

Some of them even are relying on this in their UI, so arguably the current firmware behavior is defective from their perspective.

This is true, currently you only get the implicit ACK when it's still in the list of "pending packets" (i.e. retransmissions), where it will be deleted after the first rebroadcast is overheard:

auto old = findPendingPacket(key);
if (old) {
LOG_DEBUG("Generate implicit ack");

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Firmware Size Report

42 targets | vs develop: 21 increased, 1 decreased, net +439,548 (+429.2 KB)

Target Flash vs develop RAM RAM vs develop
picow 1,274,564 📈 +29,684 (+29.0 KB) 152,508 n/a
pico2w 1,249,000 📈 +28,484 (+27.8 KB) 158,988 n/a
rak11310 833,632 📈 +28,208 (+27.5 KB) 86,320 n/a
pico 810,880 📈 +28,192 (+27.5 KB) 85,876 n/a
seeed_xiao_rp2040 809,096 📈 +28,192 (+27.5 KB) 85,868 n/a
Show 37 more target(s)
Target Flash vs develop RAM RAM vs develop
seeed_xiao_rp2350 795,136 📈 +27,200 (+26.6 KB) 92,368 n/a
pico2 796,968 📈 +27,192 (+26.6 KB) 92,376 n/a
elecrow-adv-35-tft 3,439,408 📈 +22,784 (+22.2 KB) 94,632 n/a
heltec-vision-master-e213-inkhud 2,249,888 📈 +22,528 (+22.0 KB) 92,408 n/a
t-deck-tft 3,833,104 📈 +22,432 (+21.9 KB) 108,008 n/a
rak3312 2,290,928 📈 +18,688 (+18.2 KB) 102,040 n/a
heltec-ht62-esp32c3-sx1262 2,153,248 📈 +18,256 (+17.8 KB) 112,004 n/a
seeed-xiao-s3 2,294,192 📈 +18,048 (+17.6 KB) 102,064 n/a
station-g2 2,284,176 📈 +17,824 (+17.4 KB) 101,848 n/a
station-g3 2,284,176 📈 +17,824 (+17.4 KB) 101,848 n/a
heltec-v3 2,281,824 📈 +17,744 (+17.3 KB) 130,232 n/a
rak11200 1,878,352 📈 +17,744 (+17.3 KB) 87,052 n/a
t-eth-elite 2,508,416 📈 +16,928 (+16.5 KB) 103,068 n/a
heltec-v4 2,294,016 📈 +16,720 (+16.3 KB) 101,112 n/a
tlora-c6 2,384,976 📈 +16,672 (+16.3 KB) 102,772 n/a
rak3172 183,012 📉 -3,284 (-3.2 KB) 25,008 n/a
wio-e5 240,116 📈 +1,488 (+1.5 KB) 26,640 n/a
heltec-mesh-node-t096 750,464 110,492 n/a
heltec-mesh-node-t1 748,336 102,236 n/a
heltec-mesh-node-t114 748,280 110,428 n/a
heltec-mesh-solar 745,352 110,596 n/a
heltec-mesh-solar-eink 737,256 109,916 n/a
heltec-mesh-solar-inkhud 717,880 101,372 n/a
heltec-mesh-solar-oled 745,448 110,596 n/a
heltec-mesh-solar-tft 751,752 110,692 n/a
heltec-mesh-tower-v2 736,440 101,452 n/a
meshnology_w10 2,464,560 136,212 n/a
rak4631 766,344 104,500 n/a
rak_wismeshtag 600,240 92,604 n/a
seeed_mesh_tracker_X1 507,312 87,316 n/a
seeed_wio_tracker_L1 739,928 110,340 n/a
seeed_xiao_nrf52840_kit 734,680 102,060 n/a
t-echo 753,456 93,236 n/a
t-echo-inkhud 713,320 83,956 n/a
t-echo-plus 751,160 93,236 n/a
t-impulse-plus 726,936 110,324 n/a
tracker-t1000-e 506,400 87,316 n/a

Size budgets

Env Metric Measured Budget Used
rak4631 RAM (.data+.bss) 104,500 113,000 92.5%
rak4631 flash 766,344 786,000 97.5%

Budgets live in bin/ram_budgets.json and are raised deliberately in the PR that needs the headroom - never automatically.


Updated for 2b09d81

@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.

🧹 Nitpick comments (1)
src/mesh/Router.cpp (1)

883-886: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Shorten the explanatory comment.

This four-line comment exceeds the repository’s one- or two-line maximum; condense it to the essential rationale or remove details that are apparent from the code. As per coding guidelines: “Keep code comments minimal: one or two lines maximum, only when the reason is not obvious.”

🤖 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/mesh/Router.cpp` around lines 883 - 886, Condense the explanatory comment
above the post-decode hop_start check to one or two lines, retaining only the
essential rationale that unknown hop_start identifies pre-hop firmware packets
and local-origin packets are exempt; remove the detailed processing-destination
list.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@src/mesh/Router.cpp`:
- Around line 883-886: Condense the explanatory comment above the post-decode
hop_start check to one or two lines, retaining only the essential rationale that
unknown hop_start identifies pre-hop firmware packets and local-origin packets
are exempt; remove the detailed processing-destination list.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f56ad487-f4b1-4381-8ae6-3720ea4814ed

📥 Commits

Reviewing files that changed from the base of the PR and between ae7292b and 74a4276.

📒 Files selected for processing (2)
  • src/mesh/ReliableRouter.cpp
  • src/mesh/Router.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/mesh/ReliableRouter.cpp

When we overhear another node rebroadcast one of our own packets, we
generate an implicit-ack ROUTING packet for the local sending process.
That ack is delivered locally to the phone, so pass the overheard
rebroadcast as a relay source and copy its relay_node and the rx_rssi /
rx_snr we heard it at onto the ack. This lets the connected client see
which node relayed our packet and the link quality, instead of only
learning that the packet was repeated.

allocAckNak / sendAckNak gain an optional relaySource parameter. The
ack is sent to ourselves (to == us), so Router::send() is bypassed and
does not overwrite these fields with our own.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@alecperkins
alecperkins requested a review from garthvh August 11, 2026 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request first-contribution needs-review Needs human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants