Check for hop_limit and also update next hop when hop_start == hop_limit on ACK

Also check for broadcast in `getNextHop()`
This commit is contained in:
GUVWAF 2024-11-11 10:50:36 +01:00
parent 93bcee3aab
commit 17495e7dbf
7 changed files with 25 additions and 19 deletions

View File

@ -653,7 +653,7 @@ void setup()
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
nodeDB = new NodeDB;
// If we're taking on the repeater role, use flood router and turn off 3V3_S rail because peripherals are not needed
// If we're taking on the repeater role, use NextHopRouter and turn off 3V3_S rail because peripherals are not needed
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
router = new NextHopRouter();
#ifdef PIN_3V3_EN

View File

@ -54,14 +54,13 @@ void NextHopRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtast
if (isAckorReply) {
// Update next-hop for the original transmitter of this successful transmission to the relay node, but ONLY if "from" is
// not 0 (means implicit ACK) and original packet was also relayed by this node, or we sent it directly to the destination
if (p->from != 0 && p->relay_node) {
if (p->from != 0) {
meshtastic_NodeInfoLite *origTx = nodeDB->getMeshNode(p->from);
if (origTx) {
// Either relayer of ACK was also a relayer of the packet, or we were the relayer and the ACK came directly from
// the destination
if (wasRelayer(p->relay_node, p->decoded.request_id, p->to) ||
(wasRelayer(ourRelayID, p->decoded.request_id, p->to) &&
p->relay_node == nodeDB->getLastByteOfNodeNum(p->from))) {
(wasRelayer(ourRelayID, p->decoded.request_id, p->to) && p->hop_start != 0 && p->hop_start == p->hop_limit)) {
if (origTx->next_hop != p->relay_node) { // Not already set
LOG_INFO("Update next hop of 0x%x to 0x%x based on ACK/reply", p->from, p->relay_node);
origTx->next_hop = p->relay_node;
@ -76,18 +75,18 @@ void NextHopRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtast
}
}
if (isRebroadcaster()) {
if (!isToUs(p) && !isFromUs(p)) {
if (p->next_hop == NO_NEXT_HOP_PREFERENCE || p->next_hop == ourRelayID) {
if (!isToUs(p) && !isFromUs(p) && p->hop_limit > 0) {
if (p->next_hop == NO_NEXT_HOP_PREFERENCE || p->next_hop == ourRelayID) {
if (isRebroadcaster()) {
meshtastic_MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
LOG_INFO("Relaying received message coming from %x", p->relay_node);
tosend->hop_limit--; // bump down the hop count
NextHopRouter::send(tosend);
} // else don't relay
} else {
LOG_DEBUG("Not rebroadcasting: Role = CLIENT_MUTE or Rebroadcast Mode = NONE");
}
}
} else {
LOG_DEBUG("Not rebroadcasting: Role = CLIENT_MUTE or Rebroadcast Mode = NONE");
}
// handle the packet as normal
Router::sniffReceived(p, c);
@ -99,6 +98,10 @@ void NextHopRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtast
*/
uint8_t NextHopRouter::getNextHop(NodeNum to, uint8_t relay_node)
{
// When we're a repeater router->sniffReceived will call NextHopRouter directly without checking for broadcast
if (isBroadcast(to))
return NO_NEXT_HOP_PREFERENCE;
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(to);
if (node && node->next_hop) {
// We are careful not to return the relay node as the next hop

View File

@ -54,8 +54,8 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd
// to handle it now
uint8_t ourRelayID = nodeDB->getLastByteOfNodeNum(nodeDB->getNodeNum());
if (found->sender != nodeDB->getNodeNum() && found->next_hop != NO_NEXT_HOP_PREFERENCE &&
p->next_hop == NO_NEXT_HOP_PREFERENCE && found->next_hop != ourRelayID && p->relay_node != 0 &&
wasRelayer(p->relay_node, found) && !wasRelayer(ourRelayID, found) && !wasRelayer(found->next_hop, found)) {
p->next_hop == NO_NEXT_HOP_PREFERENCE && found->next_hop != ourRelayID && wasRelayer(p->relay_node, found) &&
!wasRelayer(ourRelayID, found) && !wasRelayer(found->next_hop, found)) {
LOG_INFO("Fallback to flooding, consider unseen relay_node=0x%x", p->relay_node);
seenRecently = false;
}
@ -109,6 +109,9 @@ void PacketHistory::clearExpiredRecentPackets()
* @return true if node was indeed a relayer, false if not */
bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender)
{
if (relayer == 0)
return false;
PacketRecord r = {.sender = sender, .id = id, .rxTimeMsec = 0, .next_hop = 0};
auto found = recentPackets.find(r);

View File

@ -315,10 +315,6 @@ void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
out += " encrypted";
}
if (p->next_hop != 0)
out += DEBUG_PORT.mt_sprintf(" nextHop=0x%x", p->next_hop);
if (p->relay_node != 0)
out += DEBUG_PORT.mt_sprintf(" relay=0x%x", p->relay_node);
if (p->rx_time != 0)
out += DEBUG_PORT.mt_sprintf(" rxtime=%u", p->rx_time);
if (p->rx_snr != 0.0)
@ -329,6 +325,10 @@ void printPacket(const char *prefix, const meshtastic_MeshPacket *p)
out += DEBUG_PORT.mt_sprintf(" via MQTT");
if (p->hop_start != 0)
out += DEBUG_PORT.mt_sprintf(" hopStart=%d", p->hop_start);
if (p->next_hop != 0)
out += DEBUG_PORT.mt_sprintf(" nextHop=0x%x", p->next_hop);
if (p->relay_node != 0)
out += DEBUG_PORT.mt_sprintf(" relay=0x%x", p->relay_node);
if (p->priority != 0)
out += DEBUG_PORT.mt_sprintf(" priority=%d", p->priority);

View File

@ -245,4 +245,4 @@ void setupModules()
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra
// acks
routingModule = new RoutingModule();
}
}

View File

@ -208,4 +208,4 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
neighbors.push_back(new_nbr);
}
return &neighbors.back();
}
}

View File

@ -67,4 +67,4 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
void printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np);
void printNodeDBNeighbors();
};
extern NeighborInfoModule *neighborInfoModule;
extern NeighborInfoModule *neighborInfoModule;