The alignment bug is FIXED -- hardware now reports "frame 1 (342 B) etype=0800
at 12: FF FF FF FF FF FF 00 2B", i.e. broadcast dst at 0, host MAC at 6,
ethertype at 12. Perfectly aligned, correctly received, correctly skipped as
not ours.
So 00 00 00 01 was never a dropped write. It is frame data being read as a
descriptor, because the ring HAS NO OVERFLOW PROTECTION: nothing in the
gateware consumes RRP, so RXFrameAssembler keeps writing and laps the reader
(the real BBA has RBFI for exactly this). The poll loop costs ~5 EXI
transactions per frame (~200 us) while a 100 Mbit link delivers a 342-byte
frame every ~30 us, and the ring is 15 pages -- roughly 3 to 11 frames. Under
continuous traffic pages are reused before they are read. That is also why it
"worked once out of three tries": it is a race against the host's background
traffic.
ring_next() now returns -4 when the writer is more than two thirds of the ring
ahead, and the caller resyncs and continues instead of parsing bytes that
belong to a different frame. The timeout reports seen / bad-descriptor /
lapped counts so the three cases stay distinguishable.
Detection is not prevention, so the app and the README both now say to quiet
the link first with gc-testlink.sh, which sets a static address and takes the
interface out of NetworkManager -- stopping the DHCP client whose 342-byte
broadcasts are the main offender.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>