Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions src/mesh/RadioLibInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,10 @@ bool RadioLibInterface::randomBytes(uint8_t *buffer, size_t length)
}

// Older RadioLib versions only expose random(min, max), so fill the buffer byte-by-byte.
// Note: random(min, max) is half-open [min, max) per RadioLib — (0, 256) yields 0-255, which
// is the correct byte range. The previous (0, 255) could never produce the value 255.
for (size_t i = 0; i < length; ++i) {
int32_t value = iface->random(0, 255);
int32_t value = iface->random(0, 256);
if (value < 0) {
return false;
}
Expand Down Expand Up @@ -482,10 +484,19 @@ void RadioLibInterface::handleReceiveInterrupt()
#endif
if (state != RADIOLIB_ERR_NONE) {
// Log PacketHeader similar to RadioInterface::printPacket so we can try to match RX errors to other packets in the logs.
LOG_ERROR("Ignore received packet due to error=%d (maybe id=0x%08x fr=0x%08x to=0x%08x flags=0x%02x rxSNR=%g rxRSSI=%i "
"nextHop=0x%x relay=0x%x)",
state, radioBuffer.header.id, radioBuffer.header.from, radioBuffer.header.to, radioBuffer.header.flags,
iface->getSNR(), lround(iface->getRSSI()), radioBuffer.header.next_hop, radioBuffer.header.relay_node);
// CRC mismatches are routine in RF-congested areas (noise mis-demodulating to a syncword hit) — not an error class worth
// ERROR severity, but still valuable info for operators looking at the log. Everything else stays at LOG_ERROR.
if (state == RADIOLIB_ERR_CRC_MISMATCH) {
LOG_INFO("Ignore received packet due to CRC mismatch (maybe id=0x%08x fr=0x%08x to=0x%08x flags=0x%02x rxSNR=%g "
"rxRSSI=%i nextHop=0x%x relay=0x%x)",
radioBuffer.header.id, radioBuffer.header.from, radioBuffer.header.to, radioBuffer.header.flags,
iface->getSNR(), lround(iface->getRSSI()), radioBuffer.header.next_hop, radioBuffer.header.relay_node);
} else {
LOG_ERROR("Ignore received packet due to error=%d (maybe id=0x%08x fr=0x%08x to=0x%08x flags=0x%02x rxSNR=%g rxRSSI=%i "
"nextHop=0x%x relay=0x%x)",
state, radioBuffer.header.id, radioBuffer.header.from, radioBuffer.header.to, radioBuffer.header.flags,
iface->getSNR(), lround(iface->getRSSI()), radioBuffer.header.next_hop, radioBuffer.header.relay_node);
}
rxBad++;

airTime->logAirtime(RX_ALL_LOG, rxMsec);
Expand All @@ -494,14 +505,17 @@ void RadioLibInterface::handleReceiveInterrupt()
// Skip the 4 headers that are at the beginning of the rxBuf
int32_t payloadLen = length - sizeof(PacketHeader);

// CRC-good OTA reception — count as rxGood regardless of whether we process
// it further. Short/from==0/pool-exhausted packets still represent successful
// airtime usage and shouldn't silently vanish from the stats.
rxGood++;

// check for short packets
if (payloadLen < 0) {
LOG_WARN("Ignore received packet too short");
rxBad++;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now neither counted as good, nor bad.

airTime->logAirtime(RX_ALL_LOG, rxMsec);
} else {
rxGood++;
// altered packet with "from == 0" can do Remote Node Administration without permission
// altered packet with "from == 0" can do Remote Node Administration without permission.
// Still counted as a "good" OTA reception above — we just refuse to process it.
if (radioBuffer.header.from == 0) {
LOG_WARN("Ignore received packet without sender");
return;
Expand All @@ -512,6 +526,14 @@ void RadioLibInterface::handleReceiveInterrupt()
// nodes.
meshtastic_MeshPacket *mp = packetPool.allocZeroed();

// Packet pool exhaustion: drop this packet rather than deref NULL. Can happen under
// sustained heap pressure (e.g. config dump mid-RX, dense mesh bursts). The allocator
// already emits a WARN on failure, so don't duplicate it here.
if (!mp) {
airTime->logAirtime(RX_ALL_LOG, rxMsec);
return;
}

// Keep the assigned fields in sync with src/mqtt/MQTT.cpp:onReceiveProto
mp->from = radioBuffer.header.from;
mp->to = radioBuffer.header.to;
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/Router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
meshtastic_Data decodedtmp;
memset(&decodedtmp, 0, sizeof(decodedtmp));
if (!pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &decodedtmp)) {
LOG_DEBUG("Invalid protobufs in received mesh packet id=0x%08x (bad psk?)", p->id);
LOG_WARN("Invalid protobufs in received mesh packet id=0x%08x (bad psk?)", p->id);
} else if (decodedtmp.portnum == meshtastic_PortNum_UNKNOWN_APP) {
LOG_DEBUG("Invalid portnum (bad psk?)");
#if !(MESHTASTIC_EXCLUDE_PKI)
Expand Down