|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include <MeshCore.h> |
| 4 | +#include <helpers/StaticPoolPacketManager.h> |
| 5 | + |
| 6 | +// Fork-owned (not upstream-tracked). Observer builds capture every received packet |
| 7 | +// to MQTT, but RX processing needs a free pool packet first — Dispatcher::checkRecv() |
| 8 | +// discards the received bytes before logRx() when allocNew() fails. Under duty-cycle |
| 9 | +// throttling the outbound queue can park the entire pool waiting on TX budget, which |
| 10 | +// starves RX allocation and silently caps MQTT capture at the TX rate (each completed |
| 11 | +// TX frees exactly one packet for exactly one more RX). |
| 12 | +// |
| 13 | +// This manager sheds *retransmissions* instead: once the free pool drops below the |
| 14 | +// reserve, outbound packets are refused (freed straight back to the pool) so RX |
| 15 | +// allocation — and therefore capture — continues at full rate. The node was already |
| 16 | +// dropping traffic in that state; this chooses to drop repeats it has no TX budget |
| 17 | +// for anyway, rather than capture. |
| 18 | +class RxReservePacketManager : public StaticPoolPacketManager { |
| 19 | + int _rx_reserve; |
| 20 | +public: |
| 21 | + RxReservePacketManager(int pool_size, int rx_reserve) |
| 22 | + : StaticPoolPacketManager(pool_size), _rx_reserve(rx_reserve) {} |
| 23 | + |
| 24 | + void queueOutbound(mesh::Packet* packet, uint8_t priority, uint32_t scheduled_for) override { |
| 25 | + if (getFreeCount() < _rx_reserve) { |
| 26 | + MESH_DEBUG_PRINTLN("RxReservePacketManager: pool below RX reserve, shedding outbound"); |
| 27 | + free(packet); |
| 28 | + return; |
| 29 | + } |
| 30 | + StaticPoolPacketManager::queueOutbound(packet, priority, scheduled_for); |
| 31 | + } |
| 32 | +}; |
| 33 | + |
| 34 | +// The packet manager for an app build: observer builds reserve a quarter of the pool |
| 35 | +// for RX so MQTT capture survives duty-cycle throttling; non-observer builds keep the |
| 36 | +// upstream pool behavior unchanged. |
| 37 | +inline mesh::PacketManager* createObserverPacketManager(int pool_size) { |
| 38 | +#ifdef WITH_MQTT_BRIDGE |
| 39 | + return new RxReservePacketManager(pool_size, pool_size / 4); |
| 40 | +#else |
| 41 | + return new StaticPoolPacketManager(pool_size); |
| 42 | +#endif |
| 43 | +} |
0 commit comments