If a packet is heard multiple times, rebroadcast using the highest hop limit

Sometimes a packet will be in the TX queue waiting to be transmitted,
when it is overheard being rebroadcast by another node, with a higher
hop limit remaining. When this occurs, modify the pending packet in
the TX queue to avoid unnecessarily wasting hops.
This commit is contained in:
Steve Gilberd 2024-12-28 16:13:41 +13:00
parent b2808063d0
commit 97751df3ea
No known key found for this signature in database
GPG Key ID: 3CA3675E3C90637F
6 changed files with 40 additions and 0 deletions

View File

@ -29,6 +29,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 (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE && iface) {
iface->clampToLateRebroadcastWindow(getFrom(p), p->id);

View File

@ -99,6 +99,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, bool tx_normal, bool tx_late)
{

View File

@ -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, bool tx_normal = true, bool tx_late = true);
};

View File

@ -185,6 +185,9 @@ 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; }
/**
* 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

View File

@ -344,6 +344,18 @@ 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
*/
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

View File

@ -204,4 +204,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
* If the packet is not already in the late rebroadcast window, move it there
*/
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
*/
void clampHopsToMax(NodeNum from, PacketId id, uint32_t hop_limit);
};