FelipeMdeO opened a new pull request, #19872:
URL: https://github.com/apache/nuttx/pull/19872

   ## Summary
   
   Two independent defects in `net/arp` that together make a peer periodically
   unreachable when two network interfaces share an IPv4 subnet. Both are 
needed:
   fixing either one alone produces a worse result than the bug, which is why 
they
   are submitted together as separate commits.
   
   **1. `arp_find()` can answer with another interface's MAC.**
   The ARP table itself is keyed by `(device, address)`, but on a cache miss
   `arp_find()` falls back to `netdev_foreach(arp_match, ...)`, and 
`arp_match()`
   compares only the IP address. Any interface holding that address wins and its
   MAC is returned, regardless of the device the frame is going out on. A frame
   transmitted on interface A can therefore be addressed to the MAC of 
interface B.
   Note the asymmetry with route selection, which already filters on
   `IFF_IS_RUNNING` (`netdev_prefixlen_findby_lipv4addr()`).
   
   **2. `arp_send()` leaks `dev->d_lock`.**
   The `-EINPROGRESS` branch does `goto wait`, jumping over the 
`netdev_unlock(dev)`
   further down, and `arp_wait()` does not release the lock either. The caller
   therefore sleeps holding `d_lock`, while `netdev_upper_rxpoll_work()` needs 
that
   same lock to dispatch incoming frames — so the ARP reply being waited for can
   never reach `arp_input()`. Because `d_lock` is recursive, retries re-acquire 
it
   and the recursion depth is never unwound, so the interface stays blocked.
   
   Defect 2 is normally invisible: the wrong-MAC shortcut of defect 1 keeps the 
code
   from ever reaching real ARP resolution. Remove the shortcut without fixing 
the
   lock and a self-healing outage becomes a permanent loss of connectivity.
   
   ## Impact
   
   Any configuration with two Ethernet or 802.11 interfaces on the same IPv4
   subnet. It is easy to reach with stock defaults: on an ESP32 SoftAP + station
   build, `netinit` assigns `NETINIT_IPADDR` (10.0.0.2/24) to the station while
   `dhcpd_start` puts the SoftAP on `NETUTILS_DHCPD_ROUTERIP` (10.0.0.1/24), and
   the DHCP pool then leases 10.0.0.2 to the first client.
   
   Observed symptom, reported in #19137: the SoftAP stops reaching its 
associated
   station every `NET_ARP_MAXAGE` (20 minutes with the default), for 21-80 s, 
then
   recovers on its own and repeats. During an outage the driver rejects each
   transmit with `ESP_ERR_WIFI_NOT_ASSOC` and the stack logs
   `netdev_upper_txpoll: ERROR: Transmit failed: -1`, because the destination 
MAC
   on the frame is the board's own station interface.
   
   This is expected to resolve #19137. The failure was reproduced, root-caused 
and
   fixed on an ESP32-C6 with the reporter's own defconfig and test application, 
but
   confirmation on the reporter's setup is still pending, so the issue is not
   closed by this PR.
   
   The lock leak is not specific to that topology: any caller reaching the
   `-EINPROGRESS` path can block the interface.
   
   ## Testing
   
   ESP32-C6 devkit, NuttX master with `esp32c6-devkitc` and the reporter's
   `examples/broken-network` (a TCP ping-pong every 2 s from a Linux client
   associated to the board's SoftAP). `CONFIG_NET_ARP_MAXAGE=30` shortens the
   reproduction from ~21 min to ~6 min. 40-minute arms, same board, same client,
   same configuration:
   
   | Build | Outages | Errors |
   |---|---|---|
   | master | 6 | 0 |
   | commit 2 only (scoping) | — | 42639 `ENETUNREACH`, permanent |
   | commit 1 only (lock) | 6 (same as master, still self-healing) | 0 |
   | **both commits** | **0** | **0** |
   | station and AP on different subnets (control) | 0 | 0 |
   
   The lock-only arm reproduces master exactly — same six outages, same 40.5 / 
79 s
   durations, same ~330-360 s intervals — which is what shows the two defects 
are
   independent and that each commit stands on its own.
   
   Supporting measurements on master:
   
   - 17 outages in a 6 h run, one per ARP aging cycle, no exceptions.
   - The period follows the timer: `NET_ARP_MAXAGE=120` (1200 s) gives outages 
every
     1233-1259 s; `=30` (300 s) gives every 319-359 s.
   - The failing frame was captured: destination MAC is the board's own station
     interface, source is the SoftAP, while the client holds a different MAC.
   - Same binary, station moved to another subnet: 0 outages in 118 min, versus 
5 in
     118 min with the overlapping default.
   
   As a cross-check that this is a stack issue rather than an invalid topology, 
an
   ESP-IDF application matching the NuttX side field by field (same board, 
channel,
   client, Wi-Fi init and AP config, power save, and the same overlapping-subnet
   addressing) ran 40 min with 0 outages. lwIP scopes ARP entries by netif and 
has
   no local-address shortcut.
   
   `tools/checkpatch.sh -m -g` passes on both commits.
   
   The branch as submitted, built on `ff6597806d`, was re-run through the same
   40-minute arm: 1169 exchanges, 0 outages, 0 errors, 6.7 ARP aging cycles.
   


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