FelipeMdeO commented on issue #19137:
URL: https://github.com/apache/nuttx/issues/19137#issuecomment-5308628794

   Hello @Vajnar ,
   
   I have been tracking this for about a week, running the investigation with 
Claude Code (Anthropic Claude Opus 5, model id `claude-opus-5`) driving the 
builds, the bench automation and the log analysis. Below is where it ended up.
   
   ## Environment
   
   ESP32-C6 (QFN40) rev v0.1 devkit, flashed and monitored through the devkit's 
UART bridge, running @Vajnar's own `examples/broken-network` and his 
`esp32c6-devkitc:broken-network` defconfig unmodified, on NuttX master 
(`2b5509e48a` for the final runs) with nuttx-apps master. The Wi-Fi client is a 
Linux laptop (Ubuntu 24.04) associating to the board's SoftAP on `wlo1`, with 
its internet on ethernet so the Wi-Fi interface stays dedicated to the AP; it 
runs the unmodified `client.c` from the same example, the same 3-byte ping-pong 
every 2 s.
   
   The control is an ESP-IDF v6.0.1 application I wrote to match the NuttX side 
field by field: same board, same channel, same router/client, same 
`wifi_init_config_t` (all 25 fields), same AP `wifi_config_t` (SSID, 
WPA2-PSK/CCMP, PMF required, channel, max connections, beacon interval), 
`WIFI_PS_NONE`, the same mode sequence NuttX uses (NULL → STA → start → APSTA → 
start), and the same 10.0.0.x addressing. Only the RTOS and network stack 
differ.
   
   ## What happens
   
   With the stock defaults the board's station interface gets `NETINIT_IPADDR` 
= 10.0.0.2/24 while the SoftAP gets `NETUTILS_DHCPD_ROUTERIP` = 10.0.0.1/24, so 
**two interfaces sit on 10.0.0.0/24**, and the AP's DHCP server hands 10.0.0.2 
— the station interface's own address — to the client.
   
   Every `NET_ARP_MAXAGE` the ARP entry for the client expires. `arp_find()` 
then falls back to `netdev_foreach(arp_match, ...)`, which matches on IP only, 
without regard for the interface the frame is going out on, and returns the 
**station** interface's MAC. The SoftAP transmits to a MAC that is not an 
associated station, so the driver answers `ESP_ERR_WIFI_NOT_ASSOC` and you get 
`netdev_upper_txpoll: ERROR: Transmit failed: -1`. It recovers on its own in 
21-80 s once incoming traffic relearns the entry, then repeats.
   
   Measurements:
   
   - 17 outages in a 6 h run, one per cycle, no exceptions.
   - The period follows the ARP timer exactly: `NET_ARP_MAXAGE=120` (1200 s) → 
outages every 1233-1259 s; `NET_ARP_MAXAGE=30` (300 s) → every 319-359 s.
   - The failing frame was captured: `dst=f0:f5:bd:03:06:c8 
src=f0:f5:bd:03:06:c9`, where `...c8` is the board's own station interface and 
`...c9` is its SoftAP. The client is `3c:21:9c:93:dc:1c`.
   - Same binary, only the station address moved to another subnet: **0 outages 
in 118 min** vs **5 outages in 118 min** with the default.
   - A SoftAP-only build never fails — there is no second interface to collide 
with.
   
   ## This looks like a NuttX network stack issue
   
   The ESP-IDF control was run with the **same hardware, same router and 
client, same Wi-Fi configuration and the same overlapping-subnet topology** — 
station netif pinned to 10.0.0.2/24, AP on 10.0.0.1/24, client leased 10.0.0.2. 
It ran **40 min / 1185 exchanges / 0 outages / 0 errors**. lwIP's `ARP_MAXAGE` 
is 300 s, so its ARP entries aged roughly eight times during that run — the 
very event that triggers the failure on NuttX every single time.
   
   So this is not the Wi-Fi blob, not the silicon, and not "a topology no stack 
can handle": a reference stack on the same chip handles it. Two interfaces 
sharing a prefix is unusual, but it is legitimate, and NuttX resolves the peer 
to the wrong interface's MAC where lwIP does not.
   
   One warning for anyone who tries the obvious fix. Restricting `arp_match()` 
to the transmitting device does remove the wrong-MAC shortcut, but with the 
subnet overlap still in place the resolution then never converges, the entry is 
marked unreachable and `arp_out()` starts dropping everything with 
`-ENETUNREACH`. In an A/B run that turned a self-healing 80 s outage into a 
**permanent** loss of connectivity (42639 consecutive errors, no recovery). 
Moving only the DHCP pool off 10.0.0.2 while leaving both interfaces on 
10.0.0.0/24 fails the same way, even faster. I am not proposing either.
   
   ## Workaround
   
   Until the stack side is addressed, keeping the station and the SoftAP on 
different prefixes avoids it entirely. @Vajnar, your defconfig sets neither 
`NETINIT_IPADDR` nor `NETUTILS_DHCPD_*`, so you inherit both defaults and land 
exactly on the collision — a single `ifconfig wlan0 <addr on another subnet>` 
before bringing up `wlan1` is enough to confirm it on your setup.
   
   As a default-level workaround I pushed a branch that moves the dhcpd pool to 
192.168.4.0/24, the subnet ESP-IDF uses for SoftAP, so the shipped defaults no 
longer create the overlap:
   
   
https://github.com/FelipeMdeO/nuttx-apps/tree/fix/dhcpd-startip-default-collision
   
   An A/B on the same board and config gave 6 outages in 39 min on master 
versus 0 outages in 40 min with it. I have not opened a PR: it changes a 
long-standing default that 25 in-tree defconfigs inherit and that several board 
documents reference, and more importantly it only hides the trap rather than 
fixing the resolution behaviour. Happy to send it if maintainers think the 
default change is worth it on its own, but the stack question is the one that 
matters here.
   
   ## Next Steps
    - I will keeping trying, but I have an environment limitation, I only can 
"manipulate" my home's wifi late night, so... you know...
   
   @acassis , please, can focus in "This looks like a NuttX network stack 
issue"  section and ping anyone with network stack background?
   
   


-- 
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]

Reply via email to