0477e07b8499098aff975d45ab770208531a067c
Pressing Z failed instantly, BEFORE the sender was started -- so the frames in the ring were stray traffic from the host (mDNS, IPv6 RAs, ARP), and a single descriptor we could not parse aborted the whole transfer. On a live network that is guaranteed to happen. A bad descriptor is now non-fatal: log the first few, resync RRP to the gateware's RWP, and keep waiting. Capped at 200 so a genuinely broken ring still terminates rather than spinning. This also removes the dependence on the ring being quiet when Z is pressed, which was never a reasonable assumption. The descriptor 00 00 00 01 persists after fixing both dropped-write bugs, and grep confirms no bare `ready` tests remain, so it is NOT that. Rather than theorise a fourth time, the error path now dumps 32 bytes from the head of the offending page. That distinguishes the two remaining possibilities outright: an ethernet header at offset 4 means the descriptor length is simply wrong, while a header at 3 or 5 -- or at 0 -- means we are reading the wrong place. Also dumps the first frame whose ethertype does not match, with the ethertype read at offset 12, because a body written at the wrong offset would show the ethertype at 11 or 13. And the timeout now reports how many frames were seen and how many descriptors were rejected, so "no match" is distinguishable from "nothing arrived". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Description
No description provided
Languages
Python
84.9%
C
12.4%
Shell
1.1%
Dockerfile
0.7%
Makefile
0.4%
Other
0.5%