diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index 64280f3fe..bf106a55e 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -31,8 +31,11 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) 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); + // rebroadcast, then remove the packet currently sitting in the TX queue and use this one instead. + if (iface->removePendingTXPacket(getFrom(p), p->id, p->hop_limit - 1)) { + LOG_DEBUG("Processing packet %d again for rebroadcast with with better hop limit (%d)", p->hop_limit - 1); + return false; + } } if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE && iface) { iface->clampToLateRebroadcastWindow(getFrom(p), p->id); diff --git a/src/mesh/MeshPacketQueue.cpp b/src/mesh/MeshPacketQueue.cpp index 282d27b40..6bf9b915f 100644 --- a/src/mesh/MeshPacketQueue.cpp +++ b/src/mesh/MeshPacketQueue.cpp @@ -113,11 +113,12 @@ meshtastic_MeshPacket *MeshPacketQueue::find(NodeNum from, PacketId id) } /** 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, bool tx_normal, bool tx_late) +meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id, bool tx_normal, bool tx_late, uint8_t hop_limit_lt) { for (auto it = queue.begin(); it != queue.end(); it++) { auto p = (*it); - if (getFrom(p) == from && p->id == id && ((tx_normal && !p->tx_after) || (tx_late && p->tx_after))) { + if (getFrom(p) == from && p->id == id && ((tx_normal && !p->tx_after) || (tx_late && p->tx_after)) && + (!hop_limit_lt || p->hop_limit < hop_limit_lt)) { queue.erase(it); return p; } diff --git a/src/mesh/MeshPacketQueue.h b/src/mesh/MeshPacketQueue.h index 578280ef7..b76aee583 100644 --- a/src/mesh/MeshPacketQueue.h +++ b/src/mesh/MeshPacketQueue.h @@ -39,5 +39,6 @@ class MeshPacketQueue 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, bool tx_normal = true, bool tx_late = true); + meshtastic_MeshPacket *remove(NodeNum from, PacketId id, bool tx_normal = true, bool tx_late = true, + uint8_t hop_limit_lt = 0); }; \ No newline at end of file diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h index 90f958c00..acb923a4f 100644 --- a/src/mesh/RadioInterface.h +++ b/src/mesh/RadioInterface.h @@ -185,8 +185,11 @@ class RadioInterface /** If the packet is not already in the late rebroadcast window, move it there */ virtual void clampToLateRebroadcastWindow(NodeNum from, PacketId id) { return; } - /** 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; } + /** + * If there is a packet pending TX in the queue with a worse hop limit, remove it pending replacement with a better version + * @return Whether a pending packet was removed + */ + bool removePendingTXPacket(NodeNum from, PacketId id, uint32_t hop_limit_lt) { return false; } /** * Calculate airtime per diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 7b972cad4..c99aa756b 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -345,17 +345,25 @@ void RadioLibInterface::clampToLateRebroadcastWindow(NodeNum from, PacketId id) } /** - * Clamp the hop limit to the greater of the hop count provided, or the hop count in the queue + * If there is a packet pending TX in the queue with a worse hop limit, remove it pending replacement with a better version + * @return Whether a pending packet was removed */ -void RadioLibInterface::clampHopsToMax(NodeNum from, PacketId id, uint32_t hop_limit) +bool RadioLibInterface::removePendingTXPacket(NodeNum from, PacketId id, uint32_t hop_limit_lt) { - 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; + meshtastic_MeshPacket *p = txQueue.remove(from, id, true, true, hop_limit_lt); + if (p) { + LOG_DEBUG("Dropping pending-TX packet %d with hop limit %d", p->id, p->hop_limit); + packetPool.release(p); + return true; } + return false; } +/** + * Remove a packet that is eligible for replacement from the TX queue + */ +// void RadioLibInterface::removePending + 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 affb00609..c819ae4eb 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -206,7 +206,8 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified void clampToLateRebroadcastWindow(NodeNum from, PacketId id); /** - * Clamp the hop limit to the greater of the hop count provided, or the hop count in the queue + * If there is a packet pending TX in the queue with a worse hop limit, remove it pending replacement with a better version + * @return Whether a pending packet was removed */ - void clampHopsToMax(NodeNum from, PacketId id, uint32_t hop_limit); + bool removePendingTXPacket(NodeNum from, PacketId id, uint32_t hop_limit_lt); }; \ No newline at end of file