FelipeMdeO opened a new pull request, #20167:
URL: https://github.com/apache/nuttx/pull/20167
## Summary
`openeth_receive()` (`arch/xtensa/src/common/espressif/esp_openeth.c`)
tracks the next RX descriptor to read in `priv->cur_rx_desc`, an `int`
initialized to 0 exactly once, in `esp_openeth_initialize()`. QEMU's `esp32s3`
machine models the OpenCores MAC's DMA ring pointer as resetting to descriptor
0 every time `RXEN` toggles off and back on
(`openeth_disable()`/`openeth_enable()`, called from `ifdown()`/`ifup()`), but
the driver's own index is never rewound to match.
The first bring-up happens to have both at 0, so nothing looks wrong. After
the first `ifdown()`/`ifup()` cycle they permanently disagree:
`openeth_receive()` keeps inspecting the wrong descriptor, finds it still
marked `e=1` ("owned by HW"), and silently drops every subsequent RX
notification. Since ARP replies and ICMP echo replies are RX frames like any
other, this breaks **all** inbound traffic on the interface after the first
`ifup()`, not just application sockets — `ping` fails identically to a TCP
`connect()`.
Fix: re-run the same descriptor initialization `esp_openeth_initialize()`
does at boot — re-arm every RX/TX descriptor, rewind
`cur_rx_desc`/`cur_tx_desc` to 0 — inside `openeth_ifup()`, under the same
critical section that already toggles `RXEN`.
Board-independent code, and `open_eth` only exists as a QEMU peripheral, so
there is no real-hardware regression risk. Builds on #20156 (which enabled the
RX interrupt in the first place — this bug was unreachable via interrupts
before that fix landed).
## Impact
Fixes network RX on the `esp32s3` QEMU machine (`open_eth` NIC) for any
workload that brings the interface down and back up more than once (a NIC
power-cycle pattern — e.g. anything that manages a radio's on/off state between
periodic transmissions). No impact on real hardware, since this code path is
QEMU-only.
## Testing
Reproduced with an out-of-tree NuttX application that cycles the interface
up/down between periodic MQTT publish windows under QEMU. Before the fix: the
first window always connects; every window after it fails with `ENETUNREACH` —
both the app's own TCP `connect()` and a plain `ping 10.0.2.2` issued manually
from NSH right after a failure fail identically, confirming the break is
general RX, not specific to one socket/protocol. Inspecting the kernel's ARP
table via GDB at the moment of failure showed a fresh, correctly-timestamped
*negative* entry (all-zero MAC) for the broker's address — proof that a real
ARP request was sent and genuinely got no reply, not that a stale cache entry
was blocking a retry.
Same firmware image, rebuilt only toggling this diff. Six parallel QEMU
instances, ~480s each: 0 connect failures across dozens of completed publish
windows (was ~0% success on window 2+ before the fix). `tools/checkpatch.sh -c
-u -m -g` passes clean.
Sample log lines before the fix (window 2, ~90s after window 1 succeeded):
```
[146.880000] ... c=T3_TX op=CONNECT err=-101 | arp_prewarm sendto ret=-1
[158.050000] ... c=T3_TX op=CONNECT err=-101 | cannot connect to
10.0.2.2:1883
```
and after (window 2, same test):
```
[132.800000] ... c=T3_TX op=CONNECT err=0 | connected to 10.0.2.2:1883
[138.820000] ... c=T3_TX op=STOP err=0 | window closed: 27 published, 27
deleted
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]