mirror of
https://github.com/meshtastic/firmware.git
synced 2025-10-03 05:53:24 +00:00
Merge branch 'develop' into assymRelay
This commit is contained in:
commit
aa876ba42f
@ -3,6 +3,10 @@
|
|||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
|
#include "meshUtils.h"
|
||||||
|
#if !MESHTASTIC_EXCLUDE_TRACEROUTE
|
||||||
|
#include "modules/TraceRouteModule.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
FloodingRouter::FloodingRouter() {}
|
FloodingRouter::FloodingRouter() {}
|
||||||
|
|
||||||
@ -22,7 +26,37 @@ 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
|
bool wasUpgraded = false;
|
||||||
|
bool seenRecently =
|
||||||
|
wasSeenRecently(p, true, nullptr, nullptr, &wasUpgraded); // Updates history; returns false when an upgrade is detected
|
||||||
|
|
||||||
|
// Handle hop_limit upgrade scenario for rebroadcasters
|
||||||
|
// isRebroadcaster() is duplicated in perhapsRebroadcast(), but this avoids confusing log messages
|
||||||
|
if (wasUpgraded && isRebroadcaster() && iface && p->hop_limit > 0) {
|
||||||
|
// wasSeenRecently() reports false in upgrade cases so we handle replacement before the duplicate short-circuit
|
||||||
|
// If we overhear a duplicate copy of the packet with more hops left than the one we are waiting to
|
||||||
|
// rebroadcast, then remove the packet currently sitting in the TX queue and use this one instead.
|
||||||
|
uint8_t dropThreshold = p->hop_limit; // remove queued packets that have fewer hops remaining
|
||||||
|
if (iface->removePendingTXPacket(getFrom(p), p->id, dropThreshold)) {
|
||||||
|
LOG_DEBUG("Processing upgraded packet 0x%08x for rebroadcast with hop limit %d (dropping queued < %d)", p->id,
|
||||||
|
p->hop_limit, dropThreshold);
|
||||||
|
|
||||||
|
if (nodeDB)
|
||||||
|
nodeDB->updateFrom(*p);
|
||||||
|
#if !MESHTASTIC_EXCLUDE_TRACEROUTE
|
||||||
|
if (traceRouteModule && p->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||||
|
p->decoded.portnum == meshtastic_PortNum_TRACEROUTE_APP)
|
||||||
|
traceRouteModule->processUpgradedPacket(*p);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
perhapsRebroadcast(p);
|
||||||
|
|
||||||
|
// We already enqueued the improved copy, so make sure the incoming packet stops here.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seenRecently) {
|
||||||
printPacket("Ignore dupe incoming msg", p);
|
printPacket("Ignore dupe incoming msg", p);
|
||||||
rxDupe++;
|
rxDupe++;
|
||||||
|
|
||||||
|
@ -103,12 +103,26 @@ meshtastic_MeshPacket *MeshPacketQueue::getFront()
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Attempt to find and remove a packet from this queue. Returns a pointer to the removed packet, or NULL if not found */
|
/** Get a packet from this queue. Returns a pointer to the packet, or NULL if not found. */
|
||||||
meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id, bool tx_normal, bool tx_late)
|
meshtastic_MeshPacket *MeshPacketQueue::getPacketFromQueue(NodeNum from, PacketId id)
|
||||||
{
|
{
|
||||||
for (auto it = queue.begin(); it != queue.end(); it++) {
|
for (auto it = queue.begin(); it != queue.end(); it++) {
|
||||||
auto p = (*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) {
|
||||||
|
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, 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)) &&
|
||||||
|
(!hop_limit_lt || p->hop_limit < hop_limit_lt)) {
|
||||||
queue.erase(it);
|
queue.erase(it);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -120,14 +134,7 @@ meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id, bool t
|
|||||||
/* Attempt to find a packet from this queue. Return true if it was found. */
|
/* Attempt to find a packet from this queue. Return true if it was found. */
|
||||||
bool MeshPacketQueue::find(const NodeNum from, const PacketId id)
|
bool MeshPacketQueue::find(const NodeNum from, const PacketId id)
|
||||||
{
|
{
|
||||||
for (auto it = queue.begin(); it != queue.end(); it++) {
|
return getPacketFromQueue(from, id) != NULL;
|
||||||
const auto *p = *it;
|
|
||||||
if (getFrom(p) == from && p->id == id) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,8 +35,12 @@ class MeshPacketQueue
|
|||||||
|
|
||||||
meshtastic_MeshPacket *getFront();
|
meshtastic_MeshPacket *getFront();
|
||||||
|
|
||||||
|
/** Get a packet from this queue. Returns a pointer to the packet, or NULL if not found. */
|
||||||
|
meshtastic_MeshPacket *getPacketFromQueue(NodeNum from, PacketId id);
|
||||||
|
|
||||||
/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
|
/** 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);
|
||||||
|
|
||||||
/* Attempt to find a packet from this queue. Return true if it was found. */
|
/* Attempt to find a packet from this queue. Return true if it was found. */
|
||||||
bool find(const NodeNum from, const PacketId id);
|
bool find(const NodeNum from, const PacketId id);
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
#include "NextHopRouter.h"
|
#include "NextHopRouter.h"
|
||||||
|
#include "MeshTypes.h"
|
||||||
|
#include "meshUtils.h"
|
||||||
|
#if !MESHTASTIC_EXCLUDE_TRACEROUTE
|
||||||
|
#include "modules/TraceRouteModule.h"
|
||||||
|
#endif
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
|
|
||||||
NextHopRouter::NextHopRouter() {}
|
NextHopRouter::NextHopRouter() {}
|
||||||
@ -33,7 +38,35 @@ bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
|
|||||||
{
|
{
|
||||||
bool wasFallback = false;
|
bool wasFallback = false;
|
||||||
bool weWereNextHop = false;
|
bool weWereNextHop = false;
|
||||||
if (wasSeenRecently(p, true, &wasFallback, &weWereNextHop)) { // Note: this will also add a recent packet record
|
bool wasUpgraded = false;
|
||||||
|
bool seenRecently = wasSeenRecently(p, true, &wasFallback, &weWereNextHop,
|
||||||
|
&wasUpgraded); // Updates history; returns false when an upgrade is detected
|
||||||
|
|
||||||
|
// Handle hop_limit upgrade scenario for rebroadcasters
|
||||||
|
// isRebroadcaster() is duplicated in perhapsRelay(), but this avoids confusing log messages
|
||||||
|
if (wasUpgraded && isRebroadcaster() && iface && p->hop_limit > 0) {
|
||||||
|
// Upgrade detection bypasses the duplicate short-circuit so we replace the queued packet before exiting
|
||||||
|
uint8_t dropThreshold = p->hop_limit; // remove queued packets that have fewer hops remaining
|
||||||
|
if (iface->removePendingTXPacket(getFrom(p), p->id, dropThreshold)) {
|
||||||
|
LOG_DEBUG("Processing upgraded packet 0x%08x for relay with hop limit %d (dropping queued < %d)", p->id, p->hop_limit,
|
||||||
|
dropThreshold);
|
||||||
|
|
||||||
|
if (nodeDB)
|
||||||
|
nodeDB->updateFrom(*p);
|
||||||
|
#if !MESHTASTIC_EXCLUDE_TRACEROUTE
|
||||||
|
if (traceRouteModule && p->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||||
|
p->decoded.portnum == meshtastic_PortNum_TRACEROUTE_APP)
|
||||||
|
traceRouteModule->processUpgradedPacket(*p);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
perhapsRelay(p);
|
||||||
|
|
||||||
|
// We already enqueued the improved copy, so make sure the incoming packet stops here.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seenRecently) {
|
||||||
printPacket("Ignore dupe incoming msg", p);
|
printPacket("Ignore dupe incoming msg", p);
|
||||||
|
|
||||||
if (p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA) {
|
if (p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA) {
|
||||||
|
@ -45,7 +45,8 @@ PacketHistory::~PacketHistory()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Update recentPackets and return true if we have already seen this packet */
|
/** Update recentPackets and return true if we have already seen this packet */
|
||||||
bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpdate, bool *wasFallback, bool *weWereNextHop)
|
bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpdate, bool *wasFallback, bool *weWereNextHop,
|
||||||
|
bool *wasUpgraded)
|
||||||
{
|
{
|
||||||
if (!initOk()) {
|
if (!initOk()) {
|
||||||
LOG_ERROR("Packet History - Was Seen Recently: NOT INITIALIZED!");
|
LOG_ERROR("Packet History - Was Seen Recently: NOT INITIALIZED!");
|
||||||
@ -88,6 +89,16 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd
|
|||||||
PacketRecord *found = find(r.sender, r.id); // Find the packet record in the recentPackets array
|
PacketRecord *found = find(r.sender, r.id); // Find the packet record in the recentPackets array
|
||||||
bool seenRecently = (found != NULL); // If found -> the packet was seen recently
|
bool seenRecently = (found != NULL); // If found -> the packet was seen recently
|
||||||
|
|
||||||
|
// Check for hop_limit upgrade scenario
|
||||||
|
if (seenRecently && wasUpgraded && found->hop_limit < p->hop_limit) {
|
||||||
|
LOG_DEBUG("Packet History - Hop limit upgrade: packet 0x%08x from hop_limit=%d to hop_limit=%d", p->id, found->hop_limit,
|
||||||
|
p->hop_limit);
|
||||||
|
*wasUpgraded = true;
|
||||||
|
seenRecently = false; // Allow router processing but prevent duplicate app delivery
|
||||||
|
} else if (wasUpgraded) {
|
||||||
|
*wasUpgraded = false; // Initialize to false if not an upgrade
|
||||||
|
}
|
||||||
|
|
||||||
if (seenRecently) {
|
if (seenRecently) {
|
||||||
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
|
||||||
|
@ -60,9 +60,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
|
* @param weWereNextHop if not nullptr, packet will be checked for us being the next hop and value will be set to true if so
|
||||||
|
* @param wasUpgraded if not nullptr, will be set to true if this packet has better hop_limit than previously seen
|
||||||
*/
|
*/
|
||||||
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);
|
bool *weWereNextHop = nullptr, bool *wasUpgraded = 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
|
||||||
* If wasSole is not nullptr, it will be set to true if the relayer was the only relayer of that packet
|
* If wasSole is not nullptr, it will be set to true if the relayer was the only relayer of that packet
|
||||||
|
@ -189,6 +189,12 @@ class RadioInterface
|
|||||||
/** If the packet is not already in the late rebroadcast window, move it there */
|
/** If the packet is not already in the late rebroadcast window, move it there */
|
||||||
virtual void clampToLateRebroadcastWindow(NodeNum from, PacketId id) { return; }
|
virtual void clampToLateRebroadcastWindow(NodeNum from, PacketId id) { 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
|
||||||
|
*/
|
||||||
|
virtual bool removePendingTXPacket(NodeNum from, PacketId id, uint32_t hop_limit_lt) { return false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate airtime per
|
* 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
|
* https://www.rs-online.com/designspark/rel-assets/ds-assets/uploads/knowledge-items/application-notes-for-the-internet-of-things/LoRa%20Design%20Guide.pdf
|
||||||
|
@ -362,6 +362,26 @@ void RadioLibInterface::clampToLateRebroadcastWindow(NodeNum from, PacketId id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 RadioLibInterface::removePendingTXPacket(NodeNum from, PacketId id, uint32_t hop_limit_lt)
|
||||||
|
{
|
||||||
|
meshtastic_MeshPacket *p = txQueue.remove(from, id, true, true, hop_limit_lt);
|
||||||
|
if (p) {
|
||||||
|
LOG_DEBUG("Dropping pending-TX packet 0x%08x 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()
|
void RadioLibInterface::handleTransmitInterrupt()
|
||||||
{
|
{
|
||||||
// This can be null if we forced the device to enter standby mode. In that case
|
// This can be null if we forced the device to enter standby mode. In that case
|
||||||
|
@ -215,4 +215,11 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
|
|||||||
* If the packet is not already in the late rebroadcast window, move it there
|
* If the packet is not already in the late rebroadcast window, move it there
|
||||||
*/
|
*/
|
||||||
void clampToLateRebroadcastWindow(NodeNum from, PacketId id);
|
void clampToLateRebroadcastWindow(NodeNum from, PacketId id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) override;
|
||||||
};
|
};
|
@ -13,6 +13,7 @@ ProcessMessage TextMessageModule::handleReceived(const meshtastic_MeshPacket &mp
|
|||||||
auto &p = mp.decoded;
|
auto &p = mp.decoded;
|
||||||
LOG_INFO("Received text msg from=0x%0x, id=0x%x, msg=%.*s", mp.from, mp.id, p.payload.size, p.payload.bytes);
|
LOG_INFO("Received text msg from=0x%0x, id=0x%x, msg=%.*s", mp.from, mp.id, p.payload.size, p.payload.bytes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We only store/display messages destined for us.
|
// We only store/display messages destined for us.
|
||||||
// Keep a copy of the most recent text message.
|
// Keep a copy of the most recent text message.
|
||||||
devicestate.rx_text_message = mp;
|
devicestate.rx_text_message = mp;
|
||||||
|
@ -153,6 +153,20 @@ void TraceRouteModule::alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtasti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TraceRouteModule::processUpgradedPacket(const meshtastic_MeshPacket &mp)
|
||||||
|
{
|
||||||
|
if (mp.which_payload_variant != meshtastic_MeshPacket_decoded_tag || mp.decoded.portnum != meshtastic_PortNum_TRACEROUTE_APP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
meshtastic_RouteDiscovery decoded = meshtastic_RouteDiscovery_init_zero;
|
||||||
|
if (!pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, &meshtastic_RouteDiscovery_msg, &decoded))
|
||||||
|
return;
|
||||||
|
|
||||||
|
handleReceivedProtobuf(mp, &decoded);
|
||||||
|
// Intentionally modify the packet in-place so downstream relays see our updates.
|
||||||
|
alterReceivedProtobuf(const_cast<meshtastic_MeshPacket &>(mp), &decoded);
|
||||||
|
}
|
||||||
|
|
||||||
void TraceRouteModule::insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r, bool isTowardsDestination)
|
void TraceRouteModule::insertUnknownHops(meshtastic_MeshPacket &p, meshtastic_RouteDiscovery *r, bool isTowardsDestination)
|
||||||
{
|
{
|
||||||
pb_size_t *route_count;
|
pb_size_t *route_count;
|
||||||
|
@ -35,6 +35,8 @@ class TraceRouteModule : public ProtobufModule<meshtastic_RouteDiscovery>,
|
|||||||
virtual bool wantUIFrame() override { return shouldDraw(); }
|
virtual bool wantUIFrame() override { return shouldDraw(); }
|
||||||
virtual Observable<const UIFrameEvent *> *getUIFrameObservable() override { return this; }
|
virtual Observable<const UIFrameEvent *> *getUIFrameObservable() override { return this; }
|
||||||
|
|
||||||
|
void processUpgradedPacket(const meshtastic_MeshPacket &mp);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_RouteDiscovery *r) override;
|
bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_RouteDiscovery *r) override;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user