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)

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

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 Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an optional relaySource parameter (const meshtastic_MeshPacket *) to allocAckNak and sendAckNak across MeshModule, RoutingModule, and Router. When provided, the relay node ID and overheard link metrics (rx_rssi, rx_snr) are copied into the ACK/NAK packet. ReliableRouter passes the received packet as relaySource when generating implicit ACKs for overheard rebroadcasts.

Changes

Relay source metadata in ACK/NAK packets

Layer / File(s) Summary
Signature updates across headers
src/mesh/MeshModule.h, src/modules/RoutingModule.h, src/mesh/Router.h
Adds optional const meshtastic_MeshPacket *relaySource = nullptr parameter to allocAckNak and sendAckNak declarations, maintaining backward compatibility.
Implementation: propagate and embed relay metadata
src/mesh/MeshModule.cpp, src/modules/RoutingModule.cpp, src/mesh/Router.cpp
Updates method implementations to accept and forward relaySource; MeshModule::allocAckNak conditionally copies relay_node, rx_rssi, and rx_snr from relaySource into the allocated ACK/NAK packet.
ReliableRouter callsite
src/mesh/ReliableRouter.cpp
Implicit ACK generation for overheard rebroadcasts now passes the received packet p as relaySource to sendAckNak.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A packet hops through the mesh with grace,
The relay's signal leaves a trace—
RSSI and SNR tucked inside,
The ACK now carries the overheard ride.
🐇✨

🚥 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
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding relay node info for outbound packets.
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.
Description check ✅ Passed The PR description includes a clear summary, client compatibility notes, and attestations, with only minor template items omitted.

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");

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