From 1a1d6ba270a314fbc58622c92aabfc14ef98a00d Mon Sep 17 00:00:00 2001 From: DatanoiseTV <6614616+DatanoiseTV@users.noreply.github.com> Date: Fri, 8 May 2026 21:35:01 +0200 Subject: [PATCH] router: skip pre-encryption packet copy when MQTT does not need it Router::send unconditionally allocCopy/release'd a pre-encryption clone of every relayed packet, even on builds where MQTT was excluded (MESHTASTIC_EXCLUDE_MQTT) or runtime-disabled (mqtt module nullptr or moduleConfig.mqtt.enabled=false) or when the packet was a relay rather than from us. The copy is only fed to MQTT::onSend, so guard the alloc on the same predicate the call site already used. On nodes near pool exhaustion this halves the alloc rate on the hot path. --- src/mesh/Router.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index ffeb7c5393d..058be504c07 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -372,24 +372,32 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it - DEBUG_HEAP_BEFORE; - meshtastic_MeshPacket *p_decoded = packetPool.allocCopy(*p); - DEBUG_HEAP_AFTER("Router::send", p_decoded); + // The pre-encryption copy is only needed to feed MQTT::onSend; skip it + // entirely on builds/devices where MQTT is excluded or disabled. + meshtastic_MeshPacket *p_decoded = nullptr; +#if !MESHTASTIC_EXCLUDE_MQTT + const bool needDecodedForMqtt = moduleConfig.mqtt.enabled && isFromUs(p) && mqtt; + if (needDecodedForMqtt) { + DEBUG_HEAP_BEFORE; + p_decoded = packetPool.allocCopy(*p); + DEBUG_HEAP_AFTER("Router::send", p_decoded); + } +#endif auto encodeResult = perhapsEncode(p); if (encodeResult != meshtastic_Routing_Error_NONE) { - packetPool.release(p_decoded); + if (p_decoded) + packetPool.release(p_decoded); p->channel = 0; // Reset the channel to 0, so we don't use the failing hash again abortSendAndNak(encodeResult, p); return encodeResult; // FIXME - this isn't a valid ErrorCode } #if !MESHTASTIC_EXCLUDE_MQTT - // Only publish to MQTT if we're the original transmitter of the packet - if (moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) { + if (p_decoded) { mqtt->onSend(*p, *p_decoded, chIndex); + packetPool.release(p_decoded); } #endif - packetPool.release(p_decoded); } #if HAS_UDP_MULTICAST