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]