feat(mesh): track actually-forwarded packet count, show in Diagnostics

allowPacketForward() only gates permission; the packet can still be
dropped afterward (hasSeen(), path-size limit). Add Mesh::n_forwarded,
incremented at the 3 ACTION_RETRANSMIT_DELAYED return sites, so the
Diagnostics screen can confirm a repeater is actually relaying traffic
rather than just being configured to.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-06-18 23:20:23 +02:00
co-authored by Claude Sonnet 4.6
parent 72bc4ee895
commit d1d64dc612
3 changed files with 14 additions and 2 deletions
@@ -20,7 +20,7 @@ class DiagnosticsScreen : public UIScreen {
int _scroll = 0; int _scroll = 0;
struct Row { const char* label; char value[20]; }; struct Row { const char* label; char value[20]; };
static const int MAX_ROWS = 12; static const int MAX_ROWS = 13;
Row _rows[MAX_ROWS]; Row _rows[MAX_ROWS];
int _row_count = 0; int _row_count = 0;
@@ -76,6 +76,9 @@ class DiagnosticsScreen : public UIScreen {
addRxTxRow("Ack/Path", rte_rx, rte_tx); addRxTxRow("Ack/Path", rte_rx, rte_tx);
addRxTxRow("Other", oth_rx, oth_tx); addRxTxRow("Other", oth_rx, oth_tx);
snprintf(buf, sizeof(buf), "%lu", (unsigned long)the_mesh.getNumForwarded());
addRow("Forwarded", buf);
uint32_t heap_free, heap_total; uint32_t heap_free, heap_total;
DeviceDiag::getHeapStats(heap_free, heap_total); DeviceDiag::getHeapStats(heap_free, heap_total);
if (heap_total > 0) snprintf(buf, sizeof(buf), "%lu/%luKB", (unsigned long)(heap_free / 1024), (unsigned long)(heap_total / 1024)); if (heap_total > 0) snprintf(buf, sizeof(buf), "%lu/%luKB", (unsigned long)(heap_free / 1024), (unsigned long)(heap_total / 1024));
+4
View File
@@ -5,6 +5,7 @@ namespace mesh {
void Mesh::begin() { void Mesh::begin() {
Dispatcher::begin(); Dispatcher::begin();
n_forwarded = 0;
} }
void Mesh::loop() { void Mesh::loop() {
@@ -60,6 +61,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
pkt->path[pkt->path_len++] = (int8_t) (pkt->getSNR()*4); pkt->path[pkt->path_len++] = (int8_t) (pkt->getSNR()*4);
uint32_t d = getDirectRetransmitDelay(pkt); uint32_t d = getDirectRetransmitDelay(pkt);
n_forwarded++;
return ACTION_RETRANSMIT_DELAYED(5, d); // schedule with priority 5 (for now), maybe make configurable? return ACTION_RETRANSMIT_DELAYED(5, d); // schedule with priority 5 (for now), maybe make configurable?
} }
} }
@@ -100,6 +102,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
removeSelfFromPath(pkt); removeSelfFromPath(pkt);
uint32_t d = getDirectRetransmitDelay(pkt); uint32_t d = getDirectRetransmitDelay(pkt);
n_forwarded++;
return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority
} }
} }
@@ -336,6 +339,7 @@ DispatcherAction Mesh::routeRecvPacket(Packet* packet) {
packet->setPathHashCount(n + 1); packet->setPathHashCount(n + 1);
uint32_t d = getRetransmitDelay(packet); uint32_t d = getRetransmitDelay(packet);
n_forwarded++;
// as this propagates outwards, give it lower and lower priority // as this propagates outwards, give it lower and lower priority
return ACTION_RETRANSMIT_DELAYED(packet->getPathHashCount(), d); // give priority to closer sources, than ones further away return ACTION_RETRANSMIT_DELAYED(packet->getPathHashCount(), d); // give priority to closer sources, than ones further away
} }
+5
View File
@@ -27,6 +27,7 @@ class Mesh : public Dispatcher {
RTCClock* _rtc; RTCClock* _rtc;
RNG* _rng; RNG* _rng;
MeshTables* _tables; MeshTables* _tables;
uint32_t n_forwarded; // packets actually re-transmitted (repeater/transport role)
void removeSelfFromPath(Packet* packet); void removeSelfFromPath(Packet* packet);
void routeDirectRecvAcks(Packet* packet, uint32_t delay_millis); void routeDirectRecvAcks(Packet* packet, uint32_t delay_millis);
@@ -178,6 +179,10 @@ public:
LocalIdentity self_id; LocalIdentity self_id;
// packets actually re-transmitted (vs. just permitted by allowPacketForward()) —
// confirms a repeater/transport role is really forwarding, not just configured to.
uint32_t getNumForwarded() const { return n_forwarded; }
RNG* getRNG() const { return _rng; } RNG* getRNG() const { return _rng; }
RTCClock* getRTCClock() const { return _rtc; } RTCClock* getRTCClock() const { return _rtc; }