Don't cancel relay if we were the assigned next-hop

This commit is contained in:
GUVWAF 2024-11-27 19:44:19 +01:00
parent 017bff8be7
commit 0952c861ae
4 changed files with 22 additions and 10 deletions

View File

@ -22,6 +22,8 @@ ErrorCode FloodingRouter::send(meshtastic_MeshPacket *p)
bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
{ {
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record 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 /* 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. */ 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; 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) void FloodingRouter::perhapsCancelDupe(const meshtastic_MeshPacket *p)
{ {
printPacket("Ignore dupe incoming msg", p);
rxDupe++;
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER && if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) { config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
// cancel rebroadcast of this message *if* there was already one, unless we're a router/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; tosend->hop_limit = 2;
} }
#endif #endif
tosend->next_hop = NO_NEXT_HOP_PREFERENCE; // this should already be the case, but just in case
LOG_INFO("Rebroadcast received floodmsg"); LOG_INFO("Rebroadcast received floodmsg");
// Note: we are careful to resend using the original senders node id // Note: we are careful to resend using the original senders node id

View File

@ -31,7 +31,10 @@ ErrorCode NextHopRouter::send(meshtastic_MeshPacket *p)
bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
{ {
bool wasFallback = false; 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); stopRetransmission(p->from, p->id);
// If it was a fallback to flooding, try to relay again // 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 (isRepeated) {
if (!findInTxQueue(p->from, p->id) && !perhapsRelay(p) && isToUs(p) && p->want_ack) 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); sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
} else { } else if (!weWereNextHop) {
perhapsCancelDupe(p); // If it's a dupe, cancel relay perhapsCancelDupe(p); // If it's a dupe, cancel relay if we were not explicitly asked to relay
} }
} }
return true; return true;

View File

@ -16,7 +16,7 @@ PacketHistory::PacketHistory()
/** /**
* Update recentBroadcasts and return true if we have already seen this packet * 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) { if (p->id == 0) {
LOG_DEBUG("Ignore message with zero id"); LOG_DEBUG("Ignore message with zero id");
@ -43,26 +43,32 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd
if (seenRecently) { if (seenRecently) {
LOG_DEBUG("Found existing packet record for fr=0x%x,to=0x%x,id=0x%x", p->from, p->to, p->id); 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 (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 // 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 // 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. // it now.
uint8_t ourRelayID = nodeDB->getLastByteOfNodeNum(nodeDB->getNodeNum());
if (found->sender != nodeDB->getNodeNum() && found->next_hop != NO_NEXT_HOP_PREFERENCE && 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) && found->next_hop != ourRelayID && p->next_hop == NO_NEXT_HOP_PREFERENCE && wasRelayer(p->relay_node, found) &&
!wasRelayer(ourRelayID, found) && !wasRelayer(found->next_hop, found)) { !wasRelayer(ourRelayID, found) && !wasRelayer(found->next_hop, found)) {
*wasFallback = true; *wasFallback = true;
} }
} }
// Check if we were the next hop for this packet
if (weWereNextHop) {
*weWereNextHop = found->next_hop == ourRelayID;
}
} }
if (withUpdate) { 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 // Add the existing relayed_by to the new record
for (uint8_t i = 0; i < NUM_RELAYERS - 1; i++) { for (uint8_t i = 0; i < NUM_RELAYERS - 1; i++) {
if (found->relayed_by[i]) if (found->relayed_by[i])
r.relayed_by[i + 1] = found->relayed_by[i]; r.relayed_by[i + 1] = found->relayed_by[i];
} }
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.erase(found); // as unsorted_set::iterator is const (can't update - so re-insert..)
} }
recentPackets.insert(r); recentPackets.insert(r);

View File

@ -46,8 +46,10 @@ class PacketHistory
* *
* @param withUpdate if true and not found we add an entry to recentPackets * @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 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 /* 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 */ * @return true if node was indeed a relayer, false if not */