diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index e29c596df4..2ea882c782 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -28,6 +28,10 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) // cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater! if (Router::cancelSending(p->from, p->id)) txRelayCanceled++; + } else if (iface && p->hop_limit > 0) { + // If we overhear a duplicate copy of the packet with more hops left than the one we are waiting to + // rebroadcast, then update the hop limit of the packet currently sitting in the TX queue. + iface->clampHopsToMax(getFrom(p), p->id, p->hop_limit - 1); } /* If the original transmitter is doing retransmissions (hopStart equals hopLimit) for a reliable transmission, e.g., when diff --git a/src/mesh/MeshPacketQueue.cpp b/src/mesh/MeshPacketQueue.cpp index 99ef41c1e4..ecbb3ed442 100644 --- a/src/mesh/MeshPacketQueue.cpp +++ b/src/mesh/MeshPacketQueue.cpp @@ -93,6 +93,19 @@ meshtastic_MeshPacket *MeshPacketQueue::getFront() return p; } +/** Attempt to find a packet in this queue. Returns a pointer to the found packet, or NULL if not found. */ +meshtastic_MeshPacket *MeshPacketQueue::find(NodeNum from, PacketId id) +{ + for (auto it = queue.begin(); it != queue.end(); it++) { + auto p = (*it); + if (getFrom(p) == from && p->id == id) { + return p; + } + } + + return NULL; +} + /** Attempt to find and remove a packet from this queue. Returns a pointer to the removed packet, or NULL if not found */ meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id) { diff --git a/src/mesh/MeshPacketQueue.h b/src/mesh/MeshPacketQueue.h index 3c28fc5ce7..a26169bd77 100644 --- a/src/mesh/MeshPacketQueue.h +++ b/src/mesh/MeshPacketQueue.h @@ -35,6 +35,9 @@ class MeshPacketQueue meshtastic_MeshPacket *getFront(); + /** Attempt to find a packet in this queue. Returns a pointer to the found packet, or NULL if not found. */ + meshtastic_MeshPacket *find(NodeNum from, PacketId id); + /** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */ meshtastic_MeshPacket *remove(NodeNum from, PacketId id); }; diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h index 89a4c70879..0e2d267b9e 100644 --- a/src/mesh/RadioInterface.h +++ b/src/mesh/RadioInterface.h @@ -176,6 +176,9 @@ class RadioInterface /** The delay to use when we want to flood a message. Use a weighted scale based on SNR */ uint32_t getTxDelayMsecWeighted(float snr); + /** Clamp the hop limit to the greater of the hop count provided, or the hop count in the queue */ + virtual void clampHopsToMax(NodeNum from, PacketId id, uint32_t hop_limit) { return; } + /** * Calculate airtime per * https://www.rs-online.com/designspark/rel-assets/ds-assets/uploads/knowledge-items/application-notes-for-the-internet-of-things/LoRa%20Design%20Guide.pdf diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 5f82a41ced..31f950699d 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -336,6 +336,18 @@ void RadioLibInterface::startTransmitTimerSNR(float snr) } } +/** + * Clamp the hop limit to the greater of the hop count provided, or the hop count in the queue + */ +void RadioLibInterface::clampHopsToMax(NodeNum from, PacketId id, uint32_t hop_limit) +{ + meshtastic_MeshPacket *p = txQueue.find(from, id); + if (p && p->hop_limit < hop_limit) { + LOG_DEBUG("Increasing hop limit for packet from %d to %d", p->hop_limit, hop_limit); + p->hop_limit = hop_limit; + } +} + void RadioLibInterface::handleTransmitInterrupt() { // This can be null if we forced the device to enter standby mode. In that case diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index a5c2e30ddc..3269be3653 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -200,4 +200,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified virtual void setStandby(); const char *radioLibErr = "RadioLib err="; + + /** + * Clamp the hop limit to the greater of the hop count provided, or the hop count in the queue + */ + void clampHopsToMax(NodeNum from, PacketId id, uint32_t hop_limit); }; \ No newline at end of file