Fix nRF52 AsyncUDP multicast TX/RX race on W5100S#9765
Fix nRF52 AsyncUDP multicast TX/RX race on W5100S#9765PhilipLykov wants to merge 3 commits intomeshtastic:developfrom
Conversation
|
That's how it looks in the logs: |
| return udp.endPacket(); | ||
| bool ok = udp.endPacket(); | ||
| isSending = false; | ||
| return ok; |
There was a problem hiding this comment.
UdpMulticastHandler::onSend() ignores return value of udp.writeTo() and always return true. the return value is not documented there, should it care?
| int32_t AsyncUDP::runOnce() | ||
| { | ||
| if (_onPacket && udp.parsePacket() > 0) { | ||
| if (_onPacket && !isSending && udp.parsePacket() > 0) { |
There was a problem hiding this comment.
The new guard skips parsePacket() for the entire writeTo() window. If endPacket() blocks/yields for longer intervals (as described in the PR rationale), inbound packets can accumulate and be dropped by the W5100S RX buffer during bursts. This fixes corruption but may trade it for packet loss under load.
…kets socketSendUDP() calls yield() while waiting for SEND_OK, allowing the cooperative scheduler to run AsyncUDP::runOnce(). When runOnce() calls parsePacket() on the same socket during an active send, the multicast loopback packet arriving from the switch produces a garbled 8-byte RX header (wrong source IP, wrong payload length), leading to protobuf decode errors in UdpMulticastHandler. Add a volatile isSending flag that writeTo() sets around endPacket() (the only yield point). runOnce() checks this flag and skips parsePacket() while a send is in progress. Loopback packets stay buffered in the W5100S RX buffer and are read cleanly on the next poll cycle. Also propagate writeTo() return value in UdpMulticastHandler::onSend() instead of unconditionally returning true. Made-with: Cursor
27b27af to
522118c
Compare
|
Hi @robekl, thank you for the review! Both points are valid and I've pushed an updated commit to address them: 1. You're right — 2. Narrowing the Good catch on the blocked duration. I've narrowed the The W5100S has a 2KB RX buffer per socket, which holds ~8 typical Meshtastic packets, so even during the brief |
Summary
Fix a TX/RX race condition in the nRF52
AsyncUDPimplementation that causes garbled multicast packets on RAK4631 Ethernet gateway boards (W5100S).Root cause: The W5100S
socketSendUDP()function callsyield()while polling forSEND_OK. On nRF52 (cooperative multitasking), this allowsAsyncUDP::runOnce()to execute and callparsePacket()on the same UDP socket while a send is still in progress. When the multicast loopback packet arrives from the network switch during this window,parsePacket()reads a garbled 8-byte RX header from the W5100S, producing an incorrect source IP (e.g.3.192.168.30instead of the real sender) and wrong payload length. This corrupted packet then fails protobuf decoding inUdpMulticastHandler.Fix: Add a
volatile bool isSendingflag toAsyncUDP.writeTo()sets this flag around the entire send operation (beginPacket/write/endPacket).runOnce()checks!isSendingbefore callingparsePacket(), skipping the poll when a send is active. Loopback packets remain safely buffered in the W5100S hardware RX buffer and are read cleanly on the next 5ms poll cycle.Changes
src/platform/nrf52/AsyncUDP.h— addvolatile bool isSendingmembersrc/platform/nrf52/AsyncUDP.cpp— guardwriteTo()with the flag; skipparsePacket()inrunOnce()when sendingTest plan
rak4631_eth_gwtarget — SUCCESS