From 0952c861ae4dee53df463169d7766d3fa1b8e0d5 Mon Sep 17 00:00:00 2001 From: GUVWAF Date: Wed, 27 Nov 2024 19:44:19 +0100 Subject: [PATCH] Don't cancel relay if we were the assigned next-hop --- src/mesh/FloodingRouter.cpp | 5 +++-- src/mesh/NextHopRouter.cpp | 9 ++++++--- src/mesh/PacketHistory.cpp | 14 ++++++++++---- src/mesh/PacketHistory.h | 4 +++- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index e177d3883..6f47a8102 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -22,6 +22,8 @@ ErrorCode FloodingRouter::send(meshtastic_MeshPacket *p) bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) { if (wasSeenRecently(p)) { // Note: this will also add a recent packet record + printPacket("Ignore dupe incoming msg", p); + rxDupe++; /* If the original transmitter is doing retransmissions (hopStart equals hopLimit) for a reliable transmission, e.g., when the ACK got lost, we will handle the packet again to make sure it gets an implicit ACK. */ bool isRepeated = p->hop_start > 0 && p->hop_start == p->hop_limit; @@ -42,8 +44,6 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) void FloodingRouter::perhapsCancelDupe(const meshtastic_MeshPacket *p) { - printPacket("Ignore dupe incoming msg", p); - rxDupe++; if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER && config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) { // cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater! @@ -73,6 +73,7 @@ void FloodingRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p) tosend->hop_limit = 2; } #endif + tosend->next_hop = NO_NEXT_HOP_PREFERENCE; // this should already be the case, but just in case LOG_INFO("Rebroadcast received floodmsg"); // Note: we are careful to resend using the original senders node id diff --git a/src/mesh/NextHopRouter.cpp b/src/mesh/NextHopRouter.cpp index a7dff63f6..3c010eb6b 100644 --- a/src/mesh/NextHopRouter.cpp +++ b/src/mesh/NextHopRouter.cpp @@ -31,7 +31,10 @@ ErrorCode NextHopRouter::send(meshtastic_MeshPacket *p) bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) { bool wasFallback = false; - if (wasSeenRecently(p, true, &wasFallback)) { // Note: this will also add a recent packet record + bool weWereNextHop = false; + if (wasSeenRecently(p, true, &wasFallback, &weWereNextHop)) { // Note: this will also add a recent packet record + printPacket("Ignore dupe incoming msg", p); + rxDupe++; stopRetransmission(p->from, p->id); // If it was a fallback to flooding, try to relay again @@ -46,8 +49,8 @@ bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) if (isRepeated) { if (!findInTxQueue(p->from, p->id) && !perhapsRelay(p) && isToUs(p) && p->want_ack) sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0); - } else { - perhapsCancelDupe(p); // If it's a dupe, cancel relay + } else if (!weWereNextHop) { + perhapsCancelDupe(p); // If it's a dupe, cancel relay if we were not explicitly asked to relay } } return true; diff --git a/src/mesh/PacketHistory.cpp b/src/mesh/PacketHistory.cpp index 73c3d56f1..15fa9cdcd 100644 --- a/src/mesh/PacketHistory.cpp +++ b/src/mesh/PacketHistory.cpp @@ -16,7 +16,7 @@ PacketHistory::PacketHistory() /** * Update recentBroadcasts and return true if we have already seen this packet */ -bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpdate, bool *wasFallback) +bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpdate, bool *wasFallback, bool *weWereNextHop) { if (p->id == 0) { LOG_DEBUG("Ignore message with zero id"); @@ -43,27 +43,33 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd if (seenRecently) { LOG_DEBUG("Found existing packet record for fr=0x%x,to=0x%x,id=0x%x", p->from, p->to, p->id); + uint8_t ourRelayID = nodeDB->getLastByteOfNodeNum(nodeDB->getNodeNum()); if (wasFallback) { // If it was seen with a next-hop not set to us and now it's NO_NEXT_HOP_PREFERENCE, and the relayer relayed already // before, it's a fallback to flooding. If we didn't already relay and the next-hop neither, we might need to handle // it now. - uint8_t ourRelayID = nodeDB->getLastByteOfNodeNum(nodeDB->getNodeNum()); if (found->sender != nodeDB->getNodeNum() && found->next_hop != NO_NEXT_HOP_PREFERENCE && found->next_hop != ourRelayID && p->next_hop == NO_NEXT_HOP_PREFERENCE && wasRelayer(p->relay_node, found) && !wasRelayer(ourRelayID, found) && !wasRelayer(found->next_hop, found)) { *wasFallback = true; } } + + // Check if we were the next hop for this packet + if (weWereNextHop) { + *weWereNextHop = found->next_hop == ourRelayID; + } } if (withUpdate) { - if (found != recentPackets.end()) { // delete existing to updated timestamp and next-hop/relayed_by (re-insert) + if (found != recentPackets.end()) { // delete existing to updated timestamp and relayed_by (re-insert) // Add the existing relayed_by to the new record for (uint8_t i = 0; i < NUM_RELAYERS - 1; i++) { if (found->relayed_by[i]) r.relayed_by[i + 1] = found->relayed_by[i]; } - recentPackets.erase(found); // as unsorted_set::iterator is const (can't update - so re-insert..) + r.next_hop = found->next_hop; // keep the original next_hop (such that we check whether we were originally asked) + recentPackets.erase(found); // as unsorted_set::iterator is const (can't update - so re-insert..) } recentPackets.insert(r); LOG_DEBUG("Add packet record fr=0x%x, id=0x%x", p->from, p->id); diff --git a/src/mesh/PacketHistory.h b/src/mesh/PacketHistory.h index 15c071da7..86d901d6c 100644 --- a/src/mesh/PacketHistory.h +++ b/src/mesh/PacketHistory.h @@ -46,8 +46,10 @@ class PacketHistory * * @param withUpdate if true and not found we add an entry to recentPackets * @param wasFallback if not nullptr, packet will be checked for fallback to flooding and value will be set to true if so + * @param weWereNextHop if not nullptr, packet will be checked for us being the next hop and value will be set to true if so */ - bool wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpdate = true, bool *wasFallback = nullptr); + bool wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpdate = true, bool *wasFallback = nullptr, + bool *weWereNextHop = nullptr); /* Check if a certain node was a relayer of a packet in the history given an ID and sender * @return true if node was indeed a relayer, false if not */